程式間通訊簡介

Koma_Wong發表於2018-08-25

程式間通訊

Linux幾乎支援全部UNIX程式間通訊方法,包括管道(有名管道和無名管道)、訊息佇列、共享記憶體、訊號量和套接字。其中前四個屬於同一臺機器下程式間的通訊,套接字則是用於網路通訊。

管道

  • 無名管道

    • 無名管道特點:

      • 無名管道是一種特殊的檔案,這種檔案只存在於記憶體中。

      • 無名管道只能用於父子程式或兄弟程式之間,必須用於具有親緣關係的程式間的通訊。

      • 無名管道只能由一端向另一端傳送資料,是半雙工方式,如果雙方需要同時收發資料需要兩個管道。

    • 相關介面:

      • int pipe(int fd[2]);

        • fd[2]:管道兩端用fd[0]和fd[1]來描述,讀的一端用fd[0]表示,寫的一端用fd[1]表示。通訊雙方的程式中寫資料的一方需要把fd[0]先close掉,讀的一方需要先把fd[1]給close掉。
  • 有名管道:

    • 有名管道特點:

      • 有名管道是FIFO檔案,存在於檔案系統中,可以通過檔案路徑名來指出。

      • 無名管道可以在不具有親緣關係的程式間進行通訊。

    • 相關介面:

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

        • pathname:即將建立的FIFO檔案路徑,如果檔案存在需要先刪除。

        • mode:和open()中的引數相同。

訊息佇列

共享記憶體

程式可以將同一段共享記憶體連線到它們自己的地址空間,所有程式都可以訪問共享記憶體中的地址,如果某個程式向共享記憶體內寫入資料,所做的改動將立即影響到可以訪問該共享記憶體的其他所有程式。

  • 相關介面

    • 建立共享記憶體:int shmget(key_t key, int size, int flag);

      成功時返回一個和key相關的共享記憶體識別符號,失敗範湖範圍-1。

      • key:為共享記憶體段命名,多個共享同一片記憶體的程式使用同一個key。

      • size:共享記憶體容量。

      • flag:許可權標誌位,和open的mode引數一樣。

    • 連線到共享記憶體地址空間:void *shmat(int shmid, void *addr, int flag);

      返回值即共享記憶體實際地址。

      • shmid:shmget()返回的標識。

      • addr:決定以什麼方式連線地址。

      • flag:訪問模式。

    • 從共享記憶體分離:int shmdt(const void *shmaddr);

      呼叫成功返回0,失敗返回-1。

      • shmaddr:是shmat()返回的地址指標。
  • 其他補充

    共享記憶體的方式像極了多執行緒中執行緒對全域性變數的訪問,大家都對等地有權去修改這塊記憶體的值,這就導致在多程式併發下,最終結果是不可預期的。所以對這塊臨界區的訪問需要通過訊號量來進行程式同步。

    但共享記憶體的優勢也很明顯,首先可以通過共享記憶體進行通訊的程式不需要像無名管道一樣需要通訊的程式間有親緣關係。其次記憶體共享的速度也比較快,不存在讀取檔案、訊息傳遞等過程,只需要到相應對映到的記憶體地址直接讀寫資料即可。

訊號量

在提到共享記憶體方式時也提到,程式共享記憶體和多執行緒共享全域性變數非常相似。所以在使用記憶體共享的方式是也需要通過訊號量來完成程式間同步。多執行緒同步的訊號量是POSIX訊號量, 而在程式裡使用SYSTEM V訊號量。

  • 相關介面

    • 建立訊號量:int semget(key_t key, int nsems, int semflag);

      建立成功返回訊號量識別符號,失敗返回-1。

      • key:程式pid。

      • nsems:建立訊號量的個數。

      • semflag:指定訊號量讀寫許可權。

    • 改變訊號量值:int semop(int semid, struct sembuf *sops, unsigned nsops);

      我們所需要做的主要工作就是串講sembuf變數並設定其值,然後呼叫semop,把設定好的sembuf變數傳遞進去。

      struct sembuf結構體定義如下:

      struct sembuf{
          short sem_num;
          short sem_op;
          short sem_flg;
      };

      成功返回訊號量識別符號,失敗返回-1。

      • semid:訊號量集識別符號,由semget()函式返回。

      • sops:指向struct sembuf結構的指標,先設定好sembuf值再通過指標傳遞。

      • nsops:進行操作訊號量的個數,即sops結構變數的個數,需大於或等於1。最常見設定此值等於1,只完成對一個訊號量的操作。

    • 直接控制訊號量資訊:int semctl(int semid, int semnum, int cmd, union semun arg);

      • semid:訊號量集識別符號。

      • semnum:訊號量集陣列上的下標,表示某一個訊號量。

      • arg:union semun型別。

輔助命令

ipcs命令用於報告共享記憶體、訊號量和訊息佇列資訊。

  • ipcs -a:列出共享記憶體、訊號量和訊息佇列資訊。

  • ipcs -l:列出系統限額。

  • ipcs -u:列出當前使用情況。

套接字

相關文章