進程間通訊

進程間通訊(IPC,InterProcess Communication)是指在不一樣進程之間傳播或交換信息。進程間通訊的方式有以下幾種:html

1.管道通訊

特色:node

  1. 管道只容許具備血緣關係的進程間通訊,如父子進程間的通訊。ios

  2. 它是半雙工的(即數據只能在一個方向上流動),具備固定的讀端和寫端。
  3. 管道並不是是進程全部的資源,而是和套接字同樣,歸操做系統全部。能夠將它當作文件系統,但該文件系統只存在於內存當中。c++

原型數組

#include <unistd.h>
/* Create a one-way communication channel (pipe).
   If successful, two file descriptors are stored in PIPEDES;
   bytes written on PIPEDES[1] can be read from PIPEDES[0].
   Returns 0 if successful, -1 if not.  */
extern int pipe (int fd[2]) __THROW __wur;

參數的說明:函數

​ 字符數組fd是管道傳輸或者接收時用到的文件描述符,其中fd[0]是接收的時候使用的文件描述符,即管道出口;而fd[1]是傳輸的時候用到的文件描述符,即管道入口。測試

​ 爲了使數據能夠雙向傳遞,可使用兩個管道,一個管道負責進程1的寫和進程2的讀,另外一個管道負責一個進程1的讀和進程2的寫。測試程序以下:spa

#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#define BUF_SIZE 30

int main(){
    int fds1[2], fds2[2];
    /*
     *注意:
     * 此處不能寫char* str1 = "Who are you?";
     * 獲得的sizeof(str1)等於8,該值其實是指針的大小,並非字符串數組的大小
     * 這個時候要用strlen()函數(strlen的惟一標準是找‘\0’)
     * 系統函數返回值是char *(#include <string.h>)類型的每每會在末尾加上'\0'。
     * 要注意的是未初始化的狀況下,用strlen是不可行的
     **/
    char str1[] = "Who are you?";
    char str2[] = "Thank you for your message.";
    char buf[BUF_SIZE];
    pipe(fds1);     //建立兩個管道
    pipe(fds2);

    pid_t pid = fork();
    if(pid == 0){
        write(fds1[1], str1, sizeof(str1));
        read(fds2[0], buf, BUF_SIZE);
        printf("Child process copy the message: %s\n", buf);
    }else {
        read(fds1[0], buf, BUF_SIZE);
        printf("Parent Process copy the message: %s\n", buf);
        write(fds2[1], str2, sizeof(str2));
    }
    return 0;
}

2.FIFO操作系統

​ FIFO即命名管道,在磁盤上有對應的節點,但沒有數據塊—換言之,只是擁有一個名字和相應的訪問權限,經過mknode()系統調用或者mkfifo()函數來創建的。一旦創建,任何進程均可以經過文件名將其打開和進行讀寫,而不侷限於父子進程,固然前提是進程對FIFO有適當的訪問權。當再也不被進程使用時,FIFO在內存中釋放,但磁盤節點仍然存在。線程

/* Create a new FIFO named PATH, with permission bits MODE.  */
extern int mkfifo (const char *__path, __mode_t __mode)
     __THROW __nonnull ((1));

其中的 mode 參數與open函數中的 mode 相同。一旦建立了一個 FIFO,就能夠用通常的文件I/O函數操做它。

當 open 一個FIFO時,是否設置非阻塞標誌(O_NONBLOCK)的區別:

  • 若沒有指定O_NONBLOCK(默認),以只讀方式打開的FIFO要阻塞到其餘的某個程序以寫打開這個FIFO。一樣以只寫方式打開的FIFO要阻塞到其餘某個進程以讀方式打開該FIFO。
  • 若指定了O_NONBLOCK,則以只讀方式打開會馬上返回而不阻塞(不是出錯返回)。而以只寫方式打開,若以前沒有進程以讀方式打開這個FIFO則馬上出錯返回。

示例代碼:一個進程發送消息給另外一個進程

writefifo.cpp

#include <iostream>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>  // O_WRONLY
#include <time.h>   //time
#include <unistd.h>
using namespace std;

int main(){
    int fd;
    int n;
    char buf[1024];
    time_t tp;

    if( mkfifo("fifo1",  0666) < 0 && errno != EEXIST) //建立FIFO管道
    {
        perror("Create FIFO Faileed");
    }

    printf("I am %d process.\n", getpt());  //說明進程的ID

    if((fd = open("fifo1",O_WRONLY )) < 0){   //以只寫方式打開FIFO
        perror("Open FIFO failed");
        exit(1);
    }
    for (int i = 0; i < 10; ++i) {
        time(&tp);  //獲取當前系統時間
        n = sprintf(buf, "Process %d's time is %s",getpid(), ctime(&tp));
        printf("send message: %s", buf);
        if(write(fd, buf, n+1) < 0)
        {
            perror("write FIFO Failed");
            close(fd);
            exit(1);
        }
        sleep(1);
    }
    close(fd);
    return 0;
}

readfifo.cpp

#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>  // O_WRONLY
#include <time.h>   //time
#include <unistd.h>
using namespace std;

int main(){
    int fd;
    int len;
    char buf[1024];
    if((fd = open("fifo1",  O_RDONLY)) < 0){   //以只讀方式打開FIFO
        perror("Open FIFO failed");
        exit(1);
    }
    while ((len = read(fd, buf ,1024)) > 0)   //讀取FIFO管道
    {
       printf("Read message: %s", buf);
    }

    close(fd);
    return 0;
}

若是在writefifo.cpp中修改以下,設置非阻塞標誌:

if((fd = open("fifo1",O_WRONLY | O_NONBLOCK)) < 0){   //以只寫方式打開FIFO

若是先運行writefifo,在運行readfifo,則會出錯。

3. 消息隊列

​ 消息隊列,就是一個消息的鏈表,是一系列保存在內核的列表。用戶進程能夠向消息隊列添加消息,也能夠向消息隊列讀取消息。

特色:

  • 隊列獨立於發送與接收進程。進程終止時,消息隊列及其內容並不刪除。
  • 消息隊列能夠實現消息的隨機查詢,消息不必定要以先進先出的次序讀取,也能夠按消息的類型讀取。

4.共享內存

​ 共享內存(Shared Memory),指兩個或多個進程共享一個給定的存儲區。

5. 信號量

​ 信號量是一個計數器,能夠用來控制多個進程對共享資源的訪問。它常做爲一種鎖機制,防止某進程正在訪問共享資源時,其餘進程也訪問該資源。所以,主要做爲進程間以及同一進程內不一樣線程之間的同步手段。

6.套接字

​ 套解口也是一種進程間通訊機制,與其餘通訊機制不一樣的是,它可用於不一樣及其間的進程通訊。

參考資料

進程間通訊的方式——信號、管道、消息隊列、共享內存

進程間的五種通訊方式介紹

相關文章
相關標籤/搜索