一 Linux進程間通信

進程間通信概念:進程是一個獨立的資源分配單位,不同進程之間有關聯,不能在一個進程中直接訪問另一個進程的資源 。

  • 進程和進程之間的資源是相互獨立的,一個進程不能直接訪問另外一個進程的資源 , 但是進程和進程之間不是相互獨立的 。
通信目的:
  • 數據傳輸:一個進程需要將它的數據發送給另一個進程 。
  • 資源共享:多個進程之間共享同樣的資源 。
  • 通知事件:一個進程需要向另一個或一組進程發送消息 , 通知某些或某個進程發生了某種事件(如進程終止時要通知父進程) 。
  • 進程控制:有些進程希望完全控制另一個進程的執行(如Debug進程),此時控制進程希望能夠攔截另一個進程的所有陷入和異常 , 并能夠及時知道它的狀態改變 。
如何實現進程通信?
要讓兩個不同的進程實現通信,前提條件是讓它們看到同一份資源 。所以要想辦法讓他們看到同一份資源,就需要采取一些手段,可以分為下面幾種 。
通信方式分類1.管道
  • 匿名管道pipe
  • 命名管道
2.System V IPC
  • System V 消息隊列
  • System V 共享內存
  • System V 信號量
3.POSIX IPC
  • 消息隊列
  • 共享內存
  • 信號量
  • 互斥量
  • 條件變量
  • 讀寫鎖
管道概念:我們把一個進程連接到另一個進程的一個數據流稱為一個“管道” 。
管道的特點:
  • 數據只能從管道的一端寫入,從另一端讀出
  • 寫入管道的數據遵循先入先出的原則
  • 管道所傳達的數據是無格式的 , 這要求管道的讀出方和寫入方必須事先約定好數據的格式
  • 管道不是普通的文件,不屬于某個文件系統,只存在于內存中
  • 管道讀數據是一次性的,數據一旦被讀走,它就從管道中拋棄,釋放空間
  • 管道是一種特殊的文件類型,會在應用層打開兩個文件描述符fd[0]對應的是寫端 , fd[1]對應的是讀端
  • 管道只能服務于有血緣關系的兩個進程

一 Linux進程間通信

文章插圖
匿名管道創建匿名管道-----pipe系統調用intpipe(int pidefd[2]);
功能:創建無名管道
參數:pipefd:為int類型數組的首地址 , 其存放了管道的文件描述符pipefd[0]、pipefd[1]
當一個管道建立的時候,他會創建兩個文件描述符fd[0]和fd[1] 。其中fd[0]固定用于讀管道,而fd[1]固定用于寫管道 。
返回值:成功:0失?。?1
  • 文件描述符就是操作系統為了高效管理已經打開文件所創建的一個索引(文件描述符在前面的文章介紹過)
匿名管道創建原理:
調用pipe函數后 , OS會在fd_array數組中分配兩個文件描述符給管道,一個是讀,一個是寫,并把這兩個文件描述符放到用戶傳進來的數組中 , fd[0]代表管道讀端,fd[1]代表管道寫端 。這樣一個管道就創建好了 。
一 Linux進程間通信

文章插圖
實例演示:
實例1:觀察兩個文件描述符的值
#include <stdio.h>#include <unistd.h>int main(){ int pipefd[2]; int ret = pipe(pipefd); if (ret == -1){// 管道創建失敗perror("make piep");//用于退出進程exit(-1); } // 成功返回0 // pipefd[0] 代表讀端 // pipefd[1] 代表寫端 printf("fd[0]:%d, fd[1]:%d\n", pipefd[0], pipefd[1]); return0;}運行結果如下:
一 Linux進程間通信

文章插圖
顯然,pipefd這個數組里面放的是兩個文件描述符,分別是3和4 , 因為0 , 1,2文件描述符在進程創建的時候會由系統自動創建 。
實例2:嘗試使用管道讀寫數據
#include <stdio.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>int main(){int pipefd[2];int ret = pipe(pipefd);if (ret == -1){// 管道創建失敗perror("make piep");exit(-1);}char buf[64] = "hello world";// 寫數據write(pipefd[1], buf, sizeof(buf)/sizeof(buf[0]));// 讀數據memset(buf,0,sizeof(buf));// 清空bufssize_t s = read(pipefd[0], buf, 11);buf[s] = '\0';printf("%s\n", buf);return 0;}//成功輸出hello world可以看見對管道的操作,實際上就是對兩個讀寫文件的操作,本質就是對文件的操作和使用 。
管道的本質Linux下一切皆文件,看待管道 , 其實時可以像看待文件一樣 。且管道和文件使用方法是一致的 。管道的生命周期隨進程 。

推薦閱讀