Linux內核創建一個新進程的實驗

    陳鐵  + 原創作品轉載請註明出處 + 《Linux內核分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000


    Linux內核對進程管理是操作系統的重要任務之一。此次實驗就是了解內核創建一個新進程的大致過程。爲了簡單,使用fork再用戶態創建一個進程。代碼如下:

#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");
    }
}

    在虛擬機環境中運行情況如下圖:

wKiom1UnIEPDBjk9AAFd7f8ocyQ867.jpg

wKioL1UnIY6jFls7AAHhymkdqgA500.jpg

以下使用gdb調試一下,在進程創建過程中的幾個關鍵函數出設置斷點。

wKioL1UnKAfzDFcdAAIBZvRWE0o325.jpg

在系統啓動過程走了些彎路,設置斷點的這幾個函數都是系統創建進程所必須的關鍵部分,所以啓動過程中do_fork,copy_process,copy_thread不斷的多次出現,我只好暫時使斷點失效,才讓menuos順利啓動到命令提示符。disable breakpoints 1 2 3 4 5 6.

執行fork命令,停在了斷點SyS_clone處,單步執行,定在了斷點do_fork處。經過幾行代碼,


p = copy_process(clone_flags, stack_start,stack_size,chile_tidptr, NULL,trace);

停在斷點copy_process.在執行幾行代碼,如下:

p = dup_task_struct(current);

繼續執行,斷點arch_dup_task_struct停住。

連續n命令後可以看到子進程的初始化過程:

wKioL1UnP8TjbT13AAL_meyO2aE487.jpg

程序執行斷在copy_thread後如下:

wKiom1UnP1aAEwvqAAKw-PsGSCw858.jpg

執行finish,及continue命令,進入了子進程執行的起點ret_from_fork.

wKioL1UnQiLxlL8hAAKcqmB8V40317.jpg

執行c命令,主要過程基本結束。


    總結,創建一個新進程在內核中的執行過程大致如下

        1.使用系統調用SyS_clone(或fork,vfork)系統調用創建一個新進程,而且都是通過調用do_fork來實現進程的創建;
        2.Linux通過複製父進程PCB--task_struct來創建一個新進程,要給新進程分配一個新的內核堆棧;

        3.要修改複製過來的進程數據,比如pid、進程鏈表等等執行copy_process和copy_thread
        4.p->thread.sp = (unsigned long) childregs; //調度到子進程時的內核棧頂
          p->thread.ip = (unsigned long) ret_from_fork; //調度到子進程時的第一條指令地址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章