进程控制块:
struct proc_struct {
enum proc_state state; // Process state
int pid; // Process ID
int runs; // the running times of Proces
uintptr_t kstack; // Process kernel stack
volatile bool need_resched; // bool value: need to be rescheduled to release CPU?
struct proc_struct *parent; // the parent process
struct mm_struct *mm; // Process's memory management field
struct context context; // Switch here to run process
struct trapframe *tf; // Trap frame for current interrupt
uintptr_t cr3; // CR3 register: the base addr of Page Directroy Table(PDT)
uint32_t flags; // Process flag
char name[PROC_NAME_LEN + 1]; // Process name
list_entry_t list_link; // Process link list
list_entry_t hash_link; // Process hash list
};
其中的context保存当前进程执行的上下文:
struct context {
uint32_t eip;
uint32_t esp;
uint32_t ebx;
uint32_t ecx;
uint32_t edx;
uint32_t esi;
uint32_t edi;
uint32_t ebp;
};
当前的进程current,即将要切换的进程next;
.text
.globl switch_to
switch_to: # switch_to(from, to)
# save from's registers;ESP
movl 4(%esp), %eax # eax points to from
popl 0(%eax) # save eip !popl
movl %esp, 4(%eax)
movl %ebx, 8(%eax)
movl %ecx, 12(%eax)
movl %edx, 16(%eax)
movl %esi, 20(%eax)
movl %edi, 24(%eax)
movl %ebp, 28(%eax)
# restore to's registers
movl 4(%esp), %eax # not 8(%esp): popped return address already
# eax now points to to
movl 28(%eax), %ebp
movl 24(%eax), %edi
movl 20(%eax), %esi
movl 16(%eax), %edx
movl 12(%eax), %ecx
movl 8(%eax), %ebx
movl 4(%eax), %esp
pushl 0(%eax) # push eip
ret
上面的汇编代码是 switch_to 函数的函数体,
前半部分是保存当前的各种普通寄存器的值到进程的context 结构体中
后半部分是把即将要切换到进程的context恢复到寄存器中,并修改了函数的返回地址;返回地址是forkret
forkret(void) {
forkrets(current->tf);
}
其中forkrets
:
forkrets:
# set stack to this new process's trapframe
movl 4(%esp), %esp
jmp __trapret
current
已经被修改成即将要执行的进程;
kernel_thread(int (*fn)(void *), void *arg, uint32_t clone_flags) {
struct trapframe tf;
memset(&tf, 0, sizeof(struct trapframe));
//设置中断帧,
tf.tf_cs = KERNEL_CS;
tf.tf_ds = tf.tf_es = tf.tf_ss = KERNEL_DS;
tf.tf_regs.reg_ebx = (uint32_t)fn;
tf.tf_regs.reg_edx = (uint32_t)arg;
tf.tf_eip = (uint32_t)kernel_thread_entry;
return do_fork(clone_flags | CLONE_VM, 0, &tf);
}
kernel_thread
中已经设置好了trap_frame;以中断返回的形式切换执行流,开始执行eip指向的kernel_thread_entry
,:
.globl kernel_thread_entry
kernel_thread_entry: # void kernel_thread(void)
pushl %edx # push arg
call *%ebx # call fn ,ebx存放的是一个函数地址,函数参数存放在了edx 中,
pushl %eax # save the return value of fn(arg)
call do_exit # call do_exit to terminate current thread
网友评论