ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

管道通信Linux

管道通信Linux

管道通信是 Linux 中的一种进程间通信(IPC)机制,它允许一个进程将数据传输给另一个进程。管道通常用于父子进程或兄弟进程之间的通信。在 Linux 中,管道有两种主要类型:

  1. 无名管道(Unnamed Pipe)

  2. 有名管道(Named Pipe,FIFO)

1. 无名管道通信

无名管道是最常见的一种形式,它通常在父子进程之间进行通信。无名管道没有名字,且仅在创建它的进程的父子关系中有效。

使用无名管道的基本步骤:
  1. 创建管道:使用 pipe() 系统调用创建一个管道。该调用会返回两个文件描述符:一个用于读操作,一个用于写操作。

  2. 使用 fork() 创建子进程:父进程通过 fork() 创建子进程,父子进程可以共享管道。

  3. 读写数据:父进程将数据写入管道,子进程从管道读取数据。

示例代码:

以下是一个使用无名管道的简单示例,父进程向子进程发送消息:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>int main() {int pipefd[2];pid_t pid;char buffer[128];// 创建管道if (pipe(pipefd) == -1) {perror("pipe");exit(1);}pid = fork(); // 创建子进程if (pid == -1) {perror("fork");exit(1);}if (pid > 0) { // 父进程close(pipefd[0]); // 关闭管道的读端const char *msg = "Hello from parent!";write(pipefd[1], msg, strlen(msg) + 1); // 向管道写入数据close(pipefd[1]); // 关闭写端} else { // 子进程close(pipefd[1]); // 关闭管道的写端read(pipefd[0], buffer, sizeof(buffer)); // 从管道读取数据printf("Child process received: %s\n", buffer);close(pipefd[0]); // 关闭读端}return 0;
}

解释:

  1. pipe():创建一个管道,pipefd[0] 为读端,pipefd[1] 为写端。

  2. fork():创建子进程,父子进程可以共享管道文件描述符。

  3. 父进程:向管道的写端写入数据。

  4. 子进程:从管道的读端读取数据。

2. 有名管道通信(FIFO)

有名管道是另一种管道类型,它与无名管道的区别在于,它有一个名称,并且可以在不同的进程之间共享。由于有名管道在文件系统中有一个路径,因此任何进程都可以通过该路径访问它。

使用有名管道的基本步骤:
  1. 创建有名管道:使用 mkfifo() 创建有名管道文件。

  2. 打开管道:使用 open() 打开管道文件。

  3. 读写数据:通过管道文件描述符进行数据读写操作。

  4. 删除管道:当管道不再需要时,使用 unlink() 删除有名管道。

示例代码:

创建有名管道进行通信的两个程序示例,分别是写入程序和读取程序。

1. 写入程序(writer.c):
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>#define FIFO_NAME "/tmp/myfifo"int main() {int fd;const char *msg = "Hello from writer!";// 创建有名管道if (mkfifo(FIFO_NAME, 0666) == -1) {perror("mkfifo");exit(1);}// 打开管道进行写入fd = open(FIFO_NAME, O_WRONLY);if (fd == -1) {perror("open");exit(1);}// 向管道写入数据write(fd, msg, strlen(msg) + 1);close(fd); // 关闭管道return 0;
}
2. 读取程序(reader.c):
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>#define FIFO_NAME "/tmp/myfifo"int main() {int fd;char buf[128];// 打开管道进行读取fd = open(FIFO_NAME, O_RDONLY);if (fd == -1) {perror("open");exit(1);}// 从管道读取数据read(fd, buf, sizeof(buf));printf("Reader received: %s\n", buf);close(fd); // 关闭管道return 0;
}

解释:

  1. mkfifo():创建一个名为 /tmp/myfifo 的有名管道。

  2. writer.c:打开有名管道的写端,向其中写入消息。

  3. reader.c:打开有名管道的读端,读取消息并打印。

注意:

  • 阻塞行为:如果管道没有数据可读,read() 会阻塞,直到有数据可用。反之,写操作会阻塞直到管道有空间可以写入。

  • 管道删除:使用 unlink() 删除有名管道。

3. 管道的总结:

  • 无名管道:适用于父子进程之间的单向通信,通信是匿名的。

  • 有名管道:适用于不同进程之间的通信,并且它在文件系统中有一个路径,可以被其他进程访问。

通过管道通信,进程可以有效地交换数据。管道是 Linux 系统中一个非常重要的 IPC 机制,广泛用于多进程之间的数据传输。

返回列表