在Linux操作系统中,进程间通信(IPC)是一种允许不同进程之间交换数据和信息的机制。管道和信号是两种常见的IPC方法。
管道是一种半双工的通信方式,它允许一个进程将数据流式传输到另一个进程。管道通常用于具有亲缘关系的进程之间,例如父子进程。管道分为两种类型:
无名管道(Unnamed Pipe):无名管道是一种临时性的管道,它在创建它的进程之间建立连接。无名管道的生命周期仅限于创建它的进程及其子进程。
有名管道(Named Pipe):有名管道是一种持久性的管道,它在文件系统中有一个名称。任何进程都可以通过这个名称打开管道并与之通信。有名管道适用于无亲缘关系的进程之间的通信。
pipe()
系统调用创建一个无名管道。read()
和write()
系统调用从管道中读取数据和向管道中写入数据。close()
系统调用关闭管道。信号是一种异步的通信方式,它允许一个进程向另一个进程发送一个通知。信号通常用于处理系统事件,例如中断、终止等。进程可以自定义信号处理函数来响应特定的信号。
kill()
系统调用向进程发送信号。signal()
或sigaction()
系统调用设置信号处理函数。sigprocmask()
系统调用阻塞特定的信号。以下是一个简单的示例,演示了如何使用无名管道在父子进程之间进行通信:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main() {
int pipefd[2];
pid_t pid;
char buffer[128];
// 创建管道
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
// 创建子进程
pid = fork();
if (pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid == 0) {
// 子进程
close(pipefd[1]); // 关闭写端
// 读取数据
read(pipefd[0], buffer, sizeof(buffer));
printf("Child received: %s\n", buffer);
close(pipefd[0]);
} else {
// 父进程
close(pipefd[0]); // 关闭读端
// 写入数据
const char *message = "Hello from parent!";
write(pipefd[1], message, strlen(message) + 1);
close(pipefd[1]);
}
return 0;
}
在这个示例中,父进程创建了一个无名管道,并创建了一个子进程。父进程向管道中写入一条消息,子进程从管道中读取该消息并打印出来。
通过这种方式,进程间可以实现简单的数据交换。信号机制则提供了一种异步的通知方式,用于处理系统事件或自定义事件。