进程间的通信(管道)
进程间的通信(Inter-Process Communication,IPC) 是指在不同进程之间传递或交换信息。这些进程可以是运行在同一台计算机上,也可以是通过网络连接的不同计算机上的。由于不同的进程拥有不同的内存空间,因此不能通过简单地直接访问对方的内存空间来实现信息的传递或共享,需要通过一些特殊的方法来实现。
管道
- 匿名管道(Anonymous Pipe):
- 匿名管道是Linux中最基本的管道类型,它没有名字,通常用于父进程和子进程之间的通信。
- 当使用
pipe()
系统调用时,会创建一个匿名管道。这个系统调用返回两个文件描述符:一个用于写(通常是pipefd[1]
),另一个用于读(通常是pipefd[0]
)。 - 父进程和子进程分别通过这两个文件描述符进行读写操作。
- 匿名管道是半双工的,即数据只能在一个方向上流动。
- 命名管道(Named Pipe 或 FIFO):
- 命名管道也被称为FIFO(First In First Out),它有一个名字,并允许无亲缘关系的进程之间进行通信。
- 使用
mkfifo
命令或mknod
命令可以创建命名管道。 - 与匿名管道不同,命名管道是持久的,即使创建它们的进程已经终止,它们仍然存在,直到被显式删除。
- 命名管道可以是阻塞的或非阻塞的,这取决于进程如何打开它们。
匿名管道代码测试例
/*******************************************************************
*
* file name: fifo_text1.c
* author : [email protected]
* date : 2024/06/01
* function : 创建了一个匿名管道,测试子进程向匿名管道写入数据,父进程读取匿名管道中的数据,以实现进程间
* 的通信
* note : None
*
* CopyRight (c) 2023-2024 [email protected] All Right Reseverd
*
* *****************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main() {
int pipefd[2]; // 定义文件描述符数组,pipefd[0]用于读,pipefd[1]用于写
// 创建匿名管道
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
// 创建子进程
pid_t pid = fork();
if (pid == -1) {
// 创建子进程失败
perror("fork");
exit(EXIT_FAILURE);
}
if (pid == 0) {
// 子进程
close(pipefd[0]); // 关闭读端
// 向管道写入数据
const char *message = "Hello from child process!\n";
write(pipefd[1], message, strlen(message));
close(pipefd[1]); // 关闭写端
exit(EXIT_SUCCESS);
} else {
// 父进程
close(pipefd[1]); // 关闭写端
// 从管道读取数据
char buffer[1024];
ssize_t bytesRead = read(pipefd[0], buffer, sizeof(buffer) - 1);
if (bytesRead > 0) {
buffer[bytesRead] = '\0'; // 添加字符串终止符
printf("Received from child: %s", buffer);
}
close(pipefd[0]); // 关闭读端
wait(NULL); // 等待子进程结束
}
return 0;
}
命名管道代码示例
/*******************************************************************
*
* file name: fifi_text2.c
* author : [email protected]
* date : 2024/06/01
* function : 将数据写入有名管道中的数据实现进程间的通信
* note : None
*
* CopyRight (c) 2023-2024 [email protected] All Right Reseverd
*
* *****************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#defined FIFO_PATH "./fifo1"
int main() {
// 创建有名管道
if (mkfifo(fifo_path, 0666) == -1) {
perror("mkfifo");
exit(EXIT_FAILURE);
}
// 打开有名管道以写入数据
int fd = open(fifo_path, O_WRONLY);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
// 写入数据到有名管道
const char *message = "Hello, Named Pipe!";
ssize_t bytes_written = write(fd, message, strlen(message) + 1);
if (bytes_written == -1) {
perror("write");
exit(EXIT_FAILURE);
}
// 关闭管道
close(fd);
// 删除有名管道(可选)
unlink(fifo_path);
return 0;
}
/*******************************************************************
*
* file name: pipe_text.c
* author : [email protected]
* date : 2024/06/1
* function : 读取有名管道中的数据实现进程间的通信
* note : None
*
* CopyRight (c) 2023-2024 [email protected] All Right Reseverd
*
* *****************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#define MAX_BUF 256
#defined FIFO_PATH "./fifo1"
int main() {
// 打开有名管道以读取数据
int fd = open(fifo_path, O_RDONLY);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
// 读取数据
char buffer[MAX_BUF];
ssize_t bytes_read = read(fd, buffer, MAX_BUF - 1);
if (bytes_read == -1) {
perror("read");
exit(EXIT_FAILURE);
}
// 确保字符串以null终止
buffer[bytes_read] = '\0';
// 打印读取到的数据
printf("Received: %s\n", buffer);
// 关闭管道
close(fd);
return 0;
}
管道是Linux中一种简单而有效的进程间通信机制,它允许进程之间通过内存中的管道进行数据的读写操作,匿名管道经常用于父进程和子进程之间的通信,特别是当子进程需要执行一些操作并将结果返回给父进程时,而命名管道可以用于更复杂的场景,例如多个进程之间的数据交换或服务器与客户端之间的通信。
如果代码用法有什么问题,请将问题发至网易邮箱 [email protected],作者将及时改正,欢迎与各位老爷交流讨论。
麻烦三连加关注!!!!
比心
标签:buffer,pipefd,通信,管道,进程,匿名,include From: https://www.cnblogs.com/zkbklink/p/18231793