20135327郭皓--Linux內核分析第六週 進程的描述和進程的建立

進程的描述和進程的建立

1、進程的描述

操做系統三大功能:數據結構

  • 進程管理
  • 內存管理
  • 文件系統

進程描述符task_struct數據結構atom

  • task _ struct:爲了管理進程,內核必須對每一個進程進行清晰的描述,進程描述符提供了內核所需瞭解的進程信息。spa

  • 進程的狀態:Linux進程的狀態(就緒態、運行態、阻塞態)操作系統

  • 進程的標示pid:用來標示進程線程

進程狀態轉化

進程描述符task_struct數據結構(重要部分):3d

 1 struct task_struct {
 2 volatile long state;    /* 進程的運行狀態-1 unrunnable, 0 runnable, >0 stopped */
 3 void *stack;    /*指定了進程的內核堆棧*/
 4 atomic_t usage;
 5 unsigned int flags; /* 每個進程的標識符 */
 6 
 7 int on_rq;  /*運行隊列*/
 8 
 9 pid_t pid; /*進程標識符*/
10 
11 struck list_head task;  /*進程鏈表*/
12 
13 /*父子進程*/
14 struct task_struct __rcu *real_parent; /* real parent process */
15 struct task_struct __rcu *parent; 
16 
17 struct list_head children;    /* list of my children */

 

2、進程的建立

start _ kernel代碼中的rest _ init建立兩個內核線程,kernel _ init和kthreadd。調試

kernel _ init將用戶態進程init啓動,是全部用戶態進程的祖先。rest

kthreadd是全部內核線程的祖先。code

0號進程是全部線程的祖先。(0號進程時手工寫的)orm

fork一個子進程的代碼:

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <unistd.h>
 4 int main(int argc, char * argv[])
 5 {
 6     int pid;
 7     /* fork another process */
 8     pid = fork();
 9     if (pid < 0) 
10     { 
11         /* error occurred */
12         fprintf(stderr,"Fork Failed!");
13         exit(-1);
14     } 
15     else if (pid == 0) 
16     {
17         /* child process */
18         printf("This is Child Process!\n");
19     } 
20     else 
21     { 
22         /* parent process  */
23         printf("This is Parent Process!\n");
24         /* parent will wait for the child to complete*/
25         wait(NULL);
26         printf("Child Complete!\n");
27     }
28 }

這裏特別說明一下:else if和if兩個模塊的代碼都會被執行,子進程和父進程都會返回,子進程返回0,父進程返回子進程pid。

 

 

實驗:

1. 刪除menu,克隆新的menu。

 

2.查看help

3.gdb調試

4.設置斷點

5.單步追蹤

 

總結:

新的進程從哪裏開始?

1 *childregs = *current_pt_regs(); //複製內核堆棧
2 childregs->ax = 0; //爲何子進程的fork返回0,這裏就是緣由!
3  
4 p->thread.sp = (unsigned long) childregs; //調度到子進程時的內核棧頂
5 p->thread.ip = (unsigned long) ret_from_fork; //調度到子進程時的第一條指令地址

Linux經過複製父進程來建立一個新進程:複製父進程PCB--task_struct來建立一個新進程,要給新進程分配一個新的內核堆棧。

修改複製過來的進程數據,好比pid、進程鏈表等等執行copy_process和copy_thread。

設置sp調度到子進程時的內核棧頂,ip轉到子進程時的第一條指令地址

以後,當子進程得到CPU的控制權開始運行的時候,ret _ form _ fork能夠將後面的堆棧出棧,從iret返回到用戶態,從而切換到子進程的用戶空間,完成新進程的建立。

相關文章
相關標籤/搜索