是處於執行期的程式以及它所包含的資源的總稱。
執行緒的定義:
是在程序中活動的物件。
每個執行緒都擁有乙個獨立的程式計數器、程序棧和一組程序暫存器。
核心排程的物件是執行緒,而不是程序。
3.2 程序描述符及任務結構
程序描述符的結構:task_struct,定義在中,包含乙個具體程序的所有資訊。
task_struct 就是指 pcb (程序控制塊)。
3.2.1 分配程序描述符
thread_info結構在檔案中。
3.2.2 程序描述符的存放
3.2.3 程序狀態
1.task_running (執行):無論程序是否正在占用 cpu ,只要具備執行條件,都處於該狀態。 事實上, linux 是將就緒態和執行態合併為了一種狀態。
2.task_interruptible (可中斷阻塞):在資源有效時被喚醒,也可以通過訊號或定時中斷喚醒。
3.task_uninterruptible (不可中斷阻塞):另一種阻塞狀態,處於該狀態的程序只有當資源有效時被喚醒,不能通過訊號或定時中斷喚醒。
4.task_stopped (暫停):第三種阻塞狀態,程序被停止,通常是通過接收乙個訊號sigstop, sigtstp, sigttin, sigttou。
5.task_zombile (僵死):程序已結束但尚未消亡,已經釋放了大部分資源, pcb 仍未被釋放,在task資料中仍然保留task_struct結構。一旦父程序呼叫了wait4(),程序描述符就會被釋放。
3.2.4 設定當前程序狀態
set_task_state(task, state); /* 設定任務 'task' 的狀態變成 'state' */
3.2.5 程序上下文
核心「代表程序執行」並處於程序上下文中。
此上下文中current巨集有效。
3.2.6 程序家族樹
1.獲得父程序的程序描述符:
struct task_struct *my_parent = current->parent;
2.依次訪問子程序:
struct task_struct *task;
struct list_head *list;
list_for_each(list, ¤t->children)
4.獲取鍊錶中的前乙個程序:
list_entry(task->tasks.prev, struct task_struct, tasks)
5.巨集for_each_process(task),提供了依次訪問整個任務佇列的能力,
struct task_struct *task;
for_each_process(task)
3.3 程序建立
3.3.1 寫時拷貝
fork() 和 exec()
fork():通過拷貝當前程序建立乙個子程序。
3.3.2 fork()
通過clone()系統呼叫實現fork()。
do_fork完成建立中大量工作,定義在kernel/fork.c檔案中。
呼叫copy_process()函式讓程序開始執行。(具體工作很有意思詳見《linux核心設計與實現》第27頁)
3.3.3 vfork()
與fork()很類似。
實現是通過向clone()系統呼叫傳遞乙個特殊標誌來進行。(具體工作很有意思詳見《linux核心設計與實現》第28頁)
3.4 執行緒在linux中的實現
3.4.1 建立執行緒
在呼叫clone()需傳遞一些引數標誌指明共享資源。
clone(clone_vm | clone_fs | clone_sighand, 0);
新建的程序和他的父程序就是執行緒。
乙個普通的fork()。
clone(sighand, 0);
vfork()的實現。
clone(clone_vfork | clone_vm | sighand, 0);
clone()引數標誌決定新建立程序的行為方式和父子程序之間共享的資源種類。(具體引數標識詳見《linux核心設計與實現》第29-30頁)
3.4.2 核心執行緒
核心執行緒只能由其他核心執行緒建立。
核心通過從kthreadd核心程序中衍生出所有新核心執行緒來自動處理。
在中宣告介面。
新的任務是由kthread核心進系統呼叫程通過clone()而建立的。
核心執行緒啟動後一直執行知道呼叫do_exit()退出,或者核心其它部分呼叫kthread_stop()退出。
3.5 程序終結
程序的退出一般是顯示或隱式地呼叫了exit(),或者接受了某種訊號。
只要退出,最終都呼叫了do_exit()(具體完成的繁瑣工作詳見《linux核心設計與實現》第31頁)。
3.5.1 刪除程序描述符
wait()會暫時停止目前程序的執行,直到有訊號來到或子程序結束。如果執行成功則返回子程序識別碼(pid),如果有錯誤發生則返回-1。
最終需要釋放程序描述符時,release_task()會被呼叫(具體需要完成的工作詳見《linux核心設計與實現》第32頁)
3.5.2 孤兒程序造成的進退維谷
如果父程序在子程序之前退出,必須有機制來保證子程序能找到乙個新的父親,否則這些成為孤兒的程序就會在退出時永遠處於僵死狀態。
解決方法是給子程序在當前執行緒組內找乙個執行緒作為父親,如果不行,就讓init做它們的父程序。在do_exit()中會呼叫exit_notify(),該函式會呼叫forget_original_parent(),而後者會呼叫find_new_reaper()來執行尋父。
遍歷了兩個鍊錶:子程序鍊錶和ptrace子程序鍊錶,給每個子程序設定新的父程序。
20135320趙瀚青LINUX期中總結
本學期的linux核心這門課程已經進行了一半,這門課的學習方法和上個學期深入理解計算機系統的方式差不多,所以也沒有特別多不適應,linux核心在我看來,就是理解乙個作業系統是如何實現各個功能的,先從巨集觀上讓我們理解一下,linux作業系統,然後再讓我們看看各個功能實現的 和過程,包括程序的建立,程...
20135320趙瀚青LINUX第六周學習筆記
這周主要講解的是程序。首先老師就講解了pcb程序結構塊的資料結構,pcb程序控制塊的 包含了很多資訊,最開始就是程序的狀態資訊 然後是程序狀態符,程序排程相關資訊等等很多部分。然後老師講解了用fork 建立程序的過程,然後用gdb除錯,跟蹤建立程序的過程。本週學習的內容在上個學期婁老師的課程中有涉及...
20135320趙瀚青LINUX第四章讀書筆記
文字編輯程式顯然是 1 0 消耗型的,因為它大部分時間都在等待使用者的鍵盤輸入 無論使用者的輸入速度有多快,都不可能趕上處理的速度 使用者總是希望按下鍵系統就能馬上響應。以模組方式提供的,這樣做的目的是允許不同型別的程序可以有針對性地選 擇排程算哉。cfs的做怯是允許每個程序執行一段時間 迴圈輪轉 ...