課本第三章讀書筆記

2022-08-31 11:27:13 字數 4458 閱讀 5055

程序是unix作業系統抽象概念中的最基本的一種

程序

是處於執行期的程式,(以及相關資源的總稱)不僅僅侷限於一段可執行的**,通常還要包括其他資源。實際上程序就是正在執行的程式**的實時結果。核心需要有效而透明的管理所以細節

執行緒

是在程序中活動的物件,每個執行緒都擁有乙個獨立的程式計數器,程序棧和一組程序計數器。核心排程的物件是執行緒,而不是程序

程序提供的兩種虛擬機制

虛擬處理器:實際上有多個程序分享乙個處理器,但虛擬處理器給程序一種假象,讓程序覺得自己在獨享處理器

虛擬記憶體:讓程序在分配和管理記憶體是覺得自己擁有整個系統所有記憶體資源

實際上完全可能存在兩個或多個程序執行的是同乙個程式,並且兩個或多個並存的程序還可以共享許多資源。程序在建立的時候存活呼叫fork()

fork()

複製乙個現有程序來建立乙個全新程序。

呼叫的程序稱為父程序,新產生的程序稱為子程序

fork()程序從核心返回兩次:一次回到父程序,另一次回到子程序

實際是由clone()系統呼叫實現的

建立的新程序都是為了立即執行新的,不同的程式。而接著呼叫exec()這組函式就可以建立新的位址空間,並把新的程式載入其中。

程式通過exit()系統呼叫退出執行。終結程序並釋放其占用的資源

wait4():查詢子程序是否終結
程序退出執行後備設定成為僵死狀態,直到他的父程序呼叫wait()或waitpid()為止

核心把程序的列表存放在叫做任務佇列的雙向迴圈鍊錶中。鍊錶的每一項都是型別為task_struct、稱為程序描述符的結構。程序描述符中包含了乙個具體程序的所有資訊:

他開啟的檔案、程序的位址空間、掛起的訊號、程序的狀態、以及其他的一些資訊
linux通過slab分配器分配task _ struct結構,這樣能達到物件復用和快取著色的目的。slab分配器動態生成task _ struct結構,所以只需在棧底(向下增長)或棧頂(向上增長)建立乙個新的結構struct thread _ info

每個任務的thread _ info結構在他的核心棧的尾端。結構中task域存放的是指向該任務實際的task _ struct的指標

核心通過乙個唯一的程序標識值或pid來標識每個程序。核心把每個程序的pid存放的各自的程序描述符中。

pid是乙個是,表示為pid_t隱含型別,實際上就是提高int型別

pid的預設最大值設定為32768,即系統允許同時存在的程序的最大數目。可以通過

/proc/sys/kernel/pid_max來提高上限

核心中訪問任務通常需要獲得指向其的task_struct指標。通過current巨集查詢到當前正在執行的程序描述符的速度就顯得尤為重要。

x86體系只能在核心棧的尾端建立thread_info結構,通過計算偏移間接查詢task結構

movl $-8192,%eax

andl %esp,%eax

current_thread_info()->task //從thread_info域中提取並返回task_struct的位址

程序描述符state域描述了程序的當前狀態

set _ task_state(task,state) //將任務task的狀態設定為state

等價於task-> = state
系統呼叫和異常處理是對核心明確定的介面程序之間存在明顯的繼承關係。系統中每個程序必有乙個父程序,相應的每個程序也可以擁有0個或多個子程序

程序之間的關係存放在程序描述符中。包含乙個指向父程序task_state叫做parent的指標,還包括乙個稱為children的子程序鍊錶

獲得父程序的程序描述符:

struct task _ struct   *my_parent = current->parent;
訪問子程序:

struct task_struct *task;

struct list_head *list;

list_for_each(list ¤t->children)

依次訪問程序佇列:

struct task_struct *task;

for_each_process(task)

unix獨特的程序建立方式:

