在Linux系统中,进程间通信(IPC)是一个重要的概念,它允许进程之间交换信息。管道和信号是两种常见的进程间通信机制。下面将详细介绍这两种机制的基本概念、使用场景和示例代码。
管道是一种半双工通信方式,允许数据在进程间单向传输。管道分为两种类型:匿名管道和有名管道(FIFO)。
概念:匿名管道是一种在有亲缘关系的进程间(如父子进程)进行单向数据传输的通信机制,存在于内存中,通常用于临时通信。如果需要双向通信,则一般需要两个管道。
使用场景:适用于有亲缘关系的进程间的简单数据传输,例如父子进程。
示例代码:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
int pipefd[2];
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
pid_t pid = fork();
if (pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
} else if (pid == 0) { // 子进程
close(pipefd[1]); // 关闭写端
char *msg = "Hello, Parent!";
write(pipefd[1], msg, strlen(msg));
close(pipefd[1]);
} else { // 父进程
close(pipefd[1]); // 关闭写端
char buffer[100];
read(pipefd[0], buffer, sizeof(buffer));
printf("Received: %s
", buffer);
close(pipefd[0]);
}
return 0;
}
概念:有名管道是一种特殊类型的文件,用于在不相关的进程之间实现通信。与匿名管道不同,有名管道在文件系统中具有一个实际的路径名。这允许任何具有适当权限的进程打开和使用它,而不仅限于有亲缘关系的进程。
使用场景:用于本机任何两个进程间的通信,特别是当这些进程没有血缘关系时。
示例代码:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#define FIFO "/tmp/my_fifo"
int main() {
const char *fifopath = FIFO;
mkfifo(fifopath, 0666); // 创建有名管道
char buf[1024];
int fd;
// Server
fd = open(fifopath, O_RDONLY);
while (1) {
read(fd, buf, sizeof(buf));
printf("Received: %s
", buf);
}
close(fd);
// Client
printf("enter message: ");
fgets(buf, sizeof(buf), stdin);
fd = open(fifopath, O_WRONLY);
write(fd, buf, strlen(buf) + 1);
close(fd);
return 0;
}
信号是一种用于进程间通信的机制,允许操作系统或一个进程向另一个进程发送简单的消息。信号主要用于传递关于系统事件的通知,例如中断请求、程序异常、或其他重要事件。
信号可以通过命令行(如 kill
命令)、函数调用(如 kill()
函数)或程序内部设置信号处理函数等方式发送和接收。
示例代码:
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
void signalHandler(int signum) {
printf("Received signal %d
", signum);
}
int main() {
signal(SIGINT, signalHandler);
while (1) {
printf("Running...
");
sleep(1);
}
return 0;
}
管道和信号是Linux系统中两种重要的进程间通信机制。管道适用于有亲缘关系的进程间的数据传输,而信号则用于不相关进程间的通知和事件处理。通过合理使用这两种机制,可以有效地实现进程间的信息交换和协同工作。