日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

20、进程编程基础

發(fā)布時(shí)間:2025/6/16 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 20、进程编程基础 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

進(jìn)程的基本概念

  進(jìn)程是操作系統(tǒng)設(shè)計(jì)的核心概念,Multics的設(shè)計(jì)者在20世紀(jì)60年代首次使用了"進(jìn)程"這個(gè)術(shù)語,比作業(yè)更通用一點(diǎn)。目前存在很多關(guān)于進(jìn)程的定義,例如:

1、一個(gè)正在執(zhí)行的程序。

2、計(jì)算機(jī)中正在運(yùn)行的程序的一個(gè)實(shí)例。

3、可以分配給處理器并由處理器執(zhí)行的一個(gè)實(shí)體。

4.由單一的順序的執(zhí)行線程、一個(gè)當(dāng)前狀態(tài)和一組相關(guān)的系統(tǒng)資源所描述的活動(dòng)單元。

  也可以把進(jìn)程是為由一組元素組成的實(shí)體,進(jìn)程的兩個(gè)基本元素是程序代碼和代碼相關(guān)聯(lián)的數(shù)據(jù)集。假設(shè)處理器開始執(zhí)行程序代碼,那我們把這個(gè)執(zhí)行的實(shí)體成為進(jìn)程。進(jìn)程執(zhí)行時(shí),任意給定一個(gè)時(shí)間,進(jìn)程都可以用以下元素為唯一表征:

  • 標(biāo)識(shí)符:跟這個(gè)進(jìn)程相關(guān)地唯一標(biāo)識(shí)符,用來區(qū)別其他進(jìn)程
  • 狀態(tài):如果進(jìn)程正在執(zhí)行,那么進(jìn)程處于運(yùn)行態(tài)
  • 優(yōu)先級:相對于其他進(jìn)程的優(yōu)先級
  • 程序計(jì)數(shù)器:程序中即將被執(zhí)行的下一條指令的地址
  • 內(nèi)存地址:包括程序代碼和進(jìn)程相關(guān)數(shù)據(jù)的指針,還有和其他進(jìn)程共享內(nèi)存塊的指針
  • 上下文數(shù)據(jù):進(jìn)程執(zhí)行時(shí)處理器的寄存器中的數(shù)據(jù)
  • I/O狀態(tài)信息:包括顯式的I/O請求、分配給進(jìn)程的I/O設(shè)備和被進(jìn)程使用的文件列表
  • 記賬信息

上述列表信息被存放在一個(gè)稱為進(jìn)程控制塊的數(shù)據(jù)結(jié)構(gòu)中,該控制塊由操作系統(tǒng)創(chuàng)建和管理。

  比較有意義的一點(diǎn)是,進(jìn)程控制塊包含充分的信息,這樣當(dāng)進(jìn)程被中斷時(shí),操作系統(tǒng)會(huì)把程序計(jì)數(shù)器和處理器寄存器(上下文數(shù)據(jù))保存到進(jìn)程控制塊中的相應(yīng)位置,進(jìn)程狀態(tài)也被改變?yōu)槠渌?#xff0c;例如阻塞態(tài)或就緒態(tài)?,F(xiàn)在操作系統(tǒng)可以自由地把其他進(jìn)程置為運(yùn)行態(tài),把其他進(jìn)程的程序計(jì)數(shù)器和進(jìn)程上下文數(shù)據(jù)加載到處理器寄存器,這樣其他進(jìn)程就可以開始執(zhí)行。

為什么設(shè)計(jì)了進(jìn)程??

  設(shè)計(jì)出一個(gè)能夠協(xié)調(diào)各種不同活動(dòng)的系統(tǒng)軟件是非常困難的。在任何時(shí)刻都有許多作業(yè)在運(yùn)行中,每個(gè)作業(yè)都包括要求按照順序執(zhí)行的很多步驟,因此分析時(shí)間的序列組合是不可能的。由于缺乏能夠在所有活動(dòng)中進(jìn)行協(xié)調(diào)和合作的系統(tǒng)級的方法,程序員只能基于他們對操作系統(tǒng)所控制的環(huán)境的理解,采用自己的特殊方法。然而這種方法是很脆弱的,尤其對于一些程序設(shè)計(jì)中的小錯(cuò)誤,因?yàn)檫@些錯(cuò)誤只有在很少見的時(shí)間序列發(fā)生時(shí)才會(huì)出現(xiàn)。由于需要從應(yīng)用程序軟件錯(cuò)誤和硬件錯(cuò)誤中區(qū)分出這些錯(cuò)誤,因而診斷工作是很困難的。及時(shí)檢測出錯(cuò)誤,也很難確定原因,因?yàn)楹茈y在線錯(cuò)誤產(chǎn)生的精確場景。一般而言,產(chǎn)生這類錯(cuò)誤的4個(gè)主要原因如下:

