學習IPC進程間通訊的總結(第八週)

 


 

10月24日晚上,回到宿舍準備寫這周的總結時,看了下課表忽然意識到這已是第八週,不得不說時間過得真快,與前兩年輕鬆的、無任務的課程相比,今年真是充實了太多!這也許是感受時間過得快的緣由,可是最近我也遇到了許多問題,當接觸的知識多了之後,發現本身要學的東西太多了,僅僅上課所學遠遠不夠,因此課後自學了一些課程,遇到的問題一是本身好高騖遠,總想急於求成,這看一點那看一點,沒有系統的全面的琢磨一本書,問題二:對於應用方面的知識學到手很快,但也會很快的忘記,到了應用時只記得一些概念了。對於這兩個問題,我進行了一些思考,施行以下:在學習的時候把重要的知識點記錄下來,我本身用的是有道雲筆記,新學到的知識或者 不會的問題,經過查閱資料解決的 都把他們記錄下來。效果不錯,每週均可以回顧查看。最近開設了本身的博客,寫博客是爲了總結每日所學,反思自身。古人說「吾日三省吾身」仍是頗有道理的。在本身博客中進行知識總結,以及每週每個月思考回顧總結,感受收穫良多。另外,本身也有了一些新的感悟,咱們往往感嘆許多技術大牛,博客名人如何厲害,其實咱們本身就能夠成爲技術上的leader,其一就是知識及項目經驗的不斷積累,其二,我認爲就是學習知識時對細節的把握,其三,能夠鍥而不捨,不斷的學習新技術,平時不斷的回顧,「溫故而知新」。說了不少,實踐爲真,接下來還要繼續本身的求知之旅。好了下面進行本週的知識總結。shell

 


 

本週進行了兩天的授課,和三天的實訓;主要講解了Linux進程與線程編程中的進程之間的通訊這一方面知識。總結以下:編程

 

 

 

 

下面是我對這幾種方法的理解:異步

一、無名管道(pipe ):管道是一種半雙工的通訊方式,數據只能單向流動,並且只能在父子進程間通訊。管道的緩衝區是有限的(管道存在於內存中,在管道建立時,爲緩衝區分配一個頁面大小);管道所傳送的是無格式字節流,要求管道的讀出方和寫入方必須事先約定好數據的格式。函數

 

 

 

 

進程A   fork()出一個進程B,進程B是複製進程A的副本,獲得了進程A的所有資源,所以,進程B也會有指向pd[1]的寫指針,指向pd[0]的讀指針。學習

因此管道這樣設計:spa

  進程A:線程

    Close( fd [0]);設計

    Write( fd[1],buffer,sizeof(buffer));指針

  進程B:blog

    Close(fd [1]);

    Read( fd[0],buf,sizeof(buf));

 

二、命名管道(fifo):命名管道也是半雙工的通訊方式,可是它容許無親緣關係進程間的通訊。嚴格遵循先進先出(first in first out),對管道及FIFO的讀老是從開始處返回數據,對它們的寫則把數據添加到末尾。諸如不支持lseek()等文件定位操做。

 

(1)管道應用的一個重大限制是它沒有名字,所以,只能用於具備親緣關係的進程間通訊,在有名管道(named pipe或FIFO)提出後,該限制獲得了克服。FIFO不一樣於管道之處在於它提供一個路徑名與之關聯,以FIFO的文件形式存在於文件系統中。這樣,即便與FIFO的建立進程不存在親緣關係的進程,只要能夠訪問該路徑,就可以彼此經過FIFO相互通訊(可以訪問該路徑的進程以及FIFO的建立進程之間),所以,經過FIFO不相關的進程也能交換數據。值得注意的是,FIFO嚴格遵循先進先出(first in first out),對管道及FIFO的讀老是從開始處返回數據,對它們的寫則把數據添加到末尾。它們不支持諸如lseek()等文件定位操做。

(2)有名管道的建立

int mkfifo(const char * pathname, mode_t mode);

該函數的第一個參數是一個普通的路徑名,也就是建立後FIFO的名字。第二個參數與打開普通文件的open()函數中的mode 參數相同。 若是mkfifo的第一個參數是一個已經存在的路徑名時,會返回EEXIST錯誤,因此通常典型的調用代碼首先會檢查是否返回該錯誤,若是確實返回該錯誤,那麼只要調用打開FIFO的函數就能夠了。通常文件的I/O函數均可以用於FIFO,如close、read、write等等。

