Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1294091
  • 博文数量: 175
  • 博客积分: 2743
  • 博客等级: 少校
  • 技术积分: 4024
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-30 01:41
文章分类

全部博文(175)

文章存档

2015年(1)

2013年(53)

2012年(71)

2011年(50)

分类: LINUX

2013-04-17 11:06:29

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

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

源码分析如下:


点击(此处)折叠或打开

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

  140. }

  141. /*
  142.  * Ok, this is the main fork-routine.
  143.  *
  144.  * It copies the process, and if successful kick-starts
  145.  * it and waits for it to finish using the VM if required.
  146.  */
  147.   /*这部分代码是在2.6.38中实现的*/
  148. /*参数clone_flags由两部分组成,最低的一个字节为信号掩码,用于指定子进程退出时
  149. *子进程向父进程发出的信号,通过sys_fork和sys_vfork知道它们的信号就是SIGCHLD,而
  150. *clone由用户自己决定。对于第二部分表示资源和特性标志位,fork为0,vfork为CLONE_VFORK和CLONE_VM
  151. *而clone由用户自己定义。
  152. */
  153. long do_fork(unsigned long clone_flags,
  154.      unsigned long stack_start,
  155.      struct pt_regs *regs,
  156.      unsigned long stack_size,
  157.      int __user *parent_tidptr,
  158.      int __user *child_tidptr)
  159. {
  160.     /*定义一个进程描述符*/
  161.     struct task_struct *p;
  162.     int trace = 0;
  163.     long nr;//子进程号

  164.     /*
  165.      * Do some preliminary argument and permissions checking before we
  166.      * actually start allocating stuff
  167.      */
  168.     /*
  169.     *一些必要的检查工作,我们会发现在sys_fork,sys_vfork,kernel_thread中都没有传递CLONE_NEWUSER可见
  170.     *以下这些代码没有执行,这个检查主要是为sys_clone使用的。
  171.     */
  172.     if (clone_flags & CLONE_NEWUSER) {
  173.         if (clone_flags & CLONE_THREAD)//跟踪标志被设置,出错。
  174.             return -EINVAL;
  175.         /* hopefully this check will go away when userns support is
  176.          * complete
  177.          */
  178.         if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SETUID) ||
  179.                 !capable(CAP_SETGID))
  180.             return -EPERM;
  181.     }

  182.     /*
  183.      * We hope to recycle these flags after 2.6.26
  184.      */
  185.      /*这些代码也是就一些检查工作*/
  186.     if (unlikely(clone_flags & CLONE_STOPPED)) {
  187.         static int __read_mostly count = 100;

  188.         if (count > 0 && printk_ratelimit()) {
  189.             char comm[TASK_COMM_LEN];

  190.             count--;
  191.             printk(KERN_INFO "fork(): process `%s' used deprecated "
  192.                     "clone flags 0x%lx\n",
  193.                 get_task_comm(comm, current),
  194.                 clone_flags & CLONE_STOPPED);
  195.         }
  196.     }

  197.     /*
  198.      * When called from kernel_thread, don't do user tracing stuff.
  199.      */
  200.     if (likely(user_mode(regs)))
  201.         trace = tracehook_prepare_clone(clone_flags);

  202.     /*copy_process来完成具体进程的创建,在系统资源丰富的条件下,来完成进程描述符的拷贝,当然进程号不同*/
  203.     p = copy_process(clone_flags, stack_start, regs, stack_size,
  204.              child_tidptr, NULL, trace);
  205.     /*
  206.     *调用完copy_process后如果没有指定CLONE_STOPPED就会调用下面的wake_up_new_task把新建的进程放到
  207.     *运行队列中。如果父子进程在同一个cpu中运行,且在没有设置CLONE_VM标志,则会采用写实复制技术,把子进程放到
  208.     *父进程的前面,如果子进程调用了exec就会避免一系列不必要的复制操作。
  209.     */
  210.     /*
  211.      * Do this prior waking up the new thread - the thread pointer
  212.      * might get invalid after that point, if the thread exits quickly.
  213.      */
  214.      /*IS_ERR()判断p是否正确*/
  215.     if (!IS_ERR(p)) {
  216.         /*进程描述符创建成功后,根据clone_flags来设置进程状态*/
  217.         struct completion vfork;

  218.         trace_sched_process_fork(current, p);

  219.         nr = task_pid_vnr(p);
  220.         
  221.         /*
  222.         *在sys_fork,sys_vfork,kernel_thread中没有CLONE_PARENT_SETTID且parent_tidptr=NULL
  223.         *为sys_clone使用
  224.         */
  225.         if (clone_flags & CLONE_PARENT_SETTID)
  226.             put_user(nr, parent_tidptr);

  227.         /*
  228.         *sys_fork 或 sys_clone检查的,如果设置了就把父进程放进等待队列中
  229.         */
  230.         if (clone_flags & CLONE_VFORK) {
  231.             p->vfork_done = &vfork;
  232.             init_completion(&vfork);
  233.         }

  234.         audit_finish_fork(p);
  235.         tracehook_report_clone(regs, clone_flags, nr, p);

  236.         /*
  237.          * We set PF_STARTING at creation in case tracing wants to
  238.          * use this to distinguish a fully live task from one that
  239.          * hasn't gotten to tracehook_report_clone() yet. Now we
  240.          * clear it and set the child going.
  241.          */
  242.         p->flags &= ~PF_STARTING;

  243.         if (unlikely(clone_flags & CLONE_STOPPED)) {
  244.             /*
  245.              * We'll start up with an immediate SIGSTOP.
  246.              */
  247.             sigaddset(&p->pending.signal, SIGSTOP);
  248.             set_tsk_thread_flag(p, TIF_SIGPENDING);
  249.             __set_task_state(p, TASK_STOPPED);
  250.         } else {
  251.             wake_up_new_task(p, clone_flags);
  252.         }

  253.         tracehook_report_clone_complete(trace, regs,
  254.                         clone_flags, nr, p);

  255.         if (clone_flags & CLONE_VFORK) {
  256.             freezer_do_not_count();
  257.             wait_for_completion(&vfork);//等待队列
  258.             freezer_count();
  259.             tracehook_report_vfork_done(p, nr);
  260.         }
  261.     } else {
  262.         nr = PTR_ERR(p);
  263.     }
  264.     return nr;
  265. }


阅读(1458) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~