1.不正確同步?
2.失敗互斥。?
3.不確定的程序操作?
4.死鎖

解決這些問題需要一種系統(tǒng)級別的方法監(jiān)控處理器中不同程序的執(zhí)行。進(jìn)程的概念為此提供了基礎(chǔ)。?因此進(jìn)程可以看做是由三部分組成的:?
1.一段可以執(zhí)行的程序?
2.程序所需要的相關(guān)數(shù)據(jù)?
3.程序的執(zhí)行上下文

?

?執(zhí)行上下文是進(jìn)程的重重之中。執(zhí)行上下文(execution context)?又稱作進(jìn)程狀態(tài)(process state),是操作系統(tǒng)用來管理和控制進(jìn)程所需的內(nèi)部數(shù)據(jù)。這種內(nèi)部信息和進(jìn)程是分開的,因?yàn)?span style="color:#ff0000;">操作系統(tǒng)信息不允許被進(jìn)程直接訪問。上下文包括操作系統(tǒng)管理進(jìn)程以及處理器正確執(zhí)行進(jìn)程所需要的所有信息。包括了各種處理器寄存器的內(nèi)容,如程序計(jì)數(shù)器和數(shù)據(jù)寄存器。它還包括操作系統(tǒng)使用的信息,如進(jìn)程優(yōu)先級以及進(jìn)程是否在等待特定?I/O事件的完成。

圖中兩個(gè)進(jìn)程A 和B ,存在于內(nèi)存中某部分。也就是說給每個(gè)進(jìn)程(包含程序、數(shù)據(jù)和上下文信息)分配一塊存儲(chǔ)器區(qū)域,并且在由操作系統(tǒng)建立和維護(hù)的進(jìn)程表中進(jìn)行記錄。進(jìn)程表中包含記錄每個(gè)進(jìn)程的表現(xiàn),表項(xiàng)內(nèi)容包括指向包含進(jìn)程的存儲(chǔ)塊地址的指針,還包括該進(jìn)程的部分或全部執(zhí)行上下文。指向上下文的其余部分存放在別處,可能和進(jìn)程自己保存在一起,通常也可能保存在內(nèi)存里一塊獨(dú)立的區(qū)域中。進(jìn)程索引寄存器(process index register)?包含當(dāng)前正在控制處理器的進(jìn)程在進(jìn)程表中的索引。程序計(jì)數(shù)器指向該進(jìn)程中下一條待執(zhí)行的指令?;芳拇嫫?base register)?和界限寄存器(limit register)?定義了該進(jìn)程所占據(jù)的存儲(chǔ)器區(qū)域:基址寄存器中保存了該存儲(chǔ)器區(qū)域的開始地址,界限寄存器中保存了該區(qū)域的大小(以字節(jié)或字為單位)。程序計(jì)數(shù)器和所有的數(shù)據(jù)引用相對于基址寄存器被解釋,并且不能超過界限寄存器中的值,這就可以保護(hù)內(nèi)部進(jìn)程間不會(huì)相互干涉。(解決了互斥的問題)

圖中進(jìn)程索引寄存器表明進(jìn)程B正在執(zhí)行。以前執(zhí)行的進(jìn)程被臨時(shí)中斷,在A中斷的同時(shí),所有的寄存器的內(nèi)容被記錄在它執(zhí)行上下文環(huán)境中,以后操作系統(tǒng)就可以執(zhí)行進(jìn)程切換,恢復(fù)進(jìn)程A的執(zhí)行。進(jìn)程切換過程包括保存B的上下文和恢復(fù)A的上下文。當(dāng)在程序計(jì)數(shù)器中載入指向A的程序區(qū)域的值時(shí),進(jìn)程A自動(dòng)恢復(fù)執(zhí)行。

