linuxC-管道通信

管道是一种在操作系统中用于进程间通信的基本机制。它可以让一个进程的输出直接作为另一个进程的输入,实现这两个进程之间的数据传输。下面是管道的一些基本概念:

  1. 半双工通信:管道是一种半双工的通信机制,意味着数据只能在一个方向上流动。虽然管道可以同时进行读和写操作,但在任意给定的时间里,数据只能在一个方向上传输。

  2. 单向通信:管道是单向通信的,即它只能在一个方向上传输数据。如果需要双向通信,需要创建两个管道,一个用于父进程向子进程传输数据,另一个用于子进程向父进程传输数据。

  3. 亲缘关系:管道通常用于具有亲缘关系的进程之间通信,即它们有着共同的父进程。通常情况下,一个管道由一个父进程创建,并在子进程之间传递数据。

  4. 内核缓冲区:管道在内核中被实现为一个缓冲区,用于存储数据。这个缓冲区是一个环形队列,可以在其中存储一定数量的数据。当管道满了时,写入操作会被阻塞,直到有空间可用为止。同样,当管道为空时,读取操作也会被阻塞,直到有数据可用为止。

  5. 文件描述符:在 Linux 中,管道也被视为一种特殊的文件。每个进程都有一个文件描述符表,用于跟踪打开的文件和管道。当一个管道被创建时,系统会为其分配两个文件描述符,一个用于读取数据,另一个用于写入数据。

  6. 匿名管道:匿名管道是最常见的管道类型,它没有名字,只能在具有亲缘关系的进程之间使用。它由 pipe 系统调用创建,返回两个文件描述符,一个用于读取,一个用于写入。

  7. 关闭管道:当不再需要一个管道时,应该显式地关闭它。关闭一个管道将释放相关的系统资源,并通知系统不再使用该管道。

针对上述基本概念,提出以下问题:

在 Linux 中,管道是半双工的通信机制,如果对一个管道同时读和写会怎么样?

如果一个进程同时尝试在管道上进行读和写操作,可能会出现以下情况之一:

  1. 阻塞:如果一个进程在管道上进行写操作时,而另一个进程正在尝试读取数据,写入操作将被阻塞,直到另一个进程读取了数据为止。同样,如果一个进程在管道上进行读操作时,而另一个进程正在尝试写入数据,读取操作也会被阻塞,直到有数据可用为止。

  2. 死锁:如果两个进程同时尝试在管道上进行读和写操作,并且彼此都在等待对方完成操作,可能会导致死锁。例如,一个进程尝试读取数据,但需要等待另一个进程写入数据,而另一个进程同时尝试写入数据,但需要等待第一个进程读取数据。

  3. 部分数据:如果一个进程在管道上同时进行读和写操作,可能会导致部分数据的丢失或损坏。这是因为管道是一个先进先出的数据结构,如果同时进行读和写操作,数据可能会被覆盖或丢失。

有名管道和无名管道是什么?怎么建立?

有名管道(Named Pipe)和无名管道(Anonymous Pipe)都是在 Unix 和类 Unix 系统中用于进程间通信的机制,但它们有一些不同之处。

  1. 有名管道(Named Pipe)

    • 有名管道在文件系统中有一个路径名,可以像普通文件一样通过路径访问。
    • 可以持久存在,即使没有任何进程使用它。
    • 适合用于独立的进程之间进行通信。
    • 创建方法:
      • 使用 mkfifo 系统调用或者命令行工具 mkfifo 创建一个有名管道。
      • 进程可以通过路径名打开这个有名管道,就像打开普通文件一样。
      • 进程可以使用文件 I/O 操作来读取和写入有名管道,实现进程间的通信。
  2. 无名管道(Anonymous Pipe)

    • 无名管道没有文件系统中的文件名,是一种临时的通信方式。
    • 通常用于具有亲缘关系的父子进程之间通信。
    • 随着进程的终止而消失,不能持久存在。
    • 创建方法:
      • 父进程调用 pipe() 系统调用来创建一个管道,并获得两个文件描述符,一个用于读取数据,一个用于写入数据。
      • 父进程调用 fork() 系统调用创建一个子进程。
      • 子进程继承了父进程的文件描述符表,可以通过继承来共享管道。
      • 父进程通过管道写入数据,子进程通过管道读取数据,实现进程间的通信。

创建有名管道

mkfifo my_pipe

或者在 C 语言中使用 mkfifo 函数:

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

int main() {
    mkfifo("my_pipe", 0666); // 创建一个有名管道
    return 0;
}

 

 可以看到创建了一个my_pipe的管道,现在我们

向管道写入数据:

echo "Hello, world!" > my_pipe

使用读取管道:

cat my_pipe

 下面将演示多进程间创建有名管道,用于通信的示例

发送端:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

#define FIFO_FILE "my_pipe" // 定义管道文件名

int main() {
    int fd;
    char *message = "Hello, world!"; // 要写入管道的消息

    // 创建有名管道
    mkfifo(FIFO_FILE, 0666);

    // 打开管道文件
    fd = open(FIFO_FILE, O_WRONLY);
    if (fd == -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }

    // 向管道中写入数据
    write(fd, message, strlen(message) + 1);

    // 关闭管道文件
    close(fd);

    printf("Data sent to the pipe.\n");

    return 0;
}

接收端

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

#define FIFO_FILE "my_pipe" // 定义管道文件名

int main() {
    int fd;
    char buffer[1024];

    // 打开管道文件
    fd = open(FIFO_FILE, O_RDONLY);
    if (fd == -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }

    // 从管道中读取数据
    read(fd, buffer, sizeof(buffer));
    printf("Received message: %s\n", buffer);

    // 关闭管道文件
    close(fd);

    return 0;
}

编译运行

此时查看可以看到创建了一个管道

此时运行接收端

接收到消息队列中的消息

  • 8
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值