摘要: mqy + 原創做品轉載請註明出處 + 《Linux內核分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000node
操做系統的三大功能:進程管理,內層管理,文件系統linux
最核心:進程管理編程
進程控制塊PCB——task_struct數據結構
爲了管理進程,內核必須對每一個進程進行清晰的描述,進程描述符提供了內核所需瞭解的進程信息。框架
進程的pid標示某一進程函數
進程的父子關係管理this
作調試用:操作系統
fork一個子進程的代碼3d
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- int main(int argc, char * argv[])
- {
- int pid;
- /* fork another process */
- pid = fork();//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");
- }
- }
fork系統調用在父進程和子進程各返回一次調試
建立一個新進程在內核中的執行過程
- fork、vfork和clone三個系統調用均可以建立一個新進程,並且都是經過調用do_fork來實現進程的建立;
- Linux經過複製父進程來建立一個新進程,那麼這就給咱們理解這一個過程提供一個想象的框架:
- 複製一個PCB——task_struct
- err = arch_dup_task_struct(tsk, orig);
- 要給新進程分配一個新的內核堆棧
- ti = alloc_thread_info_node(tsk, node);
- tsk->stack = ti;
- setup_thread_stack(tsk, orig); //這裏只是複製thread_info,而非複製內核堆棧
- 要修改複製過來的進程數據,好比pid、進程鏈表等等都要改改吧,見copy_process內部。
- 從用戶態的代碼看fork();函數返回了兩次,即在父子進程中各返回一次,父進程從系統調用中返回比較容易理解,子進程從系統調用中返回,那它在系統調用處理過程當中的哪裏開始執行的呢?這就涉及子進程的內核堆棧數據狀態和task_struct中thread記錄的sp和ip的一致性問題,這是在哪裏設定的?copy_thread in copy_process
- *childregs = *current_pt_regs(); //複製內核堆棧
- childregs->ax = 0; //爲何子進程的fork返回0,這裏就是緣由!
-
- p->thread.sp = (unsigned long) childregs; //調度到子進程時的內核棧頂
- p->thread.ip = (unsigned long) ret_from_fork; //調度到子進程時的第一條指令地址
進程穿件概覽及fork一個進程的用戶態代碼
理解進程建立過程複雜代碼的方法
建立新進程是經過複製當前進程來實現的
系統調用內核處理函數sys_fork,sys_clone,sys-vfork
拷貝內核堆棧數據和指定進程的第一條指令進程
Int指令和SAVE_ALL壓到內核棧的內容
實驗:分析linux內核建立一個新進程的過程
過程同上次相似,首先更新MenuOS
gdb調試fork
設置斷點並調試
linux如何建立一個新進程:Linux經過複製父進程來建立一個新進程,經過調用do_ fork來實現併爲每一個新建立的進程動態地分配一個task_ struct結構