因此進(jìn)程被當(dāng)做數(shù)據(jù)結(jié)構(gòu)來實(shí)現(xiàn)。一個(gè)進(jìn)程可以是正在執(zhí)行,也可是等待執(zhí)行。任何時(shí)候整個(gè)進(jìn)程狀態(tài)都包含在它的執(zhí)行上下文環(huán)境中。這個(gè)結(jié)構(gòu)使得可以開發(fā)功能強(qiáng)大的技術(shù),以確保在進(jìn)程中進(jìn)行協(xié)調(diào)和合作。在操作系統(tǒng)中可能會(huì)設(shè)計(jì)和并入一些新的功能(優(yōu)先級,linux中nice值。)這可以通過擴(kuò)展上下文環(huán)境以包括支持這些特征的新信息。

?

兩狀態(tài)進(jìn)程模型?

  操作系統(tǒng)的基本職責(zé)是控制進(jìn)程的執(zhí)行。這包括確定交替執(zhí)行的方式和給進(jìn)程分配資源在設(shè)計(jì)控制進(jìn)程的程序時(shí),第一步就是描述進(jìn)程所表現(xiàn)出的行為。

  在任何時(shí)刻,一個(gè)進(jìn)程要么正在執(zhí)行,要么沒有執(zhí)行,因而可以構(gòu)造最簡單的模型。一個(gè)進(jìn)程可以處于以下兩種狀態(tài)之一:運(yùn)行態(tài)或未運(yùn)行態(tài)。當(dāng)操作系統(tǒng)創(chuàng)建一個(gè)新的進(jìn)程時(shí),它將該進(jìn)程運(yùn)行態(tài)加入到系統(tǒng)中,操作系統(tǒng)知道這個(gè)進(jìn)程是存在的,并且正在等待執(zhí)行機(jī)會(huì)。當(dāng)前正在運(yùn)行的進(jìn)程時(shí)不時(shí)的被中斷,操作系統(tǒng)中的分派器部分將選擇一個(gè)新進(jìn)程運(yùn)行。前一個(gè)進(jìn)程從運(yùn)行態(tài)轉(zhuǎn)換到未運(yùn)行狀態(tài),另外一個(gè)集成轉(zhuǎn)換到運(yùn)行態(tài)。

  從這個(gè)簡單的模型可以意識(shí)到操作系統(tǒng)的一些設(shè)計(jì)元素。必須用某種方式來表示每個(gè)進(jìn)程,使得操作系統(tǒng)能夠跟蹤它,也就是說,必須有一些與進(jìn)程相關(guān)的信息,包括進(jìn)程在內(nèi)存中的當(dāng)前狀態(tài)和位置,即進(jìn)程控制塊。未運(yùn)行的進(jìn)程必須保持在某種類型的隊(duì)列中,并等待它們的執(zhí)行時(shí)機(jī)。結(jié)構(gòu)中有一個(gè)隊(duì)列,隊(duì)列中的每一項(xiàng)都指向某個(gè)特定進(jìn)程的指針,或隊(duì)列可以由數(shù)據(jù)塊構(gòu)成的鏈表組成,每個(gè)數(shù)據(jù)塊表示一個(gè)進(jìn)程。

  因此可以用該隊(duì)列圖描述分派器的行為。被中斷的進(jìn)程轉(zhuǎn)移到等待進(jìn)程隊(duì)列中,或者,如果進(jìn)程已經(jīng)結(jié)束或取消,則被銷毀(離開系統(tǒng))。在任何一種情況下,分派器均從隊(duì)列中選擇一個(gè)進(jìn)程來執(zhí)行。

