085. 使用C语言实现简单的进程间通信
在C语言中,进程间通信(IPC)是多个进程之间交换数据的一种方式。Linux系统提供了多种IPC机制,包括管道(Pipes)、消息队列(Message Queues)、共享内存(Shared Memory)和信号(Signals)。以下将分别实现这些简单的IPC机制。
1. 管道(Pipes)
管道是一种简单的IPC机制,用于在父子进程之间单向通信。匿名管道只能用于具有亲缘关系的进程之间,而命名管道(FIFO)可以用于不相关的进程之间。
示例代码:匿名管道
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
int pipefds[2];
pid_t pid;
// 创建管道
if (pipe(pipefds) == -1) {
perror("pipe");
exit(1);
}
pid = fork();
if (pid == -1) {
perror("fork");
exit(1);
}
if (pid == 0) { // 子进程
close(pipefds[1]); // 关闭写端
char buffer[80];
read(pipefds[0], buffer, sizeof(buffer)); // 从管道读取数据
printf("子进程收到的消息:%s\n", buffer);
close(pipefds[0]); // 关闭读端
} else { // 父进程
close(pipefds[0]); // 关闭读端
char message[] = "Hello, World!";
write(pipefds[1], message, sizeof(message)); // 向管道写入数据
close(pipefds[1]); // 关闭写端
wait(NULL); // 等待子进程结束
}
return 0;
}
示例运行
输入:
无输入
输出:
子进程收到的消息:Hello, World!
2. 消息队列(Message Queues)
消息队列是一种更高级的IPC机制,允许不相关的进程之间交换消息。消息队列可以存储多个消息,每个消息都有一个类型和数据。
示例代码:消息队列
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <unistd.h>
// 消息结构
struct message {
long mtype;
char mtext[80];
};
int main() {
key_t key;
int msgid;
struct message msg;
// 创建消息队列
key = ftok("queuefile", 65);
msgid = msgget(key, 0666 | IPC_CREAT);
pid_t pid = fork();
if (pid == -1) {
perror("fork");
exit(1);
}
if (pid == 0) { // 子进程
msg.mtype = 1;
msgrcv(msgid, &msg, sizeof(msg.mtext), 1, 0);
printf("子进程收到的消息:%s\n", msg.mtext);
msgctl(msgid, IPC_RMID, NULL); // 删除消息队列
} else { // 父进程
msg.mtype = 1;
strcpy(msg.mtext, "Hello, World!");
msgsnd(msgid, &msg, sizeof(msg.mtext), 0);
wait(NULL); // 等待子进程结束
}
return 0;
}
示例运行
输入:
无输入
输出:
子进程收到的消息:Hello, World!
3. 共享内存(Shared Memory)
共享内存允许多个进程共享同一块内存区域,从而实现高效的数据交换。
示例代码:共享内存
#include <stdio.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
int main() {
key_t key;
int shmid;
char* data;
// 创建共享内存
key = ftok("shmfile", 65);
shmid = shmget(key, 1024, 0666 | IPC_CREAT);
pid_t pid = fork();
if (pid == -1) {
perror("fork");
exit(1);
}
if (pid == 0) { // 子进程
data = shmat(shmid, (void*)0, 0);
printf("子进程收到的消息:%s\n", data);
shmdt(data); // 分离共享内存
shmctl(shmid, IPC_RMID, NULL); // 删除共享内存
} else { // 父进程
data = shmat(shmid, (void*)0, 0);
strcpy(data, "Hello, World!");
wait(NULL); // 等待子进程结束
}
return 0;
}
示例运行
输入:
无输入
输出:
子进程收到的消息:Hello, World!
4. 信号(Signals)
信号是一种软件中断,用于在进程之间传递异步事件。信号可以用于简单的进程间通信,但通常用于错误处理和中断处理。
示例代码:信号
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void signal_handler(int sig) {
printf("收到信号:%d\n", sig);
}
int main() {
signal(SIGINT, signal_handler); // 设置信号处理函数
printf("按Ctrl+C发送SIGINT信号...\n");
while (1) {
sleep(1); // 休眠1秒
}
return 0;
}
示例运行
输入:
按Ctrl+C发送SIGINT信号...
输出:
收到信号:2
5. 总结
通过实现简单的进程间通信机制,可以理解不同IPC方法的特点和适用场景。管道适用于父子进程之间的单向通信,消息队列和共享内存适用于不相关进程之间的通信,而信号则用于简单的异步事件处理。在实际开发中,可以根据具体需求选择合适的IPC机制。
视频讲解
BiliBili: 视睿网络-哔哩哔哩视频 (bilibili.com)