2017-06-27 47 views
8

Tôi đã xem hàm _do_fork()() cố gắng hiểu cách fork() trả về PID con cho quá trình cha và 0 trên quá trình con.Làm thế nào có thể _do_fork() trả về hai PID khác nhau (một cho quá trình cha và một cho quá trình con)

Tôi nghĩ rằng nr chứa PID của quá trình con (sẽ được trả lại cho quá trình người gọi), nhưng tôi không thể thấy cách nó có thể trả về 0 cho quá trình con.

Câu trả lời How does fork() know when to return 0? cho biết giá trị trả lại được chuyển vào ngăn xếp được tạo cho quy trình mới, nhưng (ngoài việc không thực sự hiểu) Tôi không thể tìm thấy mã đó trong mã.

Vì vậy, trong đó giá trị trả về 0 được đặt cho quy trình con?

Mã của _do_fork() chức năng được sao chép dưới đây:

long _do_fork(unsigned long clone_flags, 
      unsigned long stack_start, 
      unsigned long stack_size, 
      int __user *parent_tidptr, 
      int __user *child_tidptr, 
      unsigned long tls) 
{ 
    struct task_struct *p; 
    int trace = 0; 
    long nr; 

    /* 
    * Determine whether and which event to report to ptracer. When 
    * called from kernel_thread or CLONE_UNTRACED is explicitly 
    * requested, no event is reported; otherwise, report if the event 
    * for the type of forking is enabled. 
    */ 
    if (!(clone_flags & CLONE_UNTRACED)) { 
     if (clone_flags & CLONE_VFORK) 
      trace = PTRACE_EVENT_VFORK; 
     else if ((clone_flags & CSIGNAL) != SIGCHLD) 
      trace = PTRACE_EVENT_CLONE; 
     else 
      trace = PTRACE_EVENT_FORK; 

     if (likely(!ptrace_event_enabled(current, trace))) 
      trace = 0; 
    } 

    p = copy_process(clone_flags, stack_start, stack_size, 
      child_tidptr, NULL, trace, tls, NUMA_NO_NODE); 
    add_latent_entropy(); 
    /* 
    * Do this prior waking up the new thread - the thread pointer 
    * might get invalid after that point, if the thread exits quickly. 
    */ 
    if (!IS_ERR(p)) { 
     struct completion vfork; 
     struct pid *pid; 

     trace_sched_process_fork(current, p); 

     pid = get_task_pid(p, PIDTYPE_PID); 
     nr = pid_vnr(pid); 

     if (clone_flags & CLONE_PARENT_SETTID) 
      put_user(nr, parent_tidptr); 

     if (clone_flags & CLONE_VFORK) { 
      p->vfork_done = &vfork; 
      init_completion(&vfork); 
      get_task_struct(p); 
     } 

     wake_up_new_task(p); 

     /* forking complete and child started to run, tell ptracer */ 
     if (unlikely(trace)) 
      ptrace_event_pid(trace, pid); 

     if (clone_flags & CLONE_VFORK) { 
      if (!wait_for_vfork_done(p, &vfork)) 
       ptrace_event_pid(PTRACE_EVENT_VFORK_DONE, pid); 
     } 

     put_pid(pid); 
    } else { 
     nr = PTR_ERR(p); 
    } 
    return nr; 
} 
+3

Bạn muốn hiểu mã của Linux, Một số người đã thử nhưng họ gặp sự cố. – Stargateur

Trả lời

9

Bạn đã xác định được một cách chính xác như thế nào quá trình id mới được trả lại cho phụ huynh, với return nr. Nhưng bạn sẽ không bao giờ thực sự nhìn thấy một return 0 bất cứ nơi nào kể từ khi mã này được thực thi trên chuỗi phụ huynh. Mã này không dành cho quy trình mới được tạo.

Bây giờ, hãy kiểm tra chức năng _do_fork.

... 
} 
p = copy_process(clone_flags, stack_start, stack_size, 
     child_tidptr, NULL, trace, tls, NUMA_NO_NODE); 
add_latent_entropy(); 
... 

Đây là nơi xảy ra tất cả sự kỳ diệu. Khi bạn gọi copy_process , nội bộ gọi copy_thread là mã cụ thể cho mục tiêu. Chức năng này chịu trách nhiệm đối phó với các cấu trúc dữ liệu liên quan đến luồng.

Bây giờ, chúng ta có mục tiêu là X86_64 với quy ước gọi là giá trị trả lại được trả về trong thanh ghi %rax. Chức năng này sau đó sao chép 0 vào %rax và sao chép giá trị của return_from_fork địa chỉ đến %rip (con trỏ chỉ dẫn).

Trên các nền tảng khác, ABI có thể yêu cầu giá trị trả lại nằm trên ngăn xếp. Trong trường hợp đó, 0 được đặt trên ngăn xếp. copy_thread là mục tiêu cụ thể nhưng copy_process thì không.

This là triển khai copy_thread cho X86_64. Bạn có thể thấy xung quanh số dòng 160 thanh ghi sp được thiết lập. Và tại dòng 182, bạn có thể thấy %ax (là một subregister của% rax) được đặt thành 0.

Tôi hy vọng điều này sẽ gây nhầm lẫn.

Các vấn đề liên quan