窺探 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. }  





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