?五狀態(tài)模型

  如果所有的進(jìn)程都做好了執(zhí)行準(zhǔn)備。隊(duì)列是先進(jìn)先出(first-in-first-out)的表,對于可運(yùn)行的進(jìn)程處理器以一種輪轉(zhuǎn)(round-robin)方式操作(依次給隊(duì)列中的每個(gè)進(jìn)程一定的執(zhí)行時(shí)間,然后進(jìn)程返回隊(duì)列,阻塞情況除外)。但是存在著一些非運(yùn)行狀態(tài)但已經(jīng)就緒等待執(zhí)行的進(jìn)程,而同時(shí)存在另外的一些處于阻塞狀態(tài)等待I/O操作結(jié)束的進(jìn)程。因此,如果使用單個(gè)隊(duì)列,分派器不能只考慮隊(duì)列中最老的進(jìn)程,相反,他應(yīng)該掃描這個(gè)列表,查找那些被阻塞且在隊(duì)列中時(shí)間最長的進(jìn)程。解決這種情況的一種比較自然的方法是將非運(yùn)行狀態(tài)分成兩個(gè)狀態(tài):就緒(ready)和阻塞(blocked),此外應(yīng)該增加兩個(gè)已經(jīng)證明很有用的狀態(tài)。

  五狀態(tài)模型中的五種狀態(tài)具體含義如下:

運(yùn)行態(tài):進(jìn)程正在被執(zhí)行(本章中,假設(shè)計(jì)算機(jī)只有一個(gè)處理器,因此一次最多只有一個(gè)進(jìn)程處于這個(gè)狀態(tài))。

就緒態(tài):進(jìn)程做好了準(zhǔn)備,只要有機(jī)會(huì)就可運(yùn)行。

阻塞態(tài):進(jìn)程在某些事件發(fā)生前不能執(zhí)行,例如IO操作完成。

新建態(tài):剛剛創(chuàng)建的進(jìn)程,操作系統(tǒng)還沒有把它加入到可執(zhí)行進(jìn)程組中,通常是進(jìn)程塊已經(jīng)創(chuàng)建但還沒有加載到內(nèi)存中的新進(jìn)程。

退出態(tài):操作系統(tǒng)從可執(zhí)行進(jìn)程組中釋放出的進(jìn)程,或者因?yàn)樗陨硗V沽?#xff0c;或者是因?yàn)槟撤N原因被取消。

  新建態(tài)和退出態(tài)對進(jìn)程管理是非常有用的。新建態(tài)對于剛剛定義的進(jìn)程,例如,如果一位新用戶試圖登錄到分時(shí)系統(tǒng)中,或者新的一批作業(yè)被提交執(zhí)行,那么操作系統(tǒng)可以分兩步定義新進(jìn)程:首先,操作系統(tǒng)執(zhí)行一些必須的輔助工作,將標(biāo)識(shí)符關(guān)聯(lián)到進(jìn)程中,分配和創(chuàng)建管理進(jìn)程所需要的所有表,此時(shí),進(jìn)程處于新建態(tài),這意味著操作系統(tǒng)已經(jīng)執(zhí)行了創(chuàng)建進(jìn)程的必要?jiǎng)幼?#xff0c;但還沒有執(zhí)行進(jìn)程;其次,操作系統(tǒng)將所需要的關(guān)于該進(jìn)程的信息保存到內(nèi)存的進(jìn)程表中,但進(jìn)程自身還未進(jìn)入內(nèi)存,就是說即將執(zhí)行的程序代碼不在內(nèi)存中,也沒有為這個(gè)程序相關(guān)的數(shù)據(jù)分配空間。當(dāng)進(jìn)程處于新建態(tài)時(shí),程序保留在外存中,通常是磁盤中。

  進(jìn)程退出也分為兩步:(1)當(dāng)進(jìn)程到達(dá)一個(gè)自然結(jié)束點(diǎn),由于出現(xiàn)不可恢復(fù)的錯(cuò)誤而被取消時(shí),或當(dāng)具有相應(yīng)權(quán)限的另一個(gè)進(jìn)程取消該進(jìn)程時(shí),進(jìn)程被終止。終止的進(jìn)程轉(zhuǎn)換到退出態(tài),此時(shí)程序不再被執(zhí)行,與程序相關(guān)的信息被操作系統(tǒng)臨時(shí)保留起來,這給輔助程序或支持程序提供了獲取所需信息的時(shí)間。(2)為了分析性能和利用率,一個(gè)實(shí)用程序可能需要提取進(jìn)程的歷史信息,一旦這些程序提取了所需要的信息,操作系統(tǒng)就不再需要任何于該進(jìn)程相關(guān)的數(shù)據(jù),該進(jìn)程將從系統(tǒng)中被刪掉。

