linux设备驱动归纳总结(四):1.进程管理的相关概念【转】
本文轉(zhuǎn)載自;http://blog.chinaunix.net/uid-25014876-id-64866.html
linux設(shè)備驅(qū)動歸納總結(jié)(四):1.進(jìn)程管理的相關(guān)概念
?
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
接下來的幾節(jié)我會大概的講一下內(nèi)核進(jìn)程的一些概念,其實應(yīng)該在學(xué)習(xí)系統(tǒng)編程時候就應(yīng)該知道的。。我參照的書籍是《linux內(nèi)核設(shè)計與實現(xiàn)》(第三版)。我會盡可能地跳開內(nèi)核代碼,簡述一下原理。
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
?
一、什么是進(jìn)程
?
簡單的說,進(jìn)程就是正在運行的程序,一個程序可以同時有多個進(jìn)程。學(xué)過C語言都知道,程序運行時并不是只有代碼,還包含其他的資源,如打開的文件,信號,全局變量等等。我在《操作系統(tǒng)原理》中看過一個很生動很深刻的例子:一個人對照著菜譜做菜。在這例子中,人就是內(nèi)核,菜譜就是程序,做菜的過程就是進(jìn)程,而菜、鍋就是這個進(jìn)程的資源。
內(nèi)核為線程提供了兩種技術(shù):虛擬處理器和虛擬內(nèi)存。這就是說,每個進(jìn)程都傻乎乎的認(rèn)為自己獨占著CPU和享用這4G的內(nèi)存,確不知道內(nèi)核在背后調(diào)度進(jìn)程和給每個進(jìn)程4G的虛擬地址。
進(jìn)程由fork創(chuàng)建,通過exit退出。
有人或許會問,那線程是什么?線程就是一種特殊的進(jìn)程。
?
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
?
二、進(jìn)程是用什么結(jié)構(gòu)體來維護(hù)
?
內(nèi)核將所有的進(jìn)程放在叫任務(wù)隊列(task list)的雙向循環(huán)鏈表中,鏈表中的每個項都是類型為task_struct、稱為進(jìn)程描述符的結(jié)構(gòu)。每個進(jìn)程描述符包含著一個進(jìn)程的所有信息,驅(qū)動開發(fā)中我用得最頻繁的有兩個成員,pid(進(jìn)程標(biāo)識值)和comm(當(dāng)前進(jìn)程的所執(zhí)行的程序文件名稱)。
來張形象點的圖:
獲得當(dāng)前正在進(jìn)行的進(jìn)程進(jìn)程描述符也很簡單,使用全局項current就可以獲得。
/*4th_mutex/4th_mutex_1/1st/test.c*/
113 P_DEBUG("[%s]:pid[%d]\n", current->comm, current->pid);
?
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
?
三、進(jìn)程的狀態(tài)
?
我只說5種,其中前兩種是之前在等待隊列的時候介紹過。
1)TASK_RUNNING(運行):該狀態(tài)出現(xiàn)在進(jìn)程正在運行,或者已經(jīng)放在運行隊列中等待執(zhí)行(對應(yīng)操作系統(tǒng)原理上所說的就緒狀態(tài))。這里要注意的是等待執(zhí)行和休眠是兩碼事。
2)TASK_INTERRUPTIBLE(可中斷休眠):這就是休眠狀態(tài)中一種,之所以說可中斷,就是說除了可以被其他進(jìn)程從等待隊列喚醒以外,還可以接送到信號而喚醒,這是常用的休眠狀態(tài)。
3)TASK_UNINTERRUPTIBLE(不可中斷休眠):這就是休眠狀態(tài)的另一種,只能從等待隊列被喚醒。因為它如此霸道,所以很少有人使用。
4)TASK_ZOMBIE(僵死):這種情況出現(xiàn)在進(jìn)程結(jié)束后,但父進(jìn)程還有來回收該進(jìn)程的進(jìn)程描述符。
5)TASK_STOPPED(停止):一看就知道,進(jìn)程停止執(zhí)行。
?
來個圖來對照前四種狀態(tài)的轉(zhuǎn)換:
由上圖可以看到用戶空間的進(jìn)程有fork()系統(tǒng)調(diào)用產(chǎn)生,如果運行途中沒有任何阻塞,它會在最后調(diào)用do_exit將進(jìn)程的狀態(tài)轉(zhuǎn)為TASK_ZOMBIE。等待父進(jìn)程來收尸。接下來就要簡單地說一下進(jìn)程的創(chuàng)建和進(jìn)程的終結(jié)。
?
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
?
四、進(jìn)程的創(chuàng)建
進(jìn)程的創(chuàng)建一般分兩步:
?
1、調(diào)用fork():
在系統(tǒng)編程時,我們一般都是調(diào)用fork()來創(chuàng)建新的用戶進(jìn)程。
先說一下傳統(tǒng)的forl()的實現(xiàn),傳統(tǒng)的fork()被調(diào)用后,內(nèi)核會拷貝父進(jìn)程的所有資源給新建的子進(jìn)程。要知道這是一個多愚蠢的操作,如果新建子進(jìn)程是打算執(zhí)行另一個新程序,之前的拷貝過程就白費了。
出于這樣的原因,linux的fork()有了寫時拷貝(copy-on-write)技術(shù)。從字面上就能理解意思,父進(jìn)程創(chuàng)建子進(jìn)程后,他給子進(jìn)程創(chuàng)建一個文件描述符,并且與子進(jìn)程以只讀方式共享原有的資源,只有在子進(jìn)程或者父進(jìn)程修改資源時,資源才會被復(fù)制。所以說,在不修改資源的情況下,fork()的實際開銷就兩樣:
1)復(fù)制父進(jìn)程的頁表給子進(jìn)程。大家應(yīng)該都知道,linux內(nèi)存管理使用的頁式管理,只要也就是說,只要把父進(jìn)程的頁表復(fù)制給子進(jìn)程,子進(jìn)程就能在頁表中找到與父進(jìn)程共享的4G虛擬地址了。
2)為子進(jìn)程創(chuàng)建唯一的進(jìn)程描述符。這個就不用解釋了,進(jìn)程與進(jìn)程描述符是一一對應(yīng)的。
?
fork具體調(diào)用的什么函數(shù)我就不詳細(xì)說了,不過應(yīng)該有這樣的一個概念:
fork->clone->do_fork()->copy_procrss:
fork()系統(tǒng)調(diào)用根據(jù)提供的參數(shù)調(diào)用clone(),然后clone()去調(diào)用do_fork(),其中do_fork中完成了創(chuàng)建的大部分操作,里面有一個主要的函數(shù)copy_process()。
?
2、調(diào)用exec():
一般的,創(chuàng)建的子進(jìn)程都不是為了完成父進(jìn)程中的任務(wù),而是需要執(zhí)行新的任務(wù)。exec()的作用就是讀取可執(zhí)行文件并加載到地址空間開始運行,可以類比成命令”./xxxxx”。如果fork()后子進(jìn)程調(diào)用exec()執(zhí)行新的代碼,就不需要拷貝父進(jìn)程的資源了。所以,一般fork()之后都是子進(jìn)程先運行。
?
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
?
五、進(jìn)程的終結(jié):
?
一般的,進(jìn)程調(diào)用exit()結(jié)束進(jìn)程。相應(yīng)的,exit()是調(diào)用do_exit()進(jìn)行刪除進(jìn)程的資源和改變進(jìn)程狀態(tài)等操作。
?
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
?
六、什么是進(jìn)程上下文:
?
用戶態(tài)的應(yīng)用程序執(zhí)行系統(tǒng)調(diào)用時,它就會陷入內(nèi)核空間,此時,我們稱內(nèi)核“代表進(jìn)程執(zhí)行”并處于進(jìn)程上下文。簡單的說,以我們之前寫的驅(qū)動舉例,當(dāng)應(yīng)用成調(diào)用open,他就會陷入內(nèi)核調(diào)用驅(qū)動函數(shù)中的test_open,此時內(nèi)核就 處于進(jìn)程上下文了。
值得一提的是,在進(jìn)程上下文時,current始終有效,它還是指向應(yīng)用層中的進(jìn)程,所以在”1st”的例子中,tesp_open打印出來的進(jìn)程號current->pid與應(yīng)用層是一樣的。
?
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
?
七、線程、進(jìn)程和內(nèi)核線程程又是怎么樣的關(guān)系:
?
線程,它是進(jìn)程活動中的對象,最通俗的解釋,一個進(jìn)程里面可以有一個或者多個線程,它們共同享用進(jìn)程的資源。
內(nèi)核線程,獨立運行在內(nèi)核空間的標(biāo)準(zhǔn)進(jìn)程,但沒有獨立的運行空間,只運行在內(nèi)核空間,但和普通進(jìn)程一樣被調(diào)度和搶占。
總的來說,線程(又叫用戶線程)和內(nèi)核線程都是進(jìn)程的特殊形式,它們的創(chuàng)建同樣也是通過調(diào)用clone()。它們和進(jìn)程的最大區(qū)別在于它們沒有獨立的4G虛擬空間。
而線程和內(nèi)核線程的區(qū)別就是:線程存在與用戶態(tài),內(nèi)核線程存在與內(nèi)核態(tài)。
同時需要強(qiáng)調(diào)的是,進(jìn)程是存在于用戶態(tài)的。
?
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
?
八、總結(jié):
?
今天只是介紹了進(jìn)程的一些基本的概念,為以后的進(jìn)程調(diào)度、并發(fā)、競態(tài)等理論打基礎(chǔ)。
?
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
總結(jié)
以上是生活随笔為你收集整理的linux设备驱动归纳总结(四):1.进程管理的相关概念【转】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 扒取网站的源代码
- 下一篇: linux:ls -l详解