進程的描述和進程的創建


                                                                                        進程的描述和進程的創建

                                                                                                        20135109 高藝桐

                                                                                                        《Linux內核分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000 

一、進程的描述

1、1進程描述符task_struck數據結構(一)

(1)操作系統的三大功能:進程管理、內存管理、文件系統。

(2)

進程控制塊PCB——task_struck

tty_struck控制台

fs_struck文件系統的描述

files_struck打開的文件描述符

mm_struck內存的描述

signal_struck信號的描述

(3)操作系統原理中的狀態:就緒態、運行態、阻塞態

(4)

內核管理中的進程狀態:

TASK_TUNNING(可運行)獲得cpu控制權正在運行,被調度出去就是就緒態。

TASK_ZOMBIE(進程被終止)

TASK_interruotibie(阻塞態)

TASK_uninterruotibie(阻塞態)

(5)進程的標示符:pid(用來標識進程)

1、2進程描述符task_struck數據結構(二)

(1)state運行狀態(指定進程狀態)

(2)SMP條件編譯(多處理器時會用到)

(3)

   

struct list_head tasks進程的鏈表,雙向循環鏈表連接,鏈表可獨立進行操作

(4)每個進程有自己獨立的地址空間,32位x86有4G進程地址空間。

(5)pid_t pid標識一個進程

(6)

進程的父子關系:兄弟父子之間的關系通過雙向鏈表連接起來。

(7)CPU相關的狀態:thread_struct(sp、ip)進程上下文切換時期關鍵作用

(8)struct files_struct*files打開文件列表

(9)struck signal_struct *signal信號處理相關工作

二、進程的創建過程

2、1進程的創建概覽及fork一個進程的用戶態代碼

(1)(文件系統、信號、內存)進程描述符中有相應的指針指向其內容,進行研究。

(2)

進程是怎么創建的:復制一份進程描述符,0號進程用代碼寫死,1號進程復制0號進程pcb,根據1號進程需要修改pid,最后加一個init可執行程序。

(3)

子進程從哪里開始執行:shell命令行怎么創建子進程的?

fork()用戶態進行創建子進程

fork系統調用在父進程和子進程各返回一次

(4)fork在子進程中返回值是父進程的ID

2、2理解進程創建過程復雜代碼的方法

(1)系統調用再回顧:

 

Int0x80是中斷指令,把用戶態堆棧轉化到內核態堆棧,把CPU最關鍵的現場eip、esp保存到內核堆棧中去。

(2)

  

    子進程從哪里開始執行:fork()出的子進程在內核中開始返回。創建一個進程的框架:復制一份進程描述符,0號進程用代碼寫死,1號進程復制0號進程pcb,根據1號進程需要修改pid,最后加一個init可執行程序。

(3)創建進程過程中要做哪些事情:修改pcb,建立鏈表,修改分配內核堆棧,保存進程執行到哪個位置,保存sp、ip(避免發生混亂),需要有thread設定eip和esp位置。

2、3瀏覽進程的創建過程相關的關鍵方法

(1)

創建新進程在內核中執行的過程:

復制一個PCB——task_struct

給新進程分配一個新的內核堆棧

更改復制過來的進程數據,比如pid,進程鏈表等

(2)系統調用內核處理函數:sys_fork、sys_clone、sys_vfork

(3)do_fork()中包含的copy process創建一個進程內容的主要代碼

(4)arch dup_task_struct復制整個PCB(*dst=src*數據結構的值復制給dst)

(5)thread_info內核堆棧,創建一個頁面,比較大(分配內核堆棧空間)

(6)p指向子進程的描述符

(7)copy_thread從子進程的pid找到了棧底的地址,把sp賦值過去,對父進程的棧底進行拷貝,包括棧頂數據,thread ip的內容。

2、4創建的新進程是從哪里開始執行的

(1)子進程從哪里開始執行的:ret_from_fork

(2)

Int指令和SAVE_ALL壓到內核棧的內容。

(3)ret_from_fork 中的syscall_exit內核堆棧可正常返回到用戶態(子進程的進程空間)。

2、5使用gdb跟蹤創建新進程的過程

自己實驗截圖:

(1)把menu刪除,克隆一份新的,把test_fork.c覆蓋掉,編譯內核,可以看到fork命令

(2)設置斷點sys_clone,設置斷點do_fork,設置斷點dup_task_struck,設置斷點copy_process,設置斷點copy_thread,設置斷點ret_from_fork

(3)在MenuOS中執行fork,就會發現fork函數停在了父進程中 

(4)繼續執行之后,停在了do_fork的位置

(5)按s進入該函數,可以看到dst = src(也就是復制父進程的struct)

(6)按n繼續追蹤

(7)在copy_thread中,可以看到把task_pg_regs(p)也就是內核堆棧特定的地址找到並初始化

三、實驗總結

  通過本周的學習,我了解到了Linux通過clone()系統調用實現fork(),fork(),vfork(),和clone()庫函數都是根據各自需要的參數標志去調用clone(),然后由clone()調用do_fork,其中do_fork函數調用了copy_process()函數,然后讓進程執行 Linux通過復制父進程創建新進程,fork、vfork、clone都是通過do_exit實現進程的創建。

  創建新進程的過程為:復制一個PCB——task_struct,給新進程分配一個新的內核堆棧,更改復制過來的進程數據,比如pid,進程鏈表等。子進程從ret_from_fork開始執行。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM