1. 概述
进程间通信(IPC)是指在多个进程之间进行数据交换和共享的一种机制。在Linux系统中,有多种方法可以实现进程间通信。本文将介绍几种常用的IPC方法,包括管道、消息队列、共享内存和信号量。对于每一种方法,将详细介绍其原理、使用方法和适用场景。
2. 管道(Pipe)
管道是最简单和最基本的IPC方法之一,它可以在父进程和子进程之间进行单向通信。管道的原理是通过在内核中创建一个缓冲区,父进程写入数据到缓冲区,子进程从缓冲区读取数据。管道可以使用系统调用pipe()来创建,使用read()和write()来进行读写操作。
2.1 创建管道
#include <unistd.h>
int pipe(int pipefd[2]);
创建一个管道,成功返回0,失败返回-1。pipefd是一个大小为2的整型数组,其中pipefd[0]用于读取数据,pipefd[1]用于写入数据。
2.2 管道的读写操作
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
使用read()和write()系统调用来进行管道的读写操作。fd是管道的文件描述符,buf是读写的缓冲区,count是读写的字节数。read()会阻塞等待直到有数据可读,write()会阻塞等待直到有空间可写。
下面是一个简单的例子,演示了如何使用管道实现父子进程之间的通信:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
int pipefd[2];
pid_t pid;
char buf[20];
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], buf, sizeof(buf));
printf("子进程接收到的数据:%s\n", buf);
close(pipefd[0]);
_exit(EXIT_SUCCESS);
} else { // 父进程
close(pipefd[0]); // 关闭读取端
write(pipefd[1], "Hello, child!", 14);
close(pipefd[1]);
wait(NULL);
exit(EXIT_SUCCESS);
}
}
运行以上程序,父进程将字符串"Hello, child!"写入管道,子进程从管道中读取数据并输出。
3. 消息队列(Message Queue)
消息队列是一个在内核中的消息容器,进程可以进行异步通信。消息队列通过系统调用msgget()、msgsnd()和msgrcv()来进行创建、发送和接收操作。
3.1 创建消息队列
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);
使用msgget()系统调用来创建新消息队列或获取现有消息队列的标识符。key是一个唯一的键值标识符,msgflg是创建消息队列时的标志位。
下面是一个简单的例子,演示了如何使用消息队列实现进程间通信:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
struct msgbuf {
long mtype;
char mtext[120];
};
int main()
{
int msqid;
key_t key;
struct msgbuf buf;
key = ftok("./msgq", 'B');
if (key == -1) {
perror("ftok");
exit(EXIT_FAILURE);
}
msqid = msgget(key, 0666 | IPC_CREAT);
if (msqid == -1) {
perror("msgget");
exit(EXIT_FAILURE);
}
buf.mtype = 1;
sprintf(buf.mtext, "Hello, message queue!");
if (msgsnd(msqid, &buf, sizeof(buf.mtext), 0) == -1) {
perror("msgsnd");
exit(EXIT_FAILURE);
}
printf("Message sent: %s\n", buf.mtext);
exit(EXIT_SUCCESS);
}
运行以上程序,创建一个新消息队列,向队列中发送一条消息。