Je regardais la fonction _do_fork()
() essayant de comprendre comment fork()
retourne le PID enfant pour le processus parent et 0 sur le processus de l'enfant.Comment _do_fork() peut renvoyer deux PID différents (un pour le processus parent et un pour le processus enfant)
Je pense que nr
contient le PID du processus enfant (qui sera retourné au processus appelant), mais je ne vois pas comment il est capable de retourner 0 au processus enfant.
La réponse How does fork() know when to return 0? dit que la valeur de retour est passé sur la pile créé pour le nouveau processus, mais (en plus pas vraiment comprendre) Je ne peux pas trouver que dans le code.
Alors, où la valeur de retour de 0 est définie pour le processus enfant?
Le code de la fonction _do_fork()
est recopié ci-dessous:
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;
}
Vous voulez comprendre le code de Linux, Certaines personnes ont essayé mais ils ont eu des problèmes. – Stargateur