進(jìn)程狀態(tài)切換

  導(dǎo)致進(jìn)程狀態(tài)轉(zhuǎn)換的事件類型有很多,其中常見的有以下8種。

1、空——>新建

  通常有四個(gè)事情會(huì)導(dǎo)致一個(gè)進(jìn)程的創(chuàng)建:

  • 批處理環(huán)境中,響應(yīng)作業(yè)提交時(shí)會(huì)創(chuàng)建進(jìn)程。
  • 交互環(huán)境中,當(dāng)一個(gè)新用戶試圖登錄時(shí)會(huì)創(chuàng)建進(jìn)程。
  • 現(xiàn)有進(jìn)程派生新進(jìn)程?;谀K話的考慮,或者為了開發(fā)并行性,用戶程序可以指示創(chuàng)建多個(gè)進(jìn)程。
  • 操作系統(tǒng)代表應(yīng)用程序創(chuàng)建進(jìn)程,例如當(dāng)用戶請求打印一個(gè)文件時(shí),操作系統(tǒng)會(huì)創(chuàng)建一個(gè)管理打印的進(jìn)程,進(jìn)而請求進(jìn)程可以繼續(xù)執(zhí)行,與完成打印任務(wù)的時(shí)間無關(guān)。

2、新建——>就緒

  操作系統(tǒng)尊卑在接納一個(gè)進(jìn)程時(shí),把一個(gè)進(jìn)程從新建態(tài)轉(zhuǎn)換到就緒態(tài)。大多數(shù)系統(tǒng)會(huì)基于現(xiàn)有的進(jìn)程數(shù)或分配給現(xiàn)有進(jìn)程的虛擬數(shù)量設(shè)置一些限制,以確保不會(huì)因?yàn)榛钴S的進(jìn)程過多而導(dǎo)致系統(tǒng)性能下降。

3、就緒——>運(yùn)行

  需要選擇一個(gè)新進(jìn)程運(yùn)行時(shí),操作系統(tǒng)會(huì)選擇一個(gè)處于就緒態(tài)的進(jìn)程,這是調(diào)度器或分派器的工作。

4、運(yùn)行——>就緒

  運(yùn)行態(tài)轉(zhuǎn)換為就緒態(tài)最常見的原因是:正在運(yùn)行的進(jìn)程到達(dá)了“允許不中斷執(zhí)行"的最大時(shí)間段,實(shí)際上所有多道程序操作系統(tǒng)都實(shí)行了這類時(shí)間限定。這類轉(zhuǎn)換還有很多其他原因,例如操作系統(tǒng)給不同進(jìn)程分配不同的優(yōu)先級,優(yōu)先級高的進(jìn)程搶占優(yōu)先級低的進(jìn)程,但這不試用于所有操作系統(tǒng)。還有一種情況是:進(jìn)程自愿釋放對處理器的控制,例如一個(gè)周期行的進(jìn)行記賬和維護(hù)的后臺(tái)進(jìn)程。

5、運(yùn)行——>阻塞

  如果操作系統(tǒng)被進(jìn)程請求必須等待某些事件,那么該進(jìn)程則進(jìn)入阻塞態(tài)。對操作系統(tǒng)的請求通常以系統(tǒng)調(diào)用的形式發(fā)出。例如:進(jìn)程可能請求操作系統(tǒng)的一個(gè)服務(wù),但操作系統(tǒng)無法立即予以服務(wù),即請求一個(gè)無法立即得到的資源,如文件或虛擬內(nèi)存中的共享區(qū)域;或者也可能需要進(jìn)行某種初始化的工作,如IO操作所遇到的情況,并且只有在該初始化完成后才能繼續(xù)執(zhí)行。當(dāng)進(jìn)程相互通信,一個(gè)進(jìn)程等待另一個(gè)進(jìn)程提供輸入時(shí),或者等待來自另一個(gè)進(jìn)程提供輸入時(shí),或者等待來自另一個(gè)進(jìn)程的信息時(shí),進(jìn)程都可能被阻塞。

