linux培训描述,【linux培训班】关于linux系统记录和描述进程的分析
從C語(yǔ)言源代碼分析,神秘的Linux系統(tǒng)是如何記錄和描述進(jìn)程的?也許我們習(xí)慣用Windows系統(tǒng),可程序員最愛(ài)的還是linux系統(tǒng),畢竟這樣的系統(tǒng)安全性比較高,可操作的難度也是有的,不適合小白來(lái)使用。那么linux系統(tǒng)到底怎么樣呢,linux系統(tǒng)是如何記錄和描述進(jìn)程的呢?
在很多文章總,都講過(guò)Linux操作系統(tǒng)中進(jìn)程的概念,其實(shí)簡(jiǎn)單來(lái)說(shuō),進(jìn)程無(wú)非就是處于運(yùn)行期的程序及其相關(guān)資源的總和。這里讀者應(yīng)該注意“相關(guān)資源”一詞,Linux 在內(nèi)核中是如何記錄進(jìn)程的資源的呢?
Linux內(nèi)核如何記錄進(jìn)程的資源?
首先應(yīng)該明白,Linux 內(nèi)核大都是采用C語(yǔ)言編寫的,因此要弄清楚內(nèi)核如何記錄進(jìn)程資源,只需要查看相關(guān)的C語(yǔ)言代碼就可以了。事實(shí)上,Linux 內(nèi)核是使用 task_struct 結(jié)構(gòu)體描述進(jìn)程的資源的,它的C語(yǔ)言部分代碼如下,請(qǐng)看:
【linux培訓(xùn)班】關(guān)于linux系統(tǒng)記錄和描述進(jìn)程的分析
task_struct 結(jié)構(gòu)體很長(zhǎng)
task_struct 結(jié)構(gòu)體很長(zhǎng),在我手中的 Linux 內(nèi)核C語(yǔ)言源代碼中,它占用了280行。當(dāng)然了,這其中包含很多條件編譯部分,在 32 位機(jī)器上,task_struct 大約要占用 1.7 KB 的內(nèi)存空間,不過(guò)考慮到它可以管理完整的進(jìn)程,1.7kB 其實(shí)并不算大了。
鑒于 task_struct 結(jié)構(gòu)體過(guò)長(zhǎng),這里不可能將其成員一一介紹清楚。如果讀者和我一樣好奇,粗略的瀏覽 task_struct 結(jié)構(gòu)體,應(yīng)該能夠發(fā)現(xiàn)一些比較令人熟悉的成員,例如:
【linux培訓(xùn)班】關(guān)于linux系統(tǒng)記錄和描述進(jìn)程的分析
task_struct 結(jié)構(gòu)體令人熟悉的成員
通過(guò)C語(yǔ)言注釋以及成員的變量名,能夠看到 task_struct 結(jié)構(gòu)體包含了文件系統(tǒng),線程結(jié)構(gòu)體,以及進(jìn)程打開(kāi)的文件等信息,這就與上一節(jié)文章的內(nèi)容對(duì)應(yīng)上了。其他成員在我之后的文章中會(huì)涉及到,這里暫不贅述。
在創(chuàng)建進(jìn)程時(shí),Linux 通過(guò) slab 分配器分配 task_struct 結(jié)構(gòu),這樣可以避免動(dòng)態(tài)分配和釋放帶來(lái)的開(kāi)銷,提高內(nèi)存的使用效率。
那么創(chuàng)建 task_struct 結(jié)構(gòu)后,內(nèi)核如何訪問(wèn)它呢?
根據(jù)我手上的內(nèi)核C語(yǔ)言源代碼,Linux 中還有一個(gè)結(jié)構(gòu)體 thread_info,它的其中一個(gè)成員 task 指針正好適合用于索引 task_struct 結(jié)構(gòu)體,在X86_64平臺(tái)上,thread_info 的相關(guān)C語(yǔ)言代碼如下,請(qǐng)看:
【linux培訓(xùn)班】關(guān)于linux系統(tǒng)記錄和描述進(jìn)程的分析
task 指針
Linux 通常會(huì)在內(nèi)核棧底或者棧頂保留 thread_info 結(jié)構(gòu),而內(nèi)核棧通常大小都是可知的,因此每個(gè)進(jìn)程都能方便的從自己的棧中找到 thread_info 結(jié)構(gòu),進(jìn)而找到 task_struct 結(jié)構(gòu)。
查找當(dāng)前進(jìn)程的 thread_info 結(jié)構(gòu),可以調(diào)用 current_thread_info() 函數(shù),它的C語(yǔ)言代碼如下,請(qǐng)看:
static inline struct thread_info *current_thread_info(void) { register unsigned long sp asm ("sp"); return (struct thread_info *)(sp & ~(THREAD_SIZE - 1)); }
current_thread_info() 函數(shù)
可見(jiàn),current_thread_info() 函數(shù)其實(shí)就是通過(guò)進(jìn)程棧計(jì)算的,因此它的實(shí)現(xiàn)與平臺(tái)架構(gòu)有關(guān),上述C語(yǔ)言代碼其實(shí)只是 arm 平臺(tái)的實(shí)現(xiàn)方法,其他平臺(tái)的實(shí)現(xiàn)方法,讀者可自行查閱。
此時(shí),要獲取當(dāng)前進(jìn)程的資源,可以通過(guò) current_thread_info()->task 索引。
進(jìn)程 PID
Linux 內(nèi)核為每一個(gè)進(jìn)程分配獨(dú)一無(wú)二的進(jìn)程標(biāo)識(shí)(process identification,PID)用于區(qū)分不同的進(jìn)程。PID 是一個(gè)整數(shù),在內(nèi)核的C語(yǔ)言源碼中表示為 pid_t 類型(其實(shí)就是 int 類型)。在Linux命令行輸入 ps 命令,即可查看進(jìn)程的 PID,例如:
查看進(jìn)程的 PID
task_struct 結(jié)構(gòu)體使用成員 pid 記錄進(jìn)程的 PID 值,相關(guān)的C語(yǔ)言代碼如下,請(qǐng)看:
【linux培訓(xùn)班】關(guān)于linux系統(tǒng)記錄和描述進(jìn)程的分析
task_struct 結(jié)構(gòu)體使用成員 pid 記錄進(jìn)程的 PID 值
在Linux系統(tǒng)中,PID 的最大值是可以調(diào)整的,早期為了兼容老版本的 Unix 和 Linux,默認(rèn)最大值為 32768(short int 類型能夠表示的最大值),這個(gè)值可以通過(guò) cat 命令查看:
# cat /proc/sys/kernel/pid_max 32768
PID 的最大值對(duì)于Linux系統(tǒng)的運(yùn)行是有影響的,因?yàn)?PID 值是獨(dú)一無(wú)二的,所以它的最大值實(shí)際上就表示系統(tǒng)可以同時(shí)運(yùn)行的最多進(jìn)程數(shù)目。對(duì)于普通的個(gè)人用戶來(lái)說(shuō),32768 足夠多,但是對(duì)于大型服務(wù)器來(lái)說(shuō),32768 可能就遠(yuǎn)遠(yuǎn)不夠了,這時(shí)可以修改 pid_max 解決這一問(wèn)題。
進(jìn)程的狀態(tài)
現(xiàn)在知道了Linux內(nèi)核是如何描述和記錄進(jìn)程資源,以及如何區(qū)分不同進(jìn)程的了。那么進(jìn)程有哪些狀態(tài)呢?讀者應(yīng)該注意到 task_struct 結(jié)構(gòu)體的第一個(gè)成員 state 了,它就是用于記錄進(jìn)程狀態(tài)的。進(jìn)程的狀態(tài)在C語(yǔ)言源代碼中是使用幾個(gè)宏定義的:
進(jìn)程的狀態(tài)在C語(yǔ)言源代碼中是使用幾個(gè)宏定義的
Linux 系統(tǒng)中的進(jìn)程必定處于這 5 種狀態(tài)之一。從上到下,分別表示進(jìn)程處于:
正在運(yùn)行或者準(zhǔn)備運(yùn)行
正在睡眠,但是可中斷,接收到信號(hào)會(huì)被提前喚醒
正在睡眠,并且不可中斷,也即即使接收到信號(hào)也不會(huì)被喚醒
被其他進(jìn)程跟蹤中
停止運(yùn)行
現(xiàn)在就明白有時(shí)無(wú)法通過(guò) kill 命令殺死 D 狀態(tài)的進(jìn)程了,這是因?yàn)檫@些進(jìn)程處于不響應(yīng)信號(hào)的狀態(tài),kill 命令本質(zhì)上是發(fā)送 SIGKILL 信號(hào),自然無(wú)法殺死該進(jìn)程。
父進(jìn)程和子進(jìn)程
進(jìn)程的父進(jìn)程和子進(jìn)程也屬于進(jìn)程的資源,因此也被記錄在 task_struct 結(jié)構(gòu)體中,請(qǐng)看相關(guān)C語(yǔ)言代碼:
【linux培訓(xùn)班】關(guān)于linux系統(tǒng)記錄和描述進(jìn)程的分析
訪問(wèn)當(dāng)前進(jìn)程的父進(jìn)程和子進(jìn)程是方便的
所以要訪問(wèn)當(dāng)前進(jìn)程的父進(jìn)程和子進(jìn)程是方便的,例如:
struct task_struct *p = current->parent; struct task_stuck *c = current->children;
稍稍思考一下,應(yīng)該能夠發(fā)現(xiàn)進(jìn)程結(jié)構(gòu)體 task_struct 中的 parent 指針和 children 指針其實(shí)構(gòu)成了一條鏈表,通過(guò)這樣的鏈表,我們能夠輕易的訪問(wèn)進(jìn)程的父進(jìn)程,祖父進(jìn)程…, 以及子進(jìn)程,孫進(jìn)程… 等。不過(guò)應(yīng)該明白,對(duì)于擁有大量進(jìn)程的系統(tǒng)來(lái)說(shuō),重復(fù)遍歷所有進(jìn)程的開(kāi)銷是很大的。
小結(jié)
本節(jié)先討論了Linux內(nèi)核如何記錄和描述進(jìn)程資源,可以看出,內(nèi)核管理進(jìn)程其實(shí)就是管理 task_struct 結(jié)構(gòu)體。接著,通過(guò)C語(yǔ)言源代碼查看了內(nèi)核如何訪問(wèn) task_struct 結(jié)構(gòu)體,以及如何區(qū)分進(jìn)程,最后我們一起還討論了進(jìn)程的狀態(tài)和家族樹(shù),可見(jiàn),Linux內(nèi)核源代碼也并不是神秘到不可理解。
如果你對(duì)linux系統(tǒng)比較感興趣,想要學(xué)習(xí)linux系統(tǒng),那就關(guān)注IT培訓(xùn)網(wǎng)小編,我們會(huì)在第一時(shí)間與您分享最新的linux運(yùn)維的相關(guān)知識(shí)!
總結(jié)
以上是生活随笔為你收集整理的linux培训描述,【linux培训班】关于linux系统记录和描述进程的分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: linux 6.4定时启动,Centos
- 下一篇: C语言求35 45的最大公约数,c语言编