Linux 進程間通信(1) -- 管道

進程間通信(IPC - InterProcess Communication)

通信的方式有很多: 文件, 管道, 信號, 共享內存, 消息隊列, 套接字, 命名管道等等;

  • 但是由于設計缺陷現(xiàn)在常用的有:
    1.管道(簡單, 默認匿名管道, 還有有名管道)
    2.信號(開銷小, 但是如果不是做系統(tǒng)編程一般不用, 因為缺點大于有點, 比如有沒有收到無法確認)
    3.共享映射區(qū)(無血緣關系之間)
    4.本地套接字(最穩(wěn)定)

一、 管道(匿名, pipe)

  1. 介紹:
    本質是內核緩沖區(qū)
    特點: 兩端, 對應讀和寫; 是一個偽文件, 進程結束, 緩沖區(qū)消失
    原理: 環(huán)形隊列實現(xiàn)(取余的算法...)
    管道尺寸默認大小 4k (ulimit -a 查看pipe size; 或者函數(shù): long fpathconf(int fd, int name);)
    局限: 不能多次訪問, 匿名管道只能是有血緣關系的進程間通信(fifo有名管道可以實現(xiàn)無血緣關系間通信)
  2. 創(chuàng)建 int pipe(int fildes[2]);
#include <stdio.h>
#include <unistd.h>
int main(int argc, const char* argv[]) {
    int fd[2];
    int ret = pipe(fd);
    if(ret == -1) {
        perror("pipe error");
        exit(1);
    }
    printf("fd[0] = %d\n", fd[0]);
    printf("fd[1] = %d\n", fd[1]);
    return 0;
}
  1. 父子進程通信(使用匿名管道)
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
int main(int argc, const char* argv[]) {
    // 1. 創(chuàng)建管道
    int fd[2];
    int ret = pipe(fd);
    if(ret == -1) {
        perror("pipe error");
        exit(1);
    }

    // 2. 創(chuàng)建子進程
    pid_t pid = fork();
    if(pid == -1) {
        perror("fork error");
        exit(1);
    }
    // 3. 通信
    // 父進程 寫操作
    if(pid > 0) {
        // parent process
        // 關閉讀端
        close(fd[0]);
        char* p = "你是子進程嗎?";
        sleep(2); //父進程寫, 但是先sleep2秒, 此時子進程會等父進程寫進去之后再讀, 因為read函數(shù)是阻塞函數(shù), 但是這是管道的阻塞屬性
        //將其設置成非阻塞,  使用fcntl 函數(shù)
        write(fd[1], p, strlen(p)+1);
        close(fd[1]);
        wait(NULL);
    } else if(pid == 0) { // 子進程 讀操作
        // 關閉寫端
        close(fd[1]);
        char buf[512];
        int len = read(fd[0], buf, sizeof(buf));
        printf("%s, %d\n", buf, len);
        close(fd[0]);
    }
    return 0;
}
  1. 管道的讀寫行為
  • 讀操作:
    管道中有數(shù)據(jù): read正常運行, 返回讀取到的字節(jié)數(shù)
    管道中無數(shù)據(jù): 1. 寫端關閉, 相當于文件讀取到了文件尾部, read返回0; 2.寫端沒有關閉, read阻塞
  • 寫操作:
    管道讀端關閉: 異常情況, 管道破裂, 異常退出, 通過13號信號(SIGPIPE)
    管道讀端沒有關閉: 1. 緩沖區(qū)沒有滿, 正常寫; 2. 緩沖區(qū)已滿, 寫阻塞

補充:

當實現(xiàn)父子間進程通信時, 如果需要將終端(/dev/tty--)上輸出的數(shù)據(jù), 或者其他地方的數(shù)據(jù)寫進管道時, 需要將終端對應的標準輸出文件描述符重定向到寫端, 使用函數(shù): int dup2(int fildes, int fildes2);

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容