C语言中的进程通信(Inter-Process Communication,IPC)方法主要有以下几种,每种方法适用于不同的应用场景。下面将详细介绍这些方法:
管道是一种允许进程间传递数据的机制,具有以下特点:
pipe()
创建管道。write()
和read()
在管道两端进行数据传输。#include
#include
int main() {
int pipefd[2];
pid_t pid;
char buf[20];
// 创建管道
pipe(pipefd);
pid = fork();
if (pid > 0) { // 父进程
close(pipefd[0]); // 关闭读取端
write(pipefd[1], "Hello from parent", 18); // 向管道写入数据
close(pipefd[1]);
} else if (pid == 0) { // 子进程
close(pipefd[1]); // 关闭写入端
read(pipefd[0], buf, sizeof(buf)); // 从管道读取数据
printf("Child received: %s\n", buf);
close(pipefd[0]);
}
return 0;
}
信号是操作系统用来通知进程发生特定事件的一种方式。信号可以由内核或其他进程发送,用于中断进程的正常执行流或通知事件的发生。常用的信号包括SIGINT
、SIGTERM
、SIGKILL
等。
signal()
或sigaction()
来设置信号处理函数。kill()
或raise()
来发送信号。#include
#include
void handler(int sig) {
printf("Received signal %d\n", sig);
}
int main() {
signal(SIGINT, handler); // 设置SIGINT信号处理函数
while (1) {
printf("Running...\n");
sleep(1);
}
return 0;
}
消息队列是进程间通信的一种形式,允许进程将数据以消息的形式放入队列中,其他进程可以从队列中读取数据。消息队列适用于需要发送结构化数据的情况。
msgget()
创建消息队列。msgsnd()
向消息队列发送消息。msgrcv()
从消息队列接收消息。#include
#include
#include
#include
struct msgbuf {
long mtype;
char mtext[100];
};
int main() {
key_t key = ftok("msgfile", 65);
int msgid = msgget(key, 0666 | IPC_CREAT);
struct msgbuf message;
message.mtype = 1;
strcpy(message.mtext, "Hello, this is a message!");
msgsnd(msgid, &message, sizeof(message), 0); // 发送消息
msgrcv(msgid, &message, sizeof(message), 1, 0); // 接收消息
printf("Received: %s\n", message.mtext);
msgctl(msgid, IPC_RMID, NULL); // 删除消息队列
return 0;
}
共享内存允许多个进程直接访问同一块内存区域,是进程间通信中最快的一种方式。共享内存通常需要配合其他同步机制(如信号量)来避免并发访问时的冲突。
shmget()
创建共享内存段。shmat()
将共享内存段映射到进程的地址空间。shmdt()
解除映射,shmctl()
控制共享内存的状态。#include
#include
#include
#include
int main() {
int shmid = shmget(IPC_PRIVATE, 1024, 0666 | IPC_CREAT);
char *shmaddr = shmat(shmid, NULL, 0);
if (fork() == 0) { // 子进程
sprintf(shmaddr, "Hello from child process!");
} else { // 父进程
sleep(1); // 等待子进程写入数据
printf("Parent received: %s\n", shmaddr);
}
shmdt(shmaddr); // 解除映射
shmctl(shmid, IPC_RMID, NULL); // 删除共享内存
return 0;
}
信号量主要用于进程间同步和互斥。通过信号量可以控制多个进程对共享资源的访问,防止资源竞争和死锁的发生。
semget()
创建信号量集。semop()
执行信号量操作(如P操作和V操作)。semctl()
对信号量进行控制。#include
#include
#include
#include
int main() {
int semid = semget(IPC_PRIVATE, 1, 0666 | IPC_CREAT);
// 初始化信号量
semctl(semid, 0, SETVAL, 1);
struct sembuf sem_op;
sem_op.sem_num = 0;
sem_op.sem_op = -1; // P操作
sem_op.sem_flg = 0;
// 执行P操作
semop(semid, &sem_op, 1);
printf("Critical section\n");
sem_op.sem_op = 1; // V操作
semop(semid, &sem_op, 1);
semctl(semid, 0, IPC_RMID); // 删除信号量
return 0;
}
套接字(Socket)是一种网络通信机制,通常用于不同主机上的进程间通信。它不仅能支持本地进程间的通信,还能支持跨机器的通信。常用在客户端-服务器模型中。
socket()
创建套接字。bind()
绑定地址。listen()
和accept()
进行监听和接收连接。send()
和recv()
进行数据传输。C语言提供了多种进程通信机制(如管道、信号、消息队列、共享内存、信号量和套接字),每种方法都有其特定的应用场景。选择合适的通信方法取决于进程间数据传递的需求、性能考虑和同步要求。