进程间通信(IPC)机制详解

分类: 365bet电脑版 发布时间: 2025-10-24 11:49:05 作者: admin

进程间通信(IPC)机制详解

在操作系统中,进程间通信(Inter-Process Communication, IPC)是不同进程间交换数据与同步操作的机制。本文将详细讲解五种常用的IPC方式:管道、信号、共享内存、消息队列和信号量,并附上相关函数的用法示例。

1. 管道(Pipe)

管道是Unix/Linux中最古老的IPC形式,分为匿名管道和命名管道两种。

匿名管道

#include

int pipe(int pipefd[2]);

pipefd[0]: 读端

pipefd[1]: 写端

返回值:成功返回0,失败返回-1

示例代码:

#include

#include

#include

int main() {

int pipefd[2];

char buf[20];

if (pipe(pipefd) == -1) {

perror("pipe");

return 1;

}

pid_t pid = fork();

if (pid == 0) { // 子进程

close(pipefd[0]); // 关闭读端

write(pipefd[1], "Hello, Parent!", 14);

close(pipefd[1]);

} else { // 父进程

close(pipefd[1]); // 关闭写端

read(pipefd[0], buf, sizeof(buf));

printf("Parent received: %s\n", buf);

close(pipefd[0]);

wait(NULL);

}

return 0;

}

命名管道(FIFO)

#include

int mkfifo(const char *pathname, mode_t mode);

创建命名管道文件

mode参数指定文件权限

使用流程:

创建FIFO:mkfifo("/tmp/myfifo", 0666)

进程A:open("/tmp/myfifo", O_WRONLY) 并写入数据

进程B:open("/tmp/myfifo", O_RDONLY) 并读取数据

2. 信号(Signal)

信号是异步通信机制,用于通知进程发生了某个事件。

常用函数

#include

void (*signal(int signum, void (*handler)(int)))(int);

int kill(pid_t pid, int sig);

int raise(int sig);

unsigned int alarm(unsigned int seconds);

常见信号:

SIGINT (2): 终端中断(Ctrl+C)

SIGKILL (9): 强制终止

SIGSEGV (11): 段错误

SIGALRM (14): 定时器信号

示例代码:

#include

#include

#include

void handler(int sig) {

printf("Received signal: %d\n", sig);

}

int main() {

signal(SIGINT, handler); // 注册SIGINT处理函数

signal(SIGALRM, handler); // 注册SIGALRM处理函数

alarm(3); // 3秒后发送SIGALRM

while(1) {

pause(); // 等待信号

}

return 0;

}

3. 共享内存(Shared Memory)

共享内存允许多个进程访问同一块内存区域,是最快的IPC方式。

关键函数

#include

int shmget(key_t key, size_t size, int shmflg);

void *shmat(int shmid, const void *shmaddr, int shmflg);

int shmdt(const void *shmaddr);

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

使用步骤:

创建/获取共享内存段:shmget()

附加到进程地址空间:shmat()

读写共享内存

分离共享内存:shmdt()

控制共享内存(删除等):shmctl()

示例代码:

#include

#include

#include

#include

#define SHM_SIZE 1024

int main() {

key_t key = ftok("/tmp", 'A');

int shmid = shmget(key, SHM_SIZE, IPC_CREAT | 0666);

if (shmid == -1) {

perror("shmget");

return 1;

}

char *shm_ptr = (char*)shmat(shmid, NULL, 0);

if (shm_ptr == (void*)-1) {

perror("shmat");

return 1;

}

// 写入数据

strcpy(shm_ptr, "Hello, Shared Memory!");

// 读取数据(在另一个进程中)

// printf("Read from shared memory: %s\n", shm_ptr);

shmdt(shm_ptr);

shmctl(shmid, IPC_RMID, NULL); // 删除共享内存

return 0;

}

4. 消息队列(Message Queue)

消息队列允许进程通过发送/接收消息来通信。

关键函数

#include

int msgget(key_t key, int msgflg);

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

int msgctl(int msqid, int cmd, struct msqid_ds *buf);

消息结构:

struct msgbuf {

long mtype; // 消息类型

char mtext[1]; // 消息数据

};

示例代码:

#include

#include

#include

struct msgbuf {

long mtype;

char mtext[100];

};

int main() {

key_t key = ftok("/tmp", 'B');

int msgid = msgget(key, IPC_CREAT | 0666);

struct msgbuf msg;

msg.mtype = 1;

strcpy(msg.mtext, "Hello, Message Queue!");

// 发送消息

if (msgsnd(msgid, &msg, sizeof(msg.mtext), 0) == -1) {

perror("msgsnd");

return 1;

}

// 接收消息(在另一个进程中)

// if (msgrcv(msgid, &msg, sizeof(msg.mtext), 1, 0) == -1) {

// perror("msgrcv");

// return 1;

// }

// printf("Received: %s\n", msg.mtext);

msgctl(msgid, IPC_RMID, NULL); // 删除消息队列

return 0;

}

5. 信号量(Semaphore)

信号量用于进程间的同步,控制对共享资源的访问。

关键函数

#include

int semget(key_t key, int nsems, int semflg);

int semop(int semid, struct sembuf *sops, unsigned nsops);

int semctl(int semid, int semnum, int cmd, ...);

操作结构体:

struct sembuf {

unsigned short sem_num; // 信号量编号

short sem_op; // 操作(正数加,负数减)

short sem_flg; // 标志(通常为0)

};

示例代码:

#include

#include

#include

#include

union semun {

int val;

struct semid_ds *buf;

unsigned short *array;

};

int main() {

key_t key = ftok("/tmp", 'C');

int semid = semget(key, 1, IPC_CREAT | 0666);

union semun arg;

arg.val = 1; // 初始值设为1(二进制信号量)

semctl(semid, 0, SETVAL, arg);

struct sembuf op_lock = {0, -1, 0}; // P操作

struct sembuf op_unlock = {0, 1, 0}; // V操作

// 加锁

semop(semid, &op_lock, 1);

printf("Critical section start\n");

sleep(2); // 模拟临界区操作

printf("Critical section end\n");

// 解锁

semop(semid, &op_unlock, 1);

semctl(semid, 0, IPC_RMID); // 删除信号量

return 0;

}

IPC方式对比

机制

速度

复杂度

适用场景

管道

中等

父子进程间简单通信

命名管道

中等

任意进程间流式通信

信号

事件通知、简单控制

共享内存

最快

大数据量、高性能通信

消息队列

中高

结构化的进程间通信

信号量

进程同步、资源访问控制

总结

不同的IPC机制适用于不同的场景:

管道/命名管道:适合流式数据传输

信号:适合事件通知和简单控制

共享内存:适合高性能大数据传输

消息队列:适合结构化消息传递

信号量:适合进程同步和资源保护

在实际系统编程中,通常需要组合多种IPC机制来满足复杂需求。理解各种IPC机制的特点和使用场景,能够帮助开发者设计出高效可靠的进程间通信方案。

上一篇: 探索装修公司成功营销的多途径策略 下一篇: 2.6尺是多少厘米?

相关文章

合同与协议的区别及法律效力

合同与协议的区别及法律效力

乌合之众的解释及意思

乌合之众的解释及意思

【世俱杯】2025年世俱杯1/8决赛对阵

【世俱杯】2025年世俱杯1/8决赛对阵

世界上最慢的15种动物

世界上最慢的15种动物

外行不上当:一文让你了解怎么辨别和田玉的真假!

外行不上当:一文让你了解怎么辨别和田玉的真假!

苹果平板换个屏幕大概价钱?

苹果平板换个屏幕大概价钱?