窥探 kernel,just for fun --- do_fork

本系列文章由张同浩编写,转载请注明出处:http://blog.csdn.net/muge0913/article/details/7479451

邮箱:[email protected]


在上次的文章中详细的介绍了几个系统调用,它们最终都是调用了do_fork来实现进程的创建。do_fork主要完成了进程描述符的创建和pid的创建,以及进程描述符的拷贝。

本系列文章所用源码均来自2.6.38.

源码分析如下:

  1. /* 
  2.  *  Ok, this is the main fork-routine. 
  3.  * 
  4.  * It copies the process, and if successful kick-starts 
  5.  * it and waits for it to finish using the VM if required. 
  6.  */  
  7.   /*这部分代码是在2.6.38中实现的*/  
  8. /*参数clone_flags由两部分组成,最低的一个字节为信号掩码,用于指定子进程退出时 
  9. *子进程向父进程发出的信号,通过sys_fork和sys_vfork知道它们的信号就是SIGCHLD,而 
  10. *clone由用户自己决定。对于第二部分表示资源和特性标志位,fork为0,vfork为CLONE_VFORK和CLONE_VM 
  11. *而clone由用户自己定义。 
  12. */  
  13. long do_fork(unsigned long clone_flags,  
  14.           unsigned long stack_start,  
  15.           struct pt_regs *regs,  
  16.           unsigned long stack_size,  
  17.           int __user *parent_tidptr,  
  18.           int __user *child_tidptr)  
  19. {  
  20.     /*定义一个进程描述符*/  
  21.     struct task_struct *p;  
  22.     int trace = 0;  
  23.     long nr;//子进程号  
  24.   
  25.     /* 
  26.      * Do some preliminary argument and permissions checking before we 
  27.      * actually start allocating stuff 
  28.      */  
  29.     /* 
  30.     *一些必要的检查工作,我们会发现在sys_fork,sys_vfork,kernel_thread中都没有传递CLONE_NEWUSER可见 
  31.     *以下这些代码没有执行,这个检查主要是为sys_clone使用的。 
  32.     */  
  33.     if (clone_flags & CLONE_NEWUSER) {  
  34.         if (clone_flags & CLONE_THREAD)//跟踪标志被设置,出错。  
  35.             return -EINVAL;  
  36.         /* hopefully this check will go away when userns support is 
  37.          * complete 
  38.          */  
  39.         if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SETUID) ||  
  40.                 !capable(CAP_SETGID))  
  41.             return -EPERM;  
  42.     }  
  43.   
  44.     /* 
  45.      * We hope to recycle these flags after 2.6.26 
  46.      */  
  47.      /*这些代码也是就一些检查工作*/  
  48.     if (unlikely(clone_flags & CLONE_STOPPED)) {  
  49.         static int __read_mostly count = 100;  
  50.   
  51.         if (count > 0 && printk_ratelimit()) {  
  52.             char comm[TASK_COMM_LEN];  
  53.   
  54.             count--;  
  55.             printk(KERN_INFO "fork(): process `%s' used deprecated "  
  56.                     "clone flags 0x%lx\n",  
  57.                 get_task_comm(comm, current),  
  58.                 clone_flags & CLONE_STOPPED);  
  59.         }  
  60.     }  
  61.   
  62.     /* 
  63.      * When called from kernel_thread, don't do user tracing stuff. 
  64.      */  
  65.     if (likely(user_mode(regs)))  
  66.         trace = tracehook_prepare_clone(clone_flags);  
  67.   
  68.     /*copy_process来完成具体进程的创建,在系统资源丰富的条件下,来完成进程描述符的拷贝,当然进程号不同*/  
  69.     p = copy_process(clone_flags, stack_start, regs, stack_size,  
  70.              child_tidptr, NULL, trace);  
  71.     /* 
  72.     *调用完copy_process后如果没有指定CLONE_STOPPED就会调用下面的wake_up_new_task把新建的进程放到 
  73.     *运行队列中。如果父子进程在同一个cpu中运行,且在没有设置CLONE_VM标志,则会采用写实复制技术,把子进程放到 
  74.     *父进程的前面,如果子进程调用了exec就会避免一系列不必要的复制操作。 
  75.     */  
  76.     /* 
  77.      * Do this prior waking up the new thread - the thread pointer 
  78.      * might get invalid after that point, if the thread exits quickly. 
  79.      */  
  80.      /*IS_ERR()判断p是否正确*/  
  81.     if (!IS_ERR(p)) {  
  82.         /*进程描述符创建成功后,根据clone_flags来设置进程状态*/  
  83.         struct completion vfork;  
  84.   
  85.         trace_sched_process_fork(current, p);  
  86.   
  87.         nr = task_pid_vnr(p);  
  88.           
  89.         /* 
  90.         *在sys_fork,sys_vfork,kernel_thread中没有CLONE_PARENT_SETTID且parent_tidptr=NULL 
  91.         *为sys_clone使用 
  92.         */  
  93.         if (clone_flags & CLONE_PARENT_SETTID)  
  94.             put_user(nr, parent_tidptr);  
  95.   
  96.         /* 
  97.         *sys_fork 或 sys_clone检查的,如果设置了就把父进程放进等待队列中 
  98.         */  
  99.         if (clone_flags & CLONE_VFORK) {  
  100.             p->vfork_done = &vfork;  
  101.             init_completion(&vfork);  
  102.         }  
  103.   
  104.         audit_finish_fork(p);  
  105.         tracehook_report_clone(regs, clone_flags, nr, p);  
  106.   
  107.         /* 
  108.          * We set PF_STARTING at creation in case tracing wants to 
  109.          * use this to distinguish a fully live task from one that 
  110.          * hasn't gotten to tracehook_report_clone() yet.  Now we 
  111.          * clear it and set the child going. 
  112.          */  
  113.         p->flags &= ~PF_STARTING;  
  114.   
  115.         if (unlikely(clone_flags & CLONE_STOPPED)) {  
  116.             /* 
  117.              * We'll start up with an immediate SIGSTOP. 
  118.              */  
  119.             sigaddset(&p->pending.signal, SIGSTOP);  
  120.             set_tsk_thread_flag(p, TIF_SIGPENDING);  
  121.             __set_task_state(p, TASK_STOPPED);  
  122.         } else {  
  123.             wake_up_new_task(p, clone_flags);  
  124.         }  
  125.   
  126.         tracehook_report_clone_complete(trace, regs,  
  127.                         clone_flags, nr, p);  
  128.   
  129.         if (clone_flags & CLONE_VFORK) {  
  130.             freezer_do_not_count();  
  131.             wait_for_completion(&vfork);//等待队列  
  132.             freezer_count();  
  133.             tracehook_report_vfork_done(p, nr);  
  134.         }  
  135.     } else {  
  136.         nr = PTR_ERR(p);  
  137.     }  
  138.     return nr;  
  139. }  





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章