Sia padre che figlio restituiscono valori diversi a causa della manipolazione dei registri della CPU nel contesto del bambino.
Ogni processo nel kernel linux rappresentato da task_struct. task_struct è racchiuso (puntatore) nella struttura thread_info che si trova alla fine dello stack in modalità kernel. Il contesto CPU (registri) di Whole è memorizzato in questa struttura thread_info.
struct thread_info {
struct task_struct *task; /* main task structure */
struct cpu_context_save cpu_context; /* cpu context */
}
Tutte le chiamate di sistema fork/clone() chiamano la funzione kernel_fork do_fork().
long do_fork(unsigned long clone_flags,
unsigned long stack_start,
struct pt_regs *regs,
unsigned long stack_size,
int __user *parent_tidptr,
int __user *child_tidptr)
Qui è la sequenza di esecuzione
do_fork() -> copy_process-> copy_thread() (copy_thread è arco chiamata di funzione specifica)
copy_thread() copia i valori di registro dal genitore e cambia il valore restituito 0 (Nel caso del braccio)
struct pt_regs *childregs = task_pt_regs(p);
*childregs = *regs; /* Copy register value from parent process*/
childregs->ARM_r0 = 0; /*Change the return value*/
thread->cpu_context.sp = (unsigned long)childregs;/*Write back the value to thread info*/
thread->cpu_context.pc = (unsigned long)ret_from_fork;
Quando il bambino viene pianificato esegue una routine di assemblaggio ret_from_fork() che restituisce zero. Per il genitore ottiene il valore di ritorno dalla do_fork(), che è pid del processo
nr = task_pid_vnr(p);
return nr;
è più comunemente chiamato "padre" e il processo di "figlio". Le persone potrebbero accusarti di sessismo. – Thomas