进程间通信的方式

进程间通信的方式

管道

概述: 用于在父子进程之间传递数据,管道在操作系统内部提供了一个缓冲区,进程可以通过该缓冲区交换数据

形式:

  • 匿名管道:用于父子进程之间的通信
  • 命名管道(FIFO):允许无关的进程之间进行通信

使用示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 #include <stdio.h>
#include <unistd.h>

int main() {
int pipefd[2];
char buffer[100];

// 创建管道
pipe(pipefd);

if (fork() == 0) { // 子进程
close(pipefd[1]); // 关闭写端
read(pipefd[0], buffer, sizeof(buffer)); // 读取管道数据
printf("Child received: %s\n", buffer);
close(pipefd[0]);
} else {
close(pipefd[0]); // 关闭读端
write(pipefd[1], "Hello from parent", 18); // 写入管道
close(pipefd[1]);
}

return 0;
}

消息队列

概述: 允许不同的进程之间通过发送和接收消息进行通信,消息队列支持异步通信,发送者和接收者可以不在同一时刻,通过FIFO的方式排列消息

使用示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <stdio.h>
#include <stdlib.h>
#include <mqueue.h>
#include <string.h>

#define QUEUE_NAME "/example_queue"

int main() {
mqd_t mq;
struct mq_attr attr;
char buffer[256];

// 创建消息队列
attr.mq_flags = 0;
attr.mq_maxmsg = 10;
attr.mq_msgsize = 256;
attr.mq_curmsgs = 0;

mq = mq_open(QUEUE_NAME, O_CREAT | O_RDWR, 0644, &attr);
if (mq == (mqd_t)-1) {
perror("mq_open");
exit(1);
}

// 发送消息
char* message = "Hello, message queue!";
if (mq_send(mq, message, strlen(message) + 1, 0) == -1) {
perror("me_send");
exit(1);
}

// 接收消息
if (mq_receive(mq, buffer, 256, NULL) == -1) {
perror("mq_receive");
exit(1);
}

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

// 关闭和删除消息队列
mq_close(mq);
mq_unlink(QUEUE_NAME);

return 0;
}

共享内存

概述: 允许多个进程直接访问同一块内存区域,通过共享内存,不同进程可以以读写的方式直接修改共享区域的数据

使用示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <stdio.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

#define SHM_NAME "/shm_example"

int main() {
int shm_fd;
char* shm_ptr;

// 创建共享内存对象
shm_fd = shm_open(SHM_NAME, O_CREAT | O_RDWR, 0666);
ftruncate(shm_fd, 256); // 设置共享内存大小

// 映射共享内存
shm_ptr = mmap(0, 256, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (shm_ptr == MAP_FAILED) {
perror("mmap");
return -1;
}

// 写入共享内存
sprintf(shm_ptr, "Hello, shared memory!");

// 读取共享内存
printf("Shared memory content: %s\n", shm_ptr);

// 解除映射和关闭文件描述符
munmap(shm_ptr, 256);
close(shm_fd);
shm_unlink(SHM_NAME);

return 0;
}

信号量

概述: 用于控制对共享资源的访问呢,解决进程之间的互斥问题,防止多个进程同时访问同一资源

  • 二进制信号量:只能取值0或1,常用于互斥锁
  • 计数信号量:信号量的值大于1,常用于管理多个共享资源

使用示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
#include <semaphore.h>
#include <pthread.h>

sem_t sem;

void* worker(void* arg) {
sem_wait(&sem);
printf("Worker started\n");
sleep(1);
sem_post(&sem);
return NULL;
}

int main() {
pthread_t t1, t2;
sem_init(&sem, 0, 1);

pthread_create(&t1, NULL, worker, NULL);
pthread_create(&t2, NULL, worker, NULL);

pthread_join(t1, NULL);
pthread_join(t2, NULL);

sem_destroy(&sem);

return 0;
}

socket

概述: 可用于本地进程间通信(Unix域套接字)或跨机器通信(基于TCP/IP协议)

服务端示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>

int main() {
int sock;
struct sockaddr_in server_addr;
char* message = "Hello from client";

// 创建socket
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
perror("socket");
exit(1);
}

// 设置服务器地址
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8080);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

// 连接服务器
connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr));

// 发送数据
send(sock, message, strlen(message), 0);

// 关闭连接
close(sock);
return 0;
}

客户端示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>

int main() {
int sock;
struct sockaddr_in server_addr;
char* message = "Hello from client";

// 创建socket
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
perror("socket");
exit(1);
}

// 设置服务器地址
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8080);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

// 连接服务器
connect(sock, (struct sockaddr*)&server_addr, sizeof(server_addr));

// 发送数据
send(sock, message, strlen(message), 0);

// 关闭连接
close(sock);
return 0;
}

进程间通信的方式
http://example.com/2025/02/27/进程间通信的方式/
作者
凌云行者
发布于
2025年2月27日
许可协议