管道通信原理简述

本文详细介绍了进程间通信的两种方式:无名管道和有名管道(FIFO)。无名管道适用于父子进程或兄弟进程间的半双工通信,而有名管道则允许无关进程间的数据交换,它是一种特殊类型的文件存在于文件系统中。文章通过代码示例展示了如何创建、读写无名管道和有名管道,并解释了在打开FIFO时阻塞与非阻塞模式的区别。
摘要由CSDN通过智能技术生成

原文链接:进程间通信(IPC)介绍_tangtang_yue的博客-CSDN博客_进程间通信(ipc)介绍

一.无名管道(pipe)

1.特点:

  1. 它是半双工的(即数据只能在一个方向上流动),具有固定读端和写端。

  2. 它只能用于具有亲缘关系的进程之间的通信(也是父子进程或者兄弟进程之间)。

  3. 它可以看成是一种特殊的文件,对于它的读写也可以使用普通的read、write 等函数。但是它不是普通的文件,并不属于其他任何文件系统,并且只存在于内存中。

2.原型:

1 #include <unistd.h>
2 int pipe(int fd[2]);    // 返回值:若成功返回0,失败返回-1

当一个管道建立时,它会创建两个文件描述符:fd[0]为读而打开,fd[1]为写而打开。

3.代码实现:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <string.h>

//       int pipe(int pipefd[2]);

int main(int argc, char *argv[])
{
        int fd[2];
        char readBuf[128];
        memset(readBuf, 0, sizeof(readBuf));
        pid_t pid;

        if (pipe(fd) == -1){
                printf("creat pipe failed!\n");
        }

        pid = fork();

        if (pid < 0){
                printf("failed to creat child process!\n");
        }
        else if (pid > 0){
                printf("creat parent process successfuly!\n");
                close(fd[0]);   //关闭通道读写操作前后关闭都可  
                write(fd[1], "hello from father", strlen("hello from father"));
                //close(fd[0]);
                wait(NULL);
        }
        else {
                printf("creat child process successfully!\n");
                close(fd[1]);
                read(fd[0], readBuf, 128);
                //close(fd[1]);                 
                printf("read: %s\n", readBuf);
                exit(0);
        }

        return 0;
}

写东西时必须关闭读端,先关闭读端再写与先写再关闭读端都可以,读东西也是同样如此。

运行结果:

一.明名管道(FIFO)

1.特点:

  1. FIFO可以在无关的进程之间交换数据,与无名管道不同。

  2. FIFO有路径名与之相关联,它是一种文件类型,它以一种特殊设备文件形式存在于文件系统中。

2.原型:

1 #include <sys/stat.h>
2 // 返回值:成功返回0,出错返回-1
3 int mkfifo(const char *pathname, mode_t mode);

其中的 mode 参数与open函数中的 mode 相同。一旦创建了一个 FIFO,就可以用一般的文件I/O函数操作它。

当 open 一个FIFO时,是否设置非阻塞标志(O_NONBLOCK)的区别:

  • 若没有指定O_NONBLOCK(默认),只读 open 要阻塞到某个其他进程为写而打开此 FIFO。类似的,只写 open 要阻塞到某个其他进程为读而打开它。

  • 若指定了O_NONBLOCK,则只读 open 立即返回。而只写 open 将出错返回 -1 如果没有进程已经为读而打开该 FIFO,其errno置ENXIO。

3.创建FIFO管道:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>

//       int mkfifo(const char *pathname, mode_t mode);
int main(int argc, char *argv[])
{
        if ((mkfifo("./file", 0600) == -1) && errno != EEXIST){
                printf("creat fifo failuer!\n");
                perror("why");
        }

        return 0;
}

4.代码实现读操作:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>


//       int mkfifo(const char *pathname, mode_t mode);
int main(int argc, char *argv[])
{
        int fd;
        int cnt = 0;
        int n_read = 0;
        char readBuf[64];
        memset(readBuf, 0, sizeof(readBuf));

        if ((mkfifo("./file", 0600) == -1) && errno != EEXIST){
                printf("creat fifo failuer!\n");
                perror("why");
        }

        fd = open("./file", O_RDONLY);
        while(1){
                cnt++;
                n_read = read(fd, readBuf, 64);
                printf("read %d bytes, context: %s\n", n_read, readBuf);

                if (cnt == 5){
                        break;
                }
        }

        return 0;
}

此时运行read,该进程会阻塞,因为打开FIFO的时候,默认是阻塞的,如下图:

 5.代码实现写操作:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
        int fd;
        int cnt = 0;
        char *str = "message from fifo";

        fd = open("./file", O_WRONLY);
        printf("write open success\n");

        while(1){
                write(fd, str, strlen(str));
                sleep(1);
                cnt++;

                if (cnt == 5){
                        break;
                }
        }

        return 0;
}

运行write.c后,read可执行文件的进程就不会阻塞了,开始从fd里读取数据到readBuf里,并最终打印出来。同时,再读写两端代码中,都设置了各自读写5次后进程终止,运行结果如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值