(3)有名管道的打開規則

有名管道比管道多了一個打開操做:open。

FIFO的打開規則:

若是當前打開操做是爲讀而打開FIFO時,若已經有相應進程爲寫而打開該FIFO,則當前打開操做將成功返回;不然,可能阻塞直到有相應進程爲寫而打開該FIFO(當前打開操做設置了阻塞標誌);或者,成功返回(當前打開操做沒有設置阻塞標誌)。

若是當前打開操做是爲寫而打開FIFO時,若是已經有相應進程爲讀而打開該FIFO,則當前打開操做將成功返回;不然,可能阻塞直到有相應進程爲讀而打開該FIFO(當前打開操做設置了阻塞標誌);或者,返回ENXIO錯誤(當前打開操做沒有設置阻塞標誌)。

小結:

管道經常使用於兩個方面:(1)在shell中時常會用到管道(做爲輸入輸入的重定向),在這種應用方式下,管道的建立對於用戶來講是透明的;(2)用於具備親緣關係的進程間通訊,用戶本身建立管道,並完成讀寫操做。

FIFO能夠說是管道的推廣,克服了管道無名字的限制,使得無親緣關係的進程一樣能夠採用先進先出的通訊機制進行通訊。

管道和FIFO的數據是字節流,應用程序之間必須事先肯定特定的傳輸"協議",採用傳播具備特定意義的消息。要靈活應用管道及FIFO,理解它們的讀寫規則是關鍵。

 

 

三、消息隊列(message queue ):消息隊列是由消息的鏈表,存放在內核中並由消息隊列標識符標識。能夠用非先進先出方式處理;消息隊列是異步通訊的;消息隊列有大小限制,一般只用於小數據量的發送;只適用於單臺主機的進程間通訊;

消息隊列:

提供從一個進程向另外一個進程發送一個數據塊的方法

 

int msgget(key_t key,int msgflg);

int msgctl(int magid,int cmd,struct msgid_ds *buf);

int msgsnd(int msgid,void *msg_ptr,size_t msg_sz,int msgflag);

int msgrcv(int msgid,void *msg_ptr,size_t msg_sz,long int msg_type,int msgflag);

 

 

 

四、共享內存( shared memory):共享內存就是映射一段能被其餘進程所訪問的內存,這段共享內存由一個進程建立,但多個進程均可以訪問。共享內存是最快的IPC方式。效率高,進程能夠直接讀寫內存,而不須要任何數據的拷貝;在共享內存段中都是以字符串的默認結束符爲一條信息的結尾。每一個進程在讀寫時都遵照這個規則,就不會破壞數據的完整性。

 

共享內存

容許兩個不像關的進程訪問同一個邏輯地址

一、int shmget(key_t key,size_t size,int shmflag);

二、void *shmat(int shm_id,const void *shm_addr,int shm_flag);

三、int shmctl(int shm_id,int cmd,struct shmid_ds *buf);

四、int shmdt(const void *shm_addr);

 

 

5.信號量(semophore ):信號量是一個計數器,能夠用來控制多個進程對共享資源的訪問。主要做爲進程間以及同一進程內不一樣線程之間的同步手段。二元信號量:與Mutex相似。

信號量:

int semget(key_t key,int num_sems,int sem_flgs);

int semctl(int sem_id,int sem_num,int command...);

int semop(int sem_id,struct sembuf *sem_ops,size_t num_sem_ops);

每一個函數的功能和參數的意義在手冊中都能找到。

 

 

一、semge建立一個信號量或者獲取一個已知信號量的鍵

key:不相關的進程能夠經過他來訪問同一個信號量

num_sems:須要的信號量數目。幾乎老是1

sem_flags:一組標誌,例如IPC_CREAT;

返回值是信號量標誌符,給其餘信號量函數使用

 

 

二、semctl:

sem_id:信號量標誌符,semget的返回值

sem_ops:信號量編號,通常取0

command:   就不解釋了,在手冊中有詳細的解釋,我就偷偷懶吧。

 

三、semop

用於改變信號量的值

struct sembuf{

short sen_nums;            //信號量編號,通常取0

short sem_op;               //通常-1是P操做,1是V操做

short sem_flag;            //一般設置爲UNDO

}

相關文章
相關標籤/搜索