標籤:
基本操作命令:
ps -ajx/-aux/-ef 查看進程間狀態/的相互關係
top 動態顯示系統中的進程
nice 按照指定的優先順序運行 /renice 改變正在啟動並執行進程的優先順序
kill -9殺死進程
jobs 查看後台進程數
進程的結構、類型、狀態、模式
0.Linux中進程包括三段:
(1)資料區段。存放的是全域變數,常量以及動態記憶體的資料空間。
(2)本文段。存放的是程式中的代碼。
(3)堆棧段。存放的是函數的返回地址,函數的參數以及局部變數。
進程類型:互動進程,既可以在前台運行,也可以在後台運行。該類進程是由shell控制和啟動並執行。
批處理進程,不屬於某個終端,被提交到一個隊列中以便順序執行。
守護進程:系統開始時執行,系統關閉時結束。
1.系統中專用的進程:
(1)ID為0的進程是調度進程,通常稱為交換進程,該進程是核心的一部分,它並不執行任何磁碟上的程式,因此也被稱為系統進程。
(2)ID為1 的進程是init進程,init進程通常讀與系統有關的初始設定檔案,並將系統引導到一個狀態。init進程絕不會終止,init進程是所有孤兒進程的父進程。
(3)ID為2的進程是頁守護進程,此進程負責支援虛擬儲存系統的分頁操作。
2.子進程是父進程的副本,子進程獲得父進程的資料空間,堆和棧的副本。這是子進程擁有的獨立的空間。父子進程並不共用這些儲存空間,父子進程共用本文段。fork之後到底是先執行父進程還是子進程是不一定的,取決於核心所使用的調度演算法,如果要求父子進程之間相互同步,則要求進程間的通訊。
vfork也能建立進程,但是不能產生父進程的副本,當子進程需要改變記憶體中的資料時,才拷貝父進程。
父進程與子進程的區別:
fork的傳回值不同;
進程ID不同;
父進程設定的檔案鎖不會被子進程繼承;
子進程未處理的鬧鐘被清除;
子進程未處理的訊號集設定為空白集。
(1)孤兒進程:對於所有父進程終止的所有進程,他們的父進程都變為init進程。init無論何時只要有一個進程終止,init就會調用一個wait函數取得其終止狀態。這樣就防止了系統中好多個殭屍進程。
(2)殭屍進程:子進程結束,父進程沒有收屍。
(3)進程間資料共用。
exec函數族:當進程認為自己不能為系統和使用者做出任何貢獻的時候,就可以調用exec函數族,讓自己執行新的程式。如果某個進程在執行一個程式的時候想執行另一個程式,則首先建立子進程,在子進程中間調用exec函數。在用exec函數是要加上出錯判斷。
傳統的處理序間通訊
(1)無名管道:無名管道是半雙工的,資料只能想一個方向流動,具有固定的讀端和寫端;無名管道只能用於父子進程或者兄弟進程(具有親緣關係的進程)之間。
無名管道單獨構成一種獨立的檔案系統;管道是基於檔案描述符的通訊方式,當一個管道建立時,它會建立兩個檔案描述符,其中fd[0] 固定於讀管道,fd[1] 固定於寫管道。管道只存在於記憶體中。
管道的讀寫:
管道是一種檔案,因此對管道的讀寫同read()和write()函數。
一個進程向管道中寫得內容被管道的另一端進程讀出。寫入的內容每次都添加在管道的尾端,並且每次都是從緩衝區的頭部讀出資料。
當父子進程對管道進程讀寫的時候,如果父進程執行寫操作,則關閉相應的讀管道的檔案描述符;而子進程進行寫操作,它將關閉相應的讀操作。
當管道為空白的時候,讀操作會阻塞,向管道中寫資料的時候Linux作業系統不保證寫入的原子操作,管道中只要有空閑地區寫進程會試圖向管道中寫入資料。如果讀操作不讀走緩衝區的資料,則寫操作一直會阻塞。只有在讀管道存在時,寫管道才有意義,不
然則會受到系統發出的SIGPIPE訊號(管道破裂)。應用程式可以處理該訊號,也可以忽略(預設動作則是終止程式)。
#include <unistd.h>
int pipe(int fd[2])
(2)有名管道:不同於有名管道之處在於它提供一個路徑名與之關聯,有名管道可以使不相關的進程之間進行通訊。以FIFO的檔案形式存在於檔案系統中。
注意:FIFO嚴格遵循先進先出,對管道及FIFO的讀總是從開始處返回資料,對他們的寫則是把資料添加到末尾。不支援lseek()等檔案操作。
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char * pathname, mode_t mode)
該函數的第一個參數是一個普通的路徑名,也就是建立後FIFO的名字。第二個參數與開啟普通檔案的open()函數中的mode 參數相同。如果mkfifo的第一個參數是一個已經存在的路徑名時,會返回EEXIST錯誤,所以一般典型的調用代碼首先會檢查是否返回該錯誤,如果確實返回該錯誤,那麼只要調用開啟FIFO的函數就可以了。一般檔案的I/O函數都可以用於FIFO,如close、read、write等等
無名管道由一個在基本檔案系統存放裝置上的INODE,一個與其相連的記憶體INODE,兩個開啟檔案控制區(分別對應管道的資訊發送端和資訊接收端)及其所屬進程的描述資訊來標識,在系統執行PIPE(P)命令列之後產生。並在P[0]中返回管道的讀通道開啟檔案描述等,在P[1]中返回管道的寫通道開啟檔案描述符。從結構上看,無名管道沒有檔案路徑名,不佔用檔案目錄項,因此檔案目錄結構中的鏈表不適用於這種檔案,它只是存在於開啟檔案結構中的一個臨時檔案,隨其所依附的進程的生存而生存,當進程終止時,無名管道也隨之消亡。
送入管道的資訊一旦被讀進程取用就從管道中消失了,讀寫操作之間符合先進先出的隊列原則。
管道檔案是處理序間通訊的工具,為了盡量少的佔用系統儲存資源,一般系統均將其限制為最大長度為4096(PIPSIZ)位元組的小型檔案。當欲寫入的訊息超過4096位元組時,就產生了讀、寫進程之間的同步問題。首先寫操作尋找PIPE檔案中當前指標的位移量F-OFFSET,然後從此位置開始盡量寫入資訊,當長度達到4096位元組時,系統控制寫進程進入睡眠狀態,一直等待讀進程取走全部資訊時,檔案長度指標置0,寫進程才被喚醒繼續工作。
為防止多個進程同時讀寫一個管道檔案而產生混亂,在管道檔案的INODE標誌字I-FLAY項中設定了ILOCK標誌項,以設定軟體鎖的方式實現多進程間對管道檔案的互斥使用。
無名管道存在著如下兩個嚴重的缺點。
第一,無名管道只能用於串連具有共同祖先的進程。
第二,無名管道是依附進程而臨時存在的。所以後來推出了一種無名管道的變種-有名管道,它常被稱為FIFO。有名管道除繼承了無名管道的所有特性優點之外,還屏棄了無名管道的兩個缺點。
首先,FIFO是一種永久性的機構,它具有普通的UNIX系統檔案名稱。在系統下可利用MKNOD命令建立永久的管道,除非刻意刪除它,否則它將一直保持在系統中。
其次,正是由於有名管道以“檔案名稱”來標識,所以只要事先約定某一特定檔案名稱,那樣所有知道該約定的服務進程,不論它們之間是否有親屬關係,都可以便利地利用管道進行通訊。
通過下面的命令可以建立一個具名管道:
/etc/mknod pipe_name p
其中“pipe_name”是要建立的具名管道的名字,參數p 必須出現在具名管道名字之後。
named pipes(具名管道)管道具有很好的使用靈活性,表現在:
1) 既可用於本地,又可用於網路。
2) 可以通過它的名稱而被引用。
3) 支援多客戶機串連。
4) 支援雙向通訊。
5) 支援非同步重疊I/O操作。
無名管道與有名管道的異同:
1.通訊方式;
2.進程是否相關;
3.存在地區不同;
4.存在周期不同;
相同點:
1.都是先進先出;
2.管道的容量相同;
Linux系統編程——處理序間通訊(一)