+ -

fork, vfork, clone,pthread_create,kernel_thread

时间:2010-03-08

来源:sandflee

在手机上看
手机扫描阅读
fork, vfork, clone,pthread_create,kernel_thread 
fork,vfork,clone,都是系统调用,以前还以为是前面两个是clone的封装,实际上前三个都是系统调用,pthread_create是对clone的封装,kernel_thread用于创建内核线程 fork 在内核中调用 do_fork(SIGCHLD, regs.esp, &regs, 0, NULL, NULL)
vfork: do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, &regs, 0, NULL, NULL)
clone: do_fork(clone_flags, newsp, &regs, 0, parent_tidptr, child_tidptr) 其中 clone_flags = regs.ebx; newsp = regs.ecx; parent_tidptr = (int __user *)regs.edx; child_tidptr = (int __user *)regs.edi;
pthread_create:  pid = __clone(__pthread_manager_event, (void **) __pthread_manager_thread_tos, CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, (void *)(long)manager_pipe[0]);    kernel_thread: do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL) 在执行这个函数之前,在栈中对regs作了初始化,把自己的参数塞进起,并设regs.eip=kernel_thread_helper,具体流程参见前一篇文章。 可见他们的不同主要在于flag的不同,为什么前两个都有SIGCHLD,把保护用户态寄存器的地址传递是为什么?进程的到底是怎么切换的? 先看do_fork,首先分配一个PID,调用copy_process()进行具体的拷贝,如果flag里有CLONE_VFORK,将父进程放入一个等待队列,所以子进程先运行。
copy_process() This creates a new process as a copy of the old one, but does not actually start it yet.It copies the registers, and all the appropriate parts of the process environment. p = dup_task_struct(current);   为子进程分配task_struct和内核stack. 然后copy_files(),copy_fs()进行拷贝。 copy_thread,把用户传进来的通用寄存器进行拷贝给子进程并设置,这儿很关键
childregs = task_pt_regs(p); *childregs = *regs; childregs->eax = 0; childregs->esp = esp;
p->thread.esp = (unsigned long) childregs; p->thread.esp0 = (unsigned long) (childregs+1);
p->thread.eip = (unsigned long) ret_from_fork; 可见传入的用户态通用寄存器附给了子进程,并置eax=0所以返回的pid是0,估计是pt_regs里没有esp,所以单独赋值了。task_struct的thread字段记录了进程特定于cpu的信息,但切换到子进程的时候,就把thread中esp,eip弹出,所以子进程就可以通过ret_from_fork返回运行了。 而ret_from_fork asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); 不明白。 至于前面说道的SIGCHLD,估计是设置子进程挂了的时候给父进程发个SIGCHLD信号。也没看到在哪儿设。 所谓创建一个进程,就是创建task_struct和内核stack,并把stack里的pt_regs设置下,返回的时候好恢复到调用点,并选择性的继承父进程的资源。

热门下载

更多