进程间通信的七种方法实战演示!值得收藏!

进程间通信的七种方法实战演示!值得收藏!

文章目录

前言

一、管道(Pipes)

管道示例代码:

管道示例流程解读:

管道示例运行效果:

二、消息队列(Message Queues)

消息队列示例代码

消息队列示例流程解读:

消息队列示例执行效果

三、共享内存(Shared Memory)

共享内存示例代码

共享内存示例流程解读:

共享内存示例执行效果

四、 信号(Signals)

信号示例代码:

信号示例流程解读:

信号示例执行效果

五、套接字(Sockets)

套接字示例代码:

套接字示例流程解读:

套接字示例执行结果

六、信号量(Semaphores)

信号量示例代码:

信号量示例流程解读:

信号量示例执行结果

七、文件映射(Memory-Mapped Files)

文件映射示例代码:

文件映射示例流程解读:

文件映射示例执行结果

总结

前言

线程和进程间的通讯(Inter-Process Communication, IPC)是操作系统中的一个重要概念,用于实现不同进程或同一进程中的不同线程之间的数据交换和协调。 但是这些概念太多了,容易搞混了,所有特地写了这篇博客来记录这些方式的使用实例,建立大家收藏起来,将来需要复习的时候,再来看一看,能够快速的带你复习一遍!

以下是几个常见的进程间通信的方式:管道、消息队列、共享内存、信号、套接字、信号量、文件映射

提示:以下是本篇文章正文内容,下面案例可供参考

一、管道(Pipes)

管道是一种半双工的通信方式,数据只能单向流动。管道分为两种类型:

匿名管道:仅限于具有亲缘关系的进程之间使用,通常用于父子进程之间的通信。 命名管道(FIFO):可以在任意两个进程之间使用,通过文件系统中的一个特殊文件来标识。

管道示例代码:

以下是一个简单的 C 语言示例,演示如何使用管道实现父子进程间的通信。

#include

#include

#include

#include

#include // 用于 memset

int main() {

int pipefd[2];

pid_t pid;

char buf[100];

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

perror("pipe");

return 1;

}

pid = fork();

if (pid == -1) {

perror("fork");

return 1;

}

if (pid == 0) {

// 子进程

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

write(pipefd[1], "Hello from child", 18);

close(pipefd[1]);

} else {

// 父进程

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

memset(buf, 0, sizeof(buf)); // 清空缓冲区

ssize_t bytes_read = read(pipefd[0], buf, sizeof(buf) - 1); // 读取数据,留一个字节给终止符

if (bytes_read > 0) {

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

} else {

perror("read");

}

close(pipefd[0]);

wait(NULL);

}

return 0;

}

管道示例流程解读:

1、创建管道:使用 pipe 函数创建一个管道,该函数返回两个文件描述符,分别用于读取和写入。

2、创建子进程:使用 fork 函数创建一个子进程。fork 返回子进程的 PID,如果返回值为 -1 表示出错,0 表示当前是子进程,其他值表示当前是父进程。

3、关闭不必要的管道端: 在父进程中,关闭管道的端(pipefd[1]),因为子进程只读取数据。 在子进程中,关闭管道的读端(pipefd[0]),因为父进程只写入数据。

4、数据传输: 子进程使用 write 函数向管道中写入数据。 父进程使用 read 函数从管道中读取数据。

5、关闭管道:在完成数据传输后,关闭管道的相应端。

6、等待子进程结束:父进程使用 wait 函数等待子进程结束。

管道示例运行效果:

二、消息队列(Message Queues)

消息队列是一种更高级的通信方式,允许进程发送和接收消息。消息队列可以存储多个消息,并且可以设置消息的优先级。

消息队列示例代码

#include

#include

#include

#include

#include

#include

#include

#define MAX_MSG_SIZE 256

// 定义消息结构体

struct msg_buffer {

long msg_type;

char msg_text[MAX_MSG_SIZE];

};

int main() {

key_t key;

int msgid;

struct msg_buffer message;

pid_t cpid;

// 生成一个唯一的键值

key = ftok("/etc/passwd", 65); // 使用现有的文件 /etc/passwd

if (key == -1) {

perror("ftok");

exit(EXIT_FAILURE);

}

// 创建消息队列

msgid = msgget(key, 0666 | IPC_CREAT);

if (msgid == -1) {

perror("msgget");

exit(EXIT_FAILURE);

}

// 创建子进程

cpid = fork();

if (cpid == -1) {

// fork 失败

perror("fork");

exit(EXIT_FAILURE);

} else if (cpid == 0) {

// 子进程

// 子进程接收消息

if (msgrcv(msgid, &message, sizeof(message.msg_text), 1, 0) == -1) {

perror("msgrcv");

exit(EXIT_FAILURE);

}

printf("Child process received: %s\n", message.msg_text);

// 子进程发送消息

message.msg_type = 2;

strcpy(message.msg_text, "Hello from child");

if (msgsnd(msgid, &message, sizeof(message.msg_text), 0) == -1) {

perror("msgsnd");

exit(EXIT_FAILURE);

}

exit(EXIT_SUCCESS);

} else {

// 父进程

// 父进程发送消息

message.msg_type = 1;

strcpy(message.msg_text, "Hello from parent");

if (msgsnd(msgid, &message, sizeof(message.msg_text), 0) == -1) {

相关文章

国际足联:2025首届新版世俱杯参赛奖金达10亿美元

365bet在线网址 10-04

脅是什么意思脅的解释 脅怎么读

beat365手机版官方网站正规 08-29

别克英朗换车钥匙,英朗车钥匙怎么换

365bet在线网址 10-21

大蒜的采薹方法是什么?

365bet在线网址 08-03