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;
}
Bạn muốn hiểu mã của Linux, Một số người đã thử nhưng họ gặp sự cố. – Stargateur