6、阻塞——>就緒

  當(dāng)所等待的事情發(fā)生后,處于阻塞態(tài)的進(jìn)程轉(zhuǎn)換到就緒態(tài)。

7、就緒——>退出

  為了清楚,圖中并未表示這種轉(zhuǎn)換。在某些系統(tǒng)中,父進(jìn)程可以在任何時(shí)刻終止一個(gè)子進(jìn)程。如果一個(gè)父進(jìn)程終止,那么與該父進(jìn)程相關(guān)的所有子進(jìn)程都將被終止。

8、阻塞——>退出

  阻塞態(tài)轉(zhuǎn)換為退出態(tài)于就緒態(tài)轉(zhuǎn)換為退出態(tài)類似。

進(jìn)程啟動(dòng)

  從磁盤加載到Linux系統(tǒng)內(nèi)存中并被執(zhí)行,一個(gè)程序大致經(jīng)過7個(gè)階段,如圖所示:

C函數(shù)總是從函數(shù)main()開始執(zhí)行,其函數(shù)原型如下:

int main(int argc,char *argv[]);

其中,argc是命令行參數(shù)的數(shù)目;參數(shù)argv是指向命令行參數(shù)構(gòu)成的數(shù)組。

當(dāng)內(nèi)核執(zhí)行C程序是,在調(diào)用函數(shù)main()之前會(huì)先調(diào)用一個(gè)特殊的啟動(dòng)例程。可執(zhí)行程序文件將此啟動(dòng)例程制定為程序的起始地址——這是由連接器設(shè)置的,而連接器則由C編譯器調(diào)用。啟動(dòng)例程從內(nèi)核取得命令行參數(shù)和環(huán)境變量值,然后為調(diào)用main()做好準(zhǔn)備。

進(jìn)程終止

  終止進(jìn)程的方式有8種,其中5中為正常終止:

(1)從函數(shù)main()主動(dòng)返回;

(2)調(diào)用函數(shù)exit();

(3)調(diào)用函數(shù)_exit()或Exit();

(4)最后一個(gè)線程從啟動(dòng)例程返回;

(5)最后一個(gè)線程調(diào)用函數(shù)pthread_exit()。

  異常終止有3種:

(1)調(diào)用函數(shù)abort()。

(2)接到一個(gè)信號(hào)。

(3)最后一個(gè)線程對線程取消做出響應(yīng)。

?

  函數(shù)_exit()和_Exit()立即進(jìn)入內(nèi)核;函數(shù)exit()則先進(jìn)行一些清理,然后返回內(nèi)核。其函數(shù)原型如下:

?

#include<unistd.h>void _exit(int status);#inlcude <stdlib.h>void _Exit(int status); void exit(int status);

  由于歷史原因,函數(shù)exit()總是執(zhí)行一個(gè)標(biāo)準(zhǔn)IO的清理關(guān)閉操作,對于所有打開流調(diào)用函數(shù)fclose(),這造成輸出緩沖區(qū)中的所有數(shù)據(jù)都被沖洗(寫入到文件中)。

?

  這3個(gè)推出函數(shù)都帶一個(gè)整型參數(shù),稱為終止?fàn)顟B(tài)。Linux系統(tǒng)Shell可以檢查進(jìn)程終止的狀態(tài)。如果調(diào)用函數(shù)時(shí)不帶終止?fàn)顟B(tài),或函數(shù)main()執(zhí)行了一個(gè)無返回值的return語句,或函數(shù)main()沒有聲明返回類型為整型,并且函數(shù)main()執(zhí)行到最后一條語句時(shí)返回(隱式返回),那么該進(jìn)程的終止?fàn)顟B(tài)為0。

?

進(jìn)程的內(nèi)核空間

  程序在內(nèi)存中大致分為5個(gè)部分,如下圖所示:


