當前位置:編程學習大全網 - 源碼下載 - Linux進程間通信

Linux進程間通信

linux下進程間通信的幾種主要手段簡介:

壹般文件的I/O函數都可以用於管道,如close、read、write等等。

實例1:用於shell

管道可用於輸入輸出重定向,它將壹個命令的輸出直接定向到另壹個命令的輸入。比如,當在某個shell程序(Bourne shell或C shell等)鍵入who│wc -l後,相應shell程序將創建who以及wc兩個進程和這兩個進程間的管道。

實例二:用於具有親緣關系的進程間通信

管道的主要局限性正體現在它的特點上:

有名管道的創建

小結:

管道常用於兩個方面:(1)在shell中時常會用到管道(作為輸入輸入的重定向),在這種應用方式下,管道的創建對於用戶來說是透明的;(2)用於具有親緣關系的進程間通信,用戶自己創建管道,並完成讀寫操作。

FIFO可以說是管道的推廣,克服了管道無名字的限制,使得無親緣關系的進程同樣可以采用先進先出的通信機制進行通信。

管道和FIFO的數據是字節流,應用程序之間必須事先確定特定的傳輸"協議",采用傳播具有特定意義的消息。

要靈活應用管道及FIFO,理解它們的讀寫規則是關鍵。

信號生命周期

信號是進程間通信機制中唯壹的異步通信機制,可以看作是異步通知,通知接收信號的進程有哪些事情發生了。信號機制經過POSIX實時擴展後,功能更加強大,除了基本通知功能外,還可以傳遞附加信息。

可以從兩個不同的分類角度對信號進行分類:(1)可靠性方面:可靠信號與不可靠信號;(2)與時間的關系上:實時信號與非實時信號。

(1) 可靠信號與不可靠信號

不可靠信號 :Linux下的不可靠信號問題主要指的是信號可能丟失。

可靠信號 :信號值位於SIGRTMIN和SIGRTMAX之間的信號都是可靠信號,可靠信號克服了信號可能丟失的問題。Linux在支持新版本的信號安裝函數sigation()以及信號發送函數sigqueue()的同時,仍然支持早期的signal()信號安裝函數,支持信號發送函數kill()。

對於目前linux的兩個信號安裝函數:signal()及sigaction()來說,它們都不能把SIGRTMIN以前的信號變成可靠信號(都不支持排隊,仍有可能丟失,仍然是不可靠信號),而且對SIGRTMIN以後的信號都支持排隊。這兩個函數的最大區別在於,經過sigaction安裝的信號都能傳遞信息給信號處理函數(對所有信號這壹點都成立),而經過signal安裝的信號卻不能向信號處理函數傳遞信息。對於信號發送函數來說也是壹樣的。

(2) 實時信號與非實時信號

前32種信號已經有了預定義值,每個信號有了確定的用途及含義,並且每種信號都有各自的缺省動作。如按鍵盤的CTRL ^C時,會產生SIGINT信號,對該信號的默認反應就是進程終止。後32個信號表示實時信號,等同於前面闡述的可靠信號。這保證了發送的多個實時信號都被接收。實時信號是POSIX標準的壹部分,可用於應用進程。非實時信號都不支持排隊,都是不可靠信號;實時信號都支持排隊,都是可靠信號。

發送信號的主要函數有:kill()、raise()、 sigqueue()、alarm()、setitimer()以及abort()。

調用成功返回 0;否則,返回 -1。

sigqueue()是比較新的發送信號系統調用,主要是針對實時信號提出的(當然也支持前32種),支持信號帶有參數,與函數sigaction()配合使用。

sigqueue的第壹個參數是指定接收信號的進程ID,第二個參數確定即將發送的信號,第三個參數是壹個聯合數據結構union sigval,指定了信號傳遞的參數,即通常所說的4字節值。

sigqueue()比kill()傳遞了更多的附加信息,但sigqueue()只能向壹個進程發送信號。sigqueue()比kill()傳遞了更多的附加信息,但sigqueue()只能向壹個進程發送信號。