是一種可以推遲甚至免除拷貝資料的技術。核心此時並不複製整個記憶體空間,而是讓父程序好和子程序共享乙個拷貝。只有在需要的時候資料才會被複製

fork()的實際開銷就是複製父程序的頁表以及給子程序建立唯一的程序描述符。一般情況下,程序在建立後會立即執行乙個可執行檔案

linux通過clone()系統呼叫實現fork()

fork()——>clone()——do_fork()——>copy _process()

copy_process的工作過程:

1、呼叫dup_task_struct()為程序建立乙個核心棧、thread_info結構等與當前程序的值相同

2、檢查並確保建立這個程序後系統程序數不會超過限制

3、子程序著手使自己與父程序區別開來:許多描述符被清零或初始化

4、子程序的狀態被設定為不可中斷模式以保證不會投入執行

5、copy_process呼叫copy_flags()以更新task_struct的flags成員

6、呼叫alloc_pid()為新程序分配乙個有效的pid

7、根據傳遞給clone()的引數標誌,copy_process拷貝或共享開啟的檔案等

8、copy_process()做掃尾工作並返回乙個指向子程序的指標

執行緒機制提供了在同一程式內共享記憶體位址空間、開啟的檔案和一些其他資源的一組執行緒

在linux中所以的執行緒都當做程序來處理,執行緒被視為乙個與其他程序共享某些資源的程序。每個執行緒都擁有唯一隸屬於自己的task_struct

執行緒的建立於程序的建立類似,只不過在呼叫clone()的時候需要傳遞一些引數來指明需要共享的資源:

獨立執行在核心空間的標準程序稱為核心執行緒。他與普通程序的區別在於核心執行緒沒有獨立的位址空間。核心執行緒和普通程序一樣可以被排程或搶占。

核心執行緒也只能由其他核心執行緒建立

從現有核心執行緒中建立乙個新的核心執行緒:

新的任務kthread核心程序通過clone()系統呼叫建立的

建立乙個新的程序並讓他執行起來

當乙個程序終結時,核心必須釋放他所占有的資源並把這一不幸告知其父程序。

程序的終結大部分都要靠do_exit()函式來完成:

呼叫了do_exit()之後程序執行緒已經僵死不能執行,但是系統還是保留了他的程序描述符(在子程序終結後仍有可能獲得他的資訊)

只有在父程序獲得已終結的子程序的資訊後或通知核心他並不關注那些訊息之後子程序的狀態描述符再回別釋放。

系統通過呼叫release_task ()釋放需要釋放的程序描述符

父程序在子程序之前退出,成為孤兒的程序就會在哎退出時永遠處於僵死狀態。所以必須保證子程序能找到乙個新的父程序(當前程序組中的乙個執行緒或者init)

一旦程序成功的找到和設定了新的父程序,就不會再有出現駐留僵死程序的危險了

init程序會例行呼叫wait()來檢查其子程序清楚所有與其相關的僵死程序

第三章讀書筆記

程序管理 3.1程序 程序就是處於執行期的程式 目標碼存放在某種儲存介質上 但程序並不僅僅侷限於一段可執行程式 執行執行緒,執行緒,是程序活動的物件。兩種虛擬機制 虛擬處理器和虛擬記憶體。最終,程式通過exit 系統呼叫退出執行。3.2程序描述及任務結構 核心把程序的列表存放在叫做任務佇列的雙向迴圈...

第三章讀書筆記

本章是講了git的使用入門,為學習本書的人展示了git的基本用法。儘管git並不是學習android移植和linux核心 驅動開發必須掌握的技術。但對於深入研究這些底層技術的人來說,git將成為學習過程中必不可少的工具。git是什麼,git就是乙個開源的分布式版本控制系統,用以有效 高速的處理從很小...

UNP讀書筆記第三章

網路位元組序和主機位元組序大小端不一樣。linux提供了4個轉換函式 include uint16 t htons uint16 t value uint32 t htonl uint 32t value uint16 t ntohs uin16 t value uint32 t ntohl uin...