呂鬆鴻 + 原創做品轉載請註明出處 + 《Linux內核分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000數據結構
進程管理
內存管理
文件系統
task _ struct:爲了管理進程,內核必須對每一個進程進行清晰的描述,進程描述符提供了內核所需瞭解的進程信息。 進程的狀態:Linux進程的狀態(就緒態、運行態、阻塞態) 進程的標示pid:用來標示進程
struct task_struct { volatile long state; /* 進程的運行狀態-1 unrunnable, 0 runnable, >0 stopped */ void *stack; /*指定了進程的內核堆棧*/ atomic_t usage; unsigned int flags; /* 每個進程的標識符 */ int on_rq; /*運行隊列*/ pid_t pid; /*進程標識符*/ struck list_head task; /*進程鏈表*/ /*父子進程*/ struct task_struct __rcu *real_parent; /* real parent process */ struct task_struct __rcu *parent; struct list_head children; /* list of my children */
建立進程的系統調用有3個,它們經過統一的系統調用接口進入核心態運行後就分道揚鑣,各自調用本身的內核函數sys_fork、sys_clone、sys_vfork進行處理。這三個函數最終都是調用do_fork函數進行建立子進程的工做,只不過使用的參數有所不一樣。 Linux經過複製父進程來建立一個新進程:複製父進程PCB--task_struct來建立一個新進程,要給新進程分配一個新的內核堆棧。 修改複製過來的進程數據,好比pid、進程鏈表等等執行copy_process和copy_thread。 以後,從ret_from_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"); } }
Linux經過複製父進程來建立一個新進程:複製父進程PCB--task_struct來建立一個新進程,要給新進程分配一個新的內核堆棧。
修改複製過來的進程數據,好比pid、進程鏈表等等執行copy_process和copy_thread。
設置sp調度到子進程時的內核棧頂,ip轉到子進程時的第一條指令地址
以後,當子進程得到CPU的控制權開始運行的時候,ret _ form _ fork能夠將後面的堆棧出棧,從iret返回到用戶態,從而切換到子進程的用戶空間,完成新進程的建立。