Linux內核-進程管理
Linux內核-進程管理

1.進程
#內核調度的對象是線程,不是進程
#對Linux而言,線程只是特殊的進程
#進程提供兩種虛擬機制:虛擬處理器、虛擬內存
#創建進程通過fork()來從父進程復制創建進程
2.進程描述符
#任務隊列:雙向鏈表(每一項都是task_struct--->進程描述符)
#Linux通過slab分配器分配task_struct
#內核通過唯一的進程標識值(PID)來標識進程
#五種進程狀態: ?1.TASK_RUNNING 進程可執行
2.TASK_INTERRUPTIBLE 可中斷
3.TASK_UNINTERRUPTIBLE 不可中斷
4._TASK_TRACED 被其他進程跟蹤
5._TASK_STOPPED 進程停止執行
#設置進程狀態: set_task_state(task, state)函數和set_surrent_state(state)函數
#所有進程都是PID為1的init進程的后代
#init進程描述符 init_task
3.進程創建
#fork()和exec()
fork()拷貝當前進程創建子進程
exec()讀入可執行文件并載入空間地址開始執行
#寫時拷貝:fork()使用寫時拷貝(copy-on-write)使得地址空間的頁拷貝被推遲到實際發生寫入時才進行
(fork()后立即執行exec()就無需進行拷貝)
fork()的實際開銷就是復制父進程的頁表以及分配進程描述符
#fork()執行過程:通過系統調用clone()調用fork()
clone()調用do_fork(),do_fork()調用copy_process()
copy_process()過程:
1.調用dum_task_struct()為新進程創建內核棧、thread_info、task_struct
2.確保創建子進程后當前進程數沒有超過限制
3.子進程開始與父進程區別開來,進程描述符中的許多成員初始化或清0
4.子進程的狀態被設置為TASK_UNINTERRUPTIBLE
5.調用copy_flags()更新來更新task_struct的flags成員
6.調用alloc_pid()為新進程分配PID
7.copy_process()拷貝共享打開的文件、文件系統信息、信號處理函數、進程地址空間和命名空間
8.copy_process()做掃尾工作并返回一個指向子進程的指針
#vfork():向clone()系統調用傳遞一個特殊標志來進行:
1.調用copy_process()時,task_struct的vfork_done成員被設置為NULL
2.如果執行do_fork()時給定地址,vfork_done會指向一個特定地址
3.子進程開始執行后,父進程不會立即開始執行,直到vfork_done指針向它發出信號
4.調用mm_release()進程退出地址空間,并檢查vfork_done是否為空,若不為空,等待父進程發送信號
5.回到do_fork(),父進程醒來并返回
4.線程在Linux中的實現
#線程機制提供了在同一程序中共享內存地址的空間運行的一組線程
#Linux將所有的線程當做進程來實現
#創建線程:
clone(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND , 0)
5.進程終結
#發生在進程調用exit()系統調用時:
任務大部分要靠do_exit()來完成:
1.將task_struct的標志成員設置為PF_EXITING
2.調用del_timer_sync()刪除任一內核定時器
3.如果BSD的進程記賬開啟,do_exit()調用acct_update_integrals()來輸出記賬信息
4.調用exit_mm()釋放進程占用的mm_struct
5.調用sem_exit(),如果進程等待IPC信號,則離開隊列
6.調用exit_files()和exit_fs()
7.把存放在task_struct的exit_code成員中的任務退出代碼置為由exit()提供的退出代碼
8.調用exit_notify()向父進程發送信號,為子進程尋找養父,養父為線程組中的其他線程或者init,并把進程狀態設為EXIT_ZOMBIE
9.do_exit()調用schedule()切換到新的進程
#刪除進程描述符:調用了do_exit(),進程僵死,但是系統還保留了進程描述符
釋放進程描述符時,release_task()會被調用:
1.調用_exit_signal(),該函數調用_unhash_process(),后者又調用?detach_pid()從pidhash上刪除該進程,同時也要從任務列表中刪除該進程
2._exit_signal()釋放目前僵死進程的資源,進行統計記錄
3.如果該進程為進程組最后一個進程,并且領頭已經死掉,release_task()通知領頭進程的父進程
4.release_task()調用put_task_struct()釋放進程內核棧和thread_info所占的頁
#孤兒進程造成的進退維谷:如果父進程在子進程之前退出,必須有機制保證子進程能找到新的父親
Linux 任務調度
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。