读核日记fork

  1. 作者:handi
  2. 星期四, 十月 28, 2004
  3. 读核日记fork上篇
  4. 中间会参考到一些资料和文章,我也会在日记头一一列出
  5. 1. lion's unix 源代码分析
  6. 2. kernel 2.6.8 /kernel/fork.c
  7. 3. kernel 2.4.18 /kernel/fork.c
  8. 4. linux情景分析(上、下)
  9. 基本上没有找到以fork命名的函数,而且还符合
  10. match case and match whold word only
  11. 于是sys_fork --> do_fork,就像socket一样只有sys_socket
  12. 至于为什么系统调用的时候是fork()和socket(),我想可能是函数map的
  13. 原因吧
  14. 先说大体流程,之后再解说代码
  15. first,检查一些状态,获取一些必要的信息
  16. --> 进入copy_process实体,复制进程(中间有一个很重要的一点,就是
  17. 为什么子进程返回值是0)
  18. --> 设置一些信息
  19. --> 让进程开始run
  20. 比较于unix的实现,我只能说linux真复杂和罗嗦,lion's unix
  21. 中的实现很简单清晰,如果只是要了解原理的,那份fork就足够了,而且
  22. 很老实的,没有sys_fork, v_fork, do_fork之类的嵌套,就一个fork
  23. 当然不清楚目前unix的版本中这是怎样实现的,所以过些天会找些minix
  24. 或bsd中实现的代码来参考,然后补充到日记中来
  25. 前面罗嗦了这么多,还是来分析一下源代码吧.
  26. /kernel/fork.c
  27. kernel_thread(),sys_fork(),sys_clone(),sys_vfork()
  28. 这几个函数都是调用do_fork()函数,主要参数区别都是集中在
  29. clone_flags上面,在/arch/i386/kernel/process.c
  30. /*
  31.  *  Ok, this is the main fork-routine.
  32.  *
  33.  * It copies the process, and if successful kick-starts
  34.  * it and waits for it to finish using the VM if required.
  35.  */
  36. long do_fork(unsigned long clone_flags,         /* 克隆标识 */
  37.        unsigned long stack_start,        /* 栈起始位置 - 怎么不用指针? */
  38.        struct pt_regs *regs,             /* 寄存器 */
  39.        unsigned long stack_size,         /* 栈大小 */
  40.        int __user *parent_tidptr,        /* 父进程的什么指针 */
  41.        int __user *child_tidptr)         /* 子进程的什么指针, 这两个指针用来指什么? */
  42. {
  43.  struct task_struct *p;  /* PCB结构 */
  44.  int trace = 0;
  45.  long pid;
  46.         /* CLONE_PTRACE 这个宏表示什么意思[set if we want to let tracing continue on the child too]
  47.          * 翻译过来的意思是如果想跟踪子进程的信息,就设置这一位
  48.          * 是否跟踪由do_fork的参数clone_flags确定的 
  49.          * 也就是说是否跟踪子进程的信息是由我们在调用的时候确定 */
  50.         /* current这个是指当前的父进程吗? 
  51.          * unlikely原型:
  52.          * #include <linux/compiler.h> */
  53.  if (unlikely(current->ptrace)) 
  54. {/* unlikely(x),对x两次取反,具体实现取决于gcc的版本,gcc 2.9.6是界点,其实就是 取x的值 */
  55.   trace = fork_traceflag (clone_flags);/* fork_traceflag inline在文件fork.c中,2.4.18版本没有独立出去 */
  56.   if (trace)
  57.    clone_flags |= CLONE_PTRACE;
  58.  }
  59.         /* 检查clone_flags,创建一个新的进程,拷贝由clone_flags指定的信息,但新进程不运行 */
  60.  p = copy_process(clone_flags, stack_start, regs, stack_size, parent_tidptr, child_tidptr);
  61.         /*
  62.   * Do this prior waking up the new thread - the thread pointer
  63.   * might get invalid after that point, if the thread exits quickly.
  64.   */
  65.  pid = IS_ERR(p) ? PTR_ERR(p) : p->pid;
  66.         /* 进程复制成功 */
  67.  if (!IS_ERR(p)) 
  68. {
  69.   struct completion vfork;
  70.   if (clone_flags & CLONE_VFORK) 
  71. {
  72.    p->vfork_done = &vfork;
  73.    init_completion(&vfork);
  74.   }
  75.   if ((p->ptrace & PT_PTRACED) || (clone_flags & CLONE_STOPPED)) 
  76. {
  77.    /*
  78.     * We'll start up with an immediate SIGSTOP.
  79.     */
  80.    sigaddset(&p->pending.signal, SIGSTOP);
  81.    set_tsk_thread_flag(p, TIF_SIGPENDING);
  82.   }
  83.   if (!(clone_flags & CLONE_STOPPED)) 
  84. {
  85.    /*
  86.     * Do the wakeup last. On SMP we treat fork() and
  87.     * CLONE_VM separately, because fork() has already
  88.     * created cache footprint on this CPU (due to
  89.     * copying the pagetables), hence migration would
  90.     * probably be costy. Threads on the other hand
  91.     * have less traction to the current CPU, and if
  92.     * there's an imbalance then the scheduler can
  93.     * migrate this fresh thread now, before it
  94.     * accumulates a larger cache footprint:
  95.     */
  96.    /* 唤醒新fork的进程 */
  97.    if (clone_flags & CLONE_VM)
  98.     wake_up_forked_thread(p);
  99.    else
  100.     wake_up_forked_process(p);
  101.   } 
  102. else 
  103. {
  104.    int cpu = get_cpu();
  105.    p->state = TASK_STOPPED;
  106.    if (cpu_is_offline(task_cpu(p)))
  107.     set_task_cpu(p, cpu);
  108.    put_cpu();
  109.   }
  110.   ++total_forks;
  111.   if (unlikely (trace)) 
  112. {
  113.    current->ptrace_message = pid;
  114.    ptrace_notify ((trace << 8) | SIGTRAP);
  115. }
  116.   if (clone_flags & CLONE_VFORK) 
  117. {
  118.    wait_for_completion(&vfork);
  119.    if (unlikely (current->ptrace & PT_TRACE_VFORK_DONE))
  120.     ptrace_notify ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP);
  121. else
  122.    /*
  123.     * Let the child process run first, to avoid most of the
  124.     * COW overhead when the child exec()s afterwards.
  125.     */
  126.    /* 让fork的子进程先运行 */
  127.    set_need_resched();
  128.  }
  129.  return pid;
  130. }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值