【C语言练习】085. 使用C语言实现简单的进程间通信
本文介绍了使用C语言实现四种进程间通信(IPC)的方法:管道、消息队列、共享内存和信号。管道适用于父子进程单向通信;消息队列支持无关联进程交换结构化消息;共享内存提供高效的数据共享;信号用于异步事件通知。每种方法均附有C代码示例和运行结果,展示了"Hello, World!"的基础通信实现。文中还总结了不同IPC机制的特点和适用场景,为系统编程、嵌入式开发等需要进程协作的场景提
085. 使用C语言实现简单的进程间通信
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机制。
C语言实现的简单进程间通信(IPC)在多个领域有广泛应用,尤其在需要高效、低延迟或跨平台交互的场景中。以下是常见应用领域及实现方式:
系统编程与操作系统
操作系统内核中频繁使用IPC机制协调进程。例如,Linux系统调用通过管道或消息队列传递控制信息。C语言直接调用系统API实现高效通信。
// 匿名管道示例
int fd[2];
pipe(fd); // 创建管道
if (fork() == 0) {
write(fd[1], "data", 5); // 子进程写入
} else {
char buf[5];
read(fd[0], buf, 5); // 父进程读取
}
嵌入式系统
资源受限的嵌入式设备常使用共享内存或信号量。C语言的轻量级特性适合直接操作硬件寄存器或内存映射。
// 共享内存示例(POSIX)
int shm_fd = shm_open("/mem_region", O_CREAT | O_RDWR, 0666);
ftruncate(shm_fd, SIZE);
void *ptr = mmap(NULL, SIZE, PROT_WRITE, MAP_SHARED, shm_fd, 0);
sprintf(ptr, "Shared data"); // 写入共享内存
网络服务器与客户端
Web服务器(如Nginx)使用IPC处理多进程请求。C语言通过套接字或Unix域套接字实现跨网络或本机通信。
// Unix域套接字示例
struct sockaddr_un addr;
int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, "/tmp/socket");
connect(sockfd, (struct sockaddr*)&addr, sizeof(addr));
数据库系统
数据库引擎(如MySQL)利用信号量或文件锁同步进程访问。C语言直接调用fcntl或sem_init实现并发控制。
// 文件锁示例
int fd = open("db.lock", O_CREAT);
flock(fd, LOCK_EX); // 排他锁
// 临界区操作
flock(fd, LOCK_UN);
科学计算与高性能计算
MPI(消息传递接口)库用C语言实现多节点进程通信。适用于分布式计算场景。
// MPI发送接收示例
int data;
MPI_Recv(&data, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
MPI_Send(&data, 1, MPI_INT, 1, 0, MPI_COMM_WORLD);
实时系统
航空或工业控制系统中,C语言通过优先级信号量确保实时进程优先执行。
// 实时信号量示例
sem_t sem;
sem_init(&sem, 1, 1); // 初始化信号量
sem_wait(&sem); // 进入临界区
sem_post(&sem); // 离开临界区
选择IPC方法时需考虑性能、复杂度及平台兼容性。管道和信号适合简单场景,共享内存和套接字适用于高性能需求。
更多推荐



所有评论(0)