可以看到一個(gè)進(jìn)程地址空間的主要成分為:
  • 正文:這是整個(gè)用戶空間的最低地址部分,存放的是指令(也就是程序所編譯成的可執(zhí)行機(jī)器碼),通常,正文段是可共享的,所以即使是頻繁執(zhí)行的程序在存儲(chǔ)器中也只需要一個(gè)副本。此外,程序端通常是只讀的,以防止程序意外修改其指令。

  • 已初始化數(shù)據(jù)段:這里存放的是初始化過的全局變量

  • 未初始化數(shù)據(jù)段:此段又稱為BSS段,這里存放的是未初始化的全局變量,在程序開始執(zhí)行之前,內(nèi)核將此段數(shù)據(jù)初始化為0或空指針。

  • 堆(heap):堆是用于存放進(jìn)程運(yùn)行中被動(dòng)態(tài)分配的內(nèi)存段,它的大小并不固定,可動(dòng)態(tài)擴(kuò)張或縮減。當(dāng)進(jìn)程調(diào)用malloc等函數(shù)分配內(nèi)存時(shí),新分配的內(nèi)存就被動(dòng)態(tài)添加到堆上(堆被擴(kuò)張);當(dāng)利用free等函數(shù)釋放內(nèi)存時(shí),被釋放的內(nèi)存從堆中被剔除(堆被縮減)

  • 棧:棧是用戶存放程序臨時(shí)創(chuàng)建的局部變量,也就是說我們函數(shù)括弧“{}”中定義的變量(但不包括static聲明的變量,static意味著在數(shù)據(jù)段中存放變量)。除此以外,在函數(shù)被調(diào)用時(shí),其參數(shù)也會(huì)被壓入發(fā)起調(diào)用的進(jìn)程棧中,并且待到調(diào)用結(jié)束后,函數(shù)的返回值也會(huì)被存放回棧中。由于棧的先進(jìn)先出特點(diǎn),所以棧特別方便用來保存/恢復(fù)調(diào)用現(xiàn)場。從這個(gè)意義上講,我們可以把堆??闯梢粋€(gè)寄存、交換臨時(shí)數(shù)據(jù)的內(nèi)存區(qū)。

  • 命令行參數(shù)和環(huán)境變量:用戶調(diào)用的最底層。

下面以一個(gè)實(shí)例完成對內(nèi)存的探究:

?

#include<stdio.h>#include<malloc.h>#include<unistd.h>int bss_var;//未初始化變量int data_var0=1;//初始化變量int main(int argc,char **argv){printf("below are addresses of types of process's mem\n");printf("Text location:\n");printf("\tAddress of main(Code Segment):%p\n",main);//獲取main的地址 printf("____________________________\n");int stack_var0=2;//棧變量 printf("Stack Location:\n");printf("\tInitial end of stack:%p\n",&stack_var0);int stack_var1=3;printf("\tnew end of stack:%p\n",&stack_var1);printf("____________________________\n");printf("Data Location:\n");printf("\tAddress of data_var(Data Segment):%p\n",&data_var0);//初始化數(shù)據(jù)段地址static int data_var1=4;printf("\tNew end of data_var(Data Segment):%p\n",&data_var1);printf("____________________________\n");printf("BSS Location:\n");printf("\tAddress of bss_var:%p\n",&bss_var);//未初始化數(shù)據(jù)段地址 printf("____________________________\n");char *b = sbrk((ptrdiff_t)0);//保存在堆區(qū)的內(nèi)存指針 printf("Heap Location:\n");printf("\tInitial end of heap:%p\n",b);brk(b+4);//brk通過傳遞的addr來重新設(shè)置program break,brk和sbrk主要的工作是實(shí)現(xiàn)虛擬內(nèi)存到內(nèi)存的映射. b=sbrk((ptrdiff_t)0);//而sbrk用來增加heap,增加的大小通過參數(shù)increment決定,返回增加大小前的heap的program break,如果increment為0則返回program break。 printf("\tNew end of heap:%p\n",b);return 0;}

?

編譯運(yùn)行結(jié)果如下:

?

參考資料

進(jìn)程詳解

進(jìn)程描述和控制

Linux內(nèi)存管理

brk和sbrk及內(nèi)存分配函數(shù)相關(guān)

理解brk和sbrk

操作系統(tǒng)之面試???/h2>

malloc內(nèi)存分配過程詳解

推薦書目

操作系統(tǒng):精髓與設(shè)計(jì)原理(原書第6版)

轉(zhuǎn)載于:https://www.cnblogs.com/noticeable/p/8490657.html

總結(jié)

以上是生活随笔為你收集整理的20、进程编程基础的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。