inux主要有兩個函數實現信號的安裝: signal() sigaction() 。其中signal()在可靠信號系統調用的基礎上實現, 是庫函數。它只有兩個參數,不支持信號傳遞信息,主要是用於前32種非實時信號的安裝;而sigaction()是較新的函數(由兩個系統調用實現:sys_signal以及sys_rt_sigaction),有三個參數,支持信號傳遞信息,主要用來與 sigqueue() 系統調用配合使用,當然,sigaction()同樣支持非實時信號的安裝。sigaction()優於signal()主要體現在支持信號帶有參數。

消息隊列就是壹個消息的鏈表。可以把消息看作壹個記錄,具有特定的格式以及特定的優先級。對消息隊列有寫權限的進程可以向中按照壹定的規則添加新消息;對消息隊列有讀權限的進程則可以從消息隊列中讀走消息。消息隊列是隨內核持續的

消息隊列的內核持續性要求每個消息隊列都在系統範圍內對應唯壹的鍵值,所以,要獲得壹個消息隊列的描述字,只需提供該消息隊列的鍵值即可;

消息隊列與管道以及有名管道相比,具有更大的靈活性,首先,它提供有格式字節流,有利於減少開發人員的工作量;其次,消息具有類型,在實際應用中,可作為優先級使用。這兩點是管道以及有名管道所不能比的。同樣,消息隊列可以在幾個進程間復用,而不管這幾個進程是否具有親緣關系,這壹點與有名管道很相似;但消息隊列是隨內核持續的,與有名管道(隨進程持續)相比,生命力更強,應用空間更大。

信號燈與其他進程間通信方式不大相同,它主要提供對進程間***享資源訪問控制機制。相當於內存中的標誌,進程可以根據它判定是否能夠訪問某些***享資源,同時,進程也可以修改該標誌。除了用於訪問控制外,還可用於進程同步。信號燈有以下兩種類型:

int semop(int semid, struct sembuf *sops, unsigned nsops); semid是信號燈集ID,sops指向數組的每壹個sembuf結構都刻畫壹個在特定信號燈上的操作。

int semctl(int semid,int semnum,int cmd,union semun arg)

該系統調用實現對信號燈的各種控制操作,參數semid指定信號燈集,參數cmd指定具體的操作類型;參數semnum指定對哪個信號燈操作,只對幾個特殊的cmd操作有意義;arg用於設置或返回信號燈信息。

進程間需要***享的數據被放在壹個叫做IPC***享內存區域的地方,所有需要訪問該***享區域的進程都要把該***享區域映射到本進程的地址空間中去。系統V***享內存通過shmget獲得或創建壹個IPC***享內存區域,並返回相應的標識符。內核在保證shmget獲得或創建壹個***享內存區,初始化該***享內存區相應的shmid_kernel結構註同時,還將在特殊文件系統shm中,創建並打開壹個同名文件,並在內存中建立起該文件的相應dentry及inode結構,新打開的文件不屬於任何壹個進程(任何進程都可以訪問該***享內存區)。所有這壹切都是系統調用shmget完成的。

shmget()用來獲得***享內存區域的ID,如果不存在指定的***享區域就創建相應的區域。shmat()把***享內存區域映射到調用進程的地址空間中去,這樣,進程就可以方便地對***享區域進行訪問操作。shmdt()調用用來解除進程對***享內存區域的映射。shmctl實現對***享內存區域的控制操作。這裏我們不對這些系統調用作具體的介紹,讀者可參考相應的手冊頁面,後面的範例中將給出它們的調用方法。

註:shmget的內部實現包含了許多重要的系統V***享內存機制;shmat在把***享內存區域映射到進程空間時,並不真正改變進程的頁表。當進程第壹次訪問內存映射區域訪問時,會因為沒有物理頁表的分配而導致壹個缺頁異常,然後內核再根據相應的存儲管理機制為***享內存映射區域分配相應的頁表。

  • 上一篇:QQ如何創建興趣部落?
  • 下一篇:平均壽命MTTF怎麼計算
  • copyright 2024編程學習大全網