标签:
阅读理解task_struct数据结构,它包含了
进程状态、运行时间、调度信息、进程的通讯状况、task_struct型链表连接指针
、标号,决定改进程归属、可以读写打开的一些文件信息、进程上下文和内核上下文、处理器上下文、内存信息等
#include <stdio.h>#include <stdlib.h>#include <unistd.h>int main(int argc, char * argv[]){ int pid;    /* fork another process */    pid = fork();
    if (pid < 0) 
    { 
        /* error occurred */
        fprintf(stderr,"Fork Failed!");
        exit(-1);
    } 
    else if (pid == 0) 
    {
        /* child process */
        printf("This is Child Process!\n");
    } 
    else
    {  
        /* parent process  */
        printf("This is Parent Process!\n");
        /* parent will wait for the child to complete*/
        wait(NULL);
        printf("Child Complete!\n");
    }
}
ti = alloc_thread_info_node(tsk, node);tsk->stack = ti; setup_thread_stack(tsk, orig); //这里只是复制thread_info,而非复制内核堆栈*childregs = *current_pt_regs(); //复制内核堆栈 childregs->ax = 0; //为什么子进程的fork返回0,这里就是原因! p->thread.sp = (unsigned long) childregs; //调度到子进程时的内核栈顶 p->thread.ip = (unsigned long) ret_from_fork; //调度到子进程时的第一条指令地址static struct task_struct *dup_task_struct(struct task_struct *orig){  struct task_struct *tsk;struct thread_info *ti;int node = tsk_fork_get_node(orig);int err;tsk = alloc_task_struct_node(node);if (!tsk)return NULL;ti = alloc_thread_info_node(tsk, node);if (!ti) goto free_tsk;err = arch_dup_task_struct(tsk, orig);if (err) goto free_ti;tsk->stack = ti;# ifdef CONFIG_SECCOMPtsk->seccomp.filter = NULL;# endifsetup_thread_stack(tsk, orig);clear_user_return_notifier(tsk);clear_tsk_need_resched(tsk);set_task_stack_end_magic(tsk);# ifdef CONFIG_CC_STACKPROTECTORtsk->stack_canary = get_random_int();# endifatomic_set(&tsk->usage, 2);# ifdef CONFIG_BLK_DEV_IO_TRACEtsk->btrace_seq = 0;# endiftsk->splice_pipe = NULL;tsk->task_frag.page = NULL;account_kernel_stack(ti, 1);return tsk;free_ti:free_thread_info(ti);free_tsk:free_task_struct(tsk);return NULL;}
int copy_thread(unsigned long clone_flags, unsigned long sp, unsigned long arg, struct task_struct *p)
 { ... 
*childregs = *current_pt_regs();
 childregs->ax = 0; 
if (sp) childregs->sp = sp;
 p->thread.ip = (unsigned long) ret_from_fork;
 ... }
/*ret from_fork*/
ENTRY(ret_from_fork)    CFI_STARTPROC
    pushl_cfi %eax
    call schedule_tail
    GET_THREAD_INFO(%ebp)
    popl_cfi %eax
    pushl_cfi $0x0202       # Reset kernel eflags
    popfl_cfi
    jmp syscall_exit
    CFI_ENDPROC
END
小结:
(ret_from_fork)新进程是从在ret_from_fork之前,也就是在copy_thread()函数中*childregs = *current_pt_regs();该句将父进程的regs参数赋值到子进程的内核堆栈,,使子进程拥有了
SAVE ALL中压入栈的参数,故在ret from_fork时可以返回当前子进程的信息。 
标签:
原文地址:http://www.cnblogs.com/yktlll/p/5350379.html