进程间通信方式有哪些?各举例实现一个demo
进程间通信方式有以下几种:
- 管道(Pipe):管道是一种半双工的通信方式,只能在具有亲缘关系的进程之间使用,一般用于父子进程之间的通信。
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int fd[2];
pid_t pid;
char buf[1024];
if (pipe(fd) < 0) {
perror("pipe error");
exit(1);
}
if ((pid = fork()) < 0) {
perror("fork error");
exit(1);
} else if (pid > 0) { // 父进程
close(fd[0]); // 关闭读端
write(fd[1], "hello world\n", 12);
} else { // 子进程
close(fd[1]); // 关闭写端
read(fd[0], buf, 1024);
printf("%s", buf);
}
return 0;
}
- 命名管道(Named Pipe):命名管道是一种半双工的通信方式,可以在不具有亲缘关系的进程之间使用,一般用于客户端与服务器之间的通信。
// 服务端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
int fd;
char buf[1024];
if (mkfifo("fifo", 0666) < 0) { // 创建命名管道
perror("mkfifo error");
exit(1);
}
if ((fd = open("fifo", O_RDONLY)) < 0) { // 打开命名管道
perror("open error");
exit(1);
}
read(fd, buf, 1024);
printf("%s", buf);
close(fd);
return 0;
}
// 客户端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
int fd;
if ((fd = open("fifo", O_WRONLY)) < 0) { // 打开命名管道
perror("open error");
exit(1);
}
write(fd, "hello world\n", 12);
close(fd);
return 0;
}
- 消息队列(Message Queue):消息队列是一种异步的通信方式,可以在不具有亲缘关系的进程之间使用。
// 发送方
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
struct msgbuf {
long mtype;
char mtext[1024];
};
int main()
{
int msqid;
struct msgbuf buf;
key_t key;
if ((key = ftok(".", 'a')) < 0) { // 创建key
perror("ftok error");
exit(1);
}
if ((msqid = msgget(key, IPC_CREAT | 0666)) < 0) { // 创建消息队列
perror("msgget error");
exit(1);
}
buf.mtype = 1; // 消息类型
strcpy(buf.mtext, "hello world");
if (msgsnd(msqid, &buf, strlen(buf.mtext), 0) < 0) { // 发送消息
perror("msgsnd error");
exit(1);
}
return 0;
}
// 接收方
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
struct msgbuf {
long mtype;
char mtext[1024];
};
int main()
{
int msqid;
struct msgbuf buf;
key_t key;
if ((key = ftok(".", 'a')) < 0) { // 创建key
perror("ftok error");
exit(1);
}
if ((msqid = msgget(key, IPC_CREAT | 0666)) < 0) { // 创建消息队列
perror("msgget error");
exit(1);
}
if (msgrcv(msqid, &buf, 1024, 1, 0) < 0) { // 接收消息
perror("msgrcv error");
exit(1);
}
printf("%s", buf.mtext);
if (msgctl(msqid, IPC_RMID, NULL) < 0) { // 删除消息队列
perror("msgctl error");
exit(1);
}
return 0;
}
- 共享内存(Shared Memory):共享内存是一种高效的通信方式,可以实现多个进程之间的数据共享。
// 写进程
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
struct shared_mem {
int flag;
char buf[1024];
};
int main()
{
int shmid;
struct shared_mem *shmptr;
key_t key;
if ((key = ftok(".", 'a')) < 0) { // 创建key
perror("ftok error");
exit(1);
}
if ((shmid = shmget(key, sizeof(struct shared_mem), IPC_CREAT | 0666)) < 0) { // 创建共享内存
perror("shmget error");
exit(1);
}
if ((shmptr = (struct shared_mem *)shmat(shmid, NULL, 0)) == (void *)-1) { // 将共享内存映射到进程的地址空间中
perror("shmat error");
exit(1);
}
while (1) {
if (shmptr->flag == 0) {
fgets(shmptr->buf, sizeof(shmptr->buf), stdin);
shmptr->flag = 1;
}
}
if (shmdt(shmptr) < 0) { // 解除共享内存映射
perror("shmdt error");
exit(1);
}
return 0;
}
// 读进程
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.h>
struct shared_mem {
int flag;
char buf[1024];
};
int main()
{
int shmid;
struct shared_mem *shmptr;
key_t key;
if ((key = ftok(".", 'a')) < 0) { // 创建key
perror("ftok error");
exit(1);
}
if ((shmid = shmget(key, sizeof(struct shared_mem), IPC_CREAT | 0666)) < 0) { // 创建共享内存
perror("shmget error");
exit(1);
}
if ((shmptr = (struct shared_mem *)shmat(shmid, NULL, 0)) == (void *)-1) { // 将共享内存映射到进程的地址空间中
perror("shmat error");
exit(1);
}
while (1) {
if (shmptr->flag == 1) {
printf("%s", shmptr->buf);
shmptr->flag = 0;
}
}
if (shmdt(shmptr) < 0) { // 解除共享内存映射
perror("shmdt error");
exit(1);
}
return 0;
}
- 信号量(Semaphore):信号量是一种用于进程间同步和互斥的机制。
// 写进程
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>
int main()
{
int semid;
struct sembuf semops;
key_t key;
if ((key = ftok(".", 'a')) < 0) { // 创建key
perror("ftok error");
exit(1);
}
if ((semid = semget(key, 1, IPC_CREAT | 0666)) < 0) { // 创建信号量
perror("semget error");
exit(1);
}
semops.sem_num = 0;
semops.sem_op = 1; // 信号量加1
semops.sem_flg = SEM_UNDO;
while (1) {
semop(semid, &semops, 1); // 发送信号量
sleep(1);
}
return 0;
}
// 读进程
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>
int main()
{
int semid;
struct sembuf semops;
key_t key;
if ((key = ftok(".", 'a')) < 0) { // 创建key
perror("ftok error");
exit(1);
}
if ((semid = semget(key, 1, IPC_CREAT | 0666)) < 0) { // 创建信号量
perror("semget error");
exit(1);
}
semops.sem_num = 0;
semops.sem_op = -1; // 信号量减1
semops.sem_flg = SEM_UNDO;
while (1) {
semop(semid, &semops, 1); // 接收信号量
printf("hello world\n");
}
return 0;
}
原文地址: https://www.cveoy.top/t/topic/bpbb 著作权归作者所有。请勿转载和采集!