美文网首页
分析Linux内核创建一个新进程的过程

分析Linux内核创建一个新进程的过程

作者: xiaoxii | 来源:发表于2017-04-02 20:04 被阅读0次

    .
    ret_from_fork

    分析fork函数对应的系统调用处理过程

    启动保护fork命令的menuOS

    设置断点进行调试

    进程的创建

    从了解进程的创建,进程间调度切换,来从总体把握进程工作

    当前进程复制一个子进程,然后进行修改

    fork一个子进程的代码

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    int main(int argc , char * argv[])
    {
        int pid;
        pid = fork();
        if(pid<0)
        {
            fprintf(stderr,"Fork Failed !");
            exit(-1);
        }
        else if (pid==0)
        {
            printf("This is Child Process!\n");
         }
        else
        {
            printf("This is Parent Process !\n");
            wait(NULL);
            printf("Child Complete!\n:);
        }
    
    }
    

    -fork()是用户态用于创建子进程的系统调用
    -pid<0时打印出错信息
    -子进程中fork()返回值为0,父进程中fork()返回值为进程pid值
    -所以else if和else都将被执行
    理解进程创建过程复杂代码的方法

    创建一个新进程在内核中的执行过程
    -fork、vfork和clone三个系统调用都可以创建一个新进程,而且都是通过调用do_fork来实现进程的创建
    -创建新进程是通过复制当前进程来实现
    -复制一个PCB task_struct
    -给新进程分配一个新内核堆栈
    -修改进程数据如pid、进程链表等
    -从用户态代码中可以看到fork()函数返回两次,在父进程和子进程中各返回一次,父进程从系统调用中返回,子进程从系统调用中返回涉及了子进程的内核堆栈数据状态和task_struct中thread记录的sp和ip的一致性问题,在copy_thread in copy_process里设定

    do_fork

    long do_fork(unsigned long clone_flags,
              unsigned long stack_start,
              unsigned long stack_size,
              int __user *parent_tidptr,
              int __user *child_tidptr)
    {
        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);
        /*
         * 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;
    }
    

    copy process创建进程内容
    -dup_task_struct复制pcb,分配新空间
    -然后初始化赋值子进程信息
    -copy thread从子进程pid内核堆栈位置栈底,拷贝内核堆栈数据和指定新进程的第一条指令地址

    创建的新进程从哪里开始执行

    ·p->thread.ip = (unsigned long) ret_from_fork;·
    ret_from_fork返回了子进程调度的第一条指令
    在复制内核堆栈时只复制了其中一部分SAVE_ALLL相关的部分,int指令和cpu压栈内容,即最栈底的部分
    ret_from_fork会跳转syscall exit,最终返回用户态,此时返回到子进程用户空间
    所以创建的新进程从ret_from_fork开始执行

    王潇洋
    原创作品转载请注明出处
    《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

    相关文章

      网友评论

          本文标题:分析Linux内核创建一个新进程的过程

          本文链接:https://www.haomeiwen.com/subject/yoggottx.html