Linux进程间通信---管道

管道是Linux进程间通讯的一种手段,管道本质其实就是一个文件。管道的类型有两种:

  • 无名管道:用于父子进程的通信,或者兄弟进程之间的通信。
  • 有名管道:用于两个独立的进程间通信,有名管道也叫 FIFO。

1、无名管道

通过man 2 pipe 可以查看Linux手册中关于pipe介绍:

#include <unistd.h>
int pipe(int pipefd[2]);

通过 pipe(int pipefd[2]) 函数可以创建一个无名管道,无名管道是一种半双工(单向)的进程间通信方式。数组pipefd用于返回两个引用管道末端的文件描述符。
其中,pipefd[0]表示管道的读取端,pipefd[1]表示管道的写入端。写入管道写入端的数据由内核缓冲,直到读取端读取为止。在写入端需要关闭pipefd[0],在读取端需要关闭pipefd[1]。
返回值:0代表成功,-1代表失败。
在这里插入图片描述

1.1 代码示例
# include <unistd.h>
# include <stdio.h>
int main(){
        int pipefd[2];
        int res= pipe(pipefd);
        if(res<0){
                printf("create pipe fail");
                return -1;
        }

        pid_t pid=fork();
        if(pid == -1){
                printf("创建子进程失败");
        }else if(pid == 0){
                //子进程写数据,因此关闭读
                close(pipefd[0]);
                write(pipefd[1],"hello,i'm your child proc\n",26);
        }else{
                //父进程读数据,关闭写
                close(pipefd[1]);
                char buff[30];
                read(pipefd[0],buff, 26);
                printf("父进程收到数据:%s",buff);
        }
        return 0;
}

1.2 无名管道小结
  • 其本质是一个文件,但是其不在磁盘上,在内核缓冲区。
  • 数据一旦被读走,便不在管道中存在,不可反复读。
  • 采用半双工通信方式,如果需要双向通信可以创建两个管道。
  • 由于无名管道没有名字,文件在文件系统中不可见,而用fork产生的子进程会自动继承父进程的描述符 ,也就是无名管道的读写端,因此只能在父子,兄弟进程间使用。

2、有名管道

man 3 mkfifo 查看Linux关于mkfifo系统函数

#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);

mkfifo函数是一个系统调用,一旦你用这种方式创建了一个FIFO特殊文件,任何进程都可以像普通文件一样打开它进行读写。但是,它必须在两端同时打开,然后才能继续对其执行任何输入或输出操作。打开FIFO进行读取通常会被阻塞,直到其他进程打开相同的FIFO进行写入,反之亦然。
参数:

  • pathname:指定文件的path name
  • mode:指定文件的权限

返回值:成功返回0,失败返回-1。

2.1 代码示例

vim fifoTest.c 代码如下

#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
int main(){
        //创建一个fifo管道文件
        int res=mkfifo("fifo_temp", 0666);
        printf("进程已经启动...\n");
        if(res==-1){
                printf("create fifo file fail");
                return -1;
        }
        //以只读的方式打开文件
        int fd= open("fifo_temp",O_RDONLY);
        if(fd == -1){
                printf("open file fail");
                return -1;
        }
        char buff[30];
        read(fd,buff,30);
        printf("收到其他进程数据:%s\n",buff);
        close(fd);
        return 0;
}

vim fifoTest2.c 代码如下

#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
int main(){
        //以只写的方式打开文件
        int fd= open("fifo_temp",O_WRONLY);
        if(fd == -1){
                printf("open file fail");
                return -1;
        }
        write(fd,"你好呀!\n",8);
        printf("即将退出进程\n");
        close(fd);
        return 0;
}

打开两个终端,分别编译 fifoTest.c、fifoTest2.c。先执行fifoTest,会创建有名管道文件,等待其他进程写入。然后执行fifoTest2往文件中写入数据。
需要注意,上面的代码,在另一个进程没有启动时都会阻塞,这是因为使用了O_RDONLY 、O_WRONLY

  • O_RDONLY 以只读方式打开 FIFO,进程会阻塞,直到另一个进程往 FIFO 里面写数据
  • O_WRONLY 只写方式打开 FIFO,进程会阻塞,直到另一个进程往 FIFO 里面读数据
  • 如果不想阻塞可以使用O_RDWR 同时读写的方式打开 FIFO
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值