一、管道
1、管道概述
管道是一种基于内存的进程间通信方法,分为无名管道和有名管道。无名管道只能用于父子进程间通信,有名管道可用于任意进程间通信。
无名管道(匿名管道)实际上是一块内存缓冲区,严格遵循先进先出的原则。其中一个进程把数据写入缓冲区,另一个进程从缓冲区取出数据,读取和写入时分别用到管道的读端和写端。父进程调用fork之后,子进程的管道描述符和父进程完全独立。如果父进程调用了close,子进程并不会受到影响。另外,管道只能用于单向通信。
有名管道(FIFO)也是一种基于内存的进程通信方式,相对于无名管道可以用于任意进程间通信。有名管道存在于文件系统中,因此允许无亲缘关系进程间通信。
2、使用管道进行进程间通信
#include
#include
#include
#define MSGSIZE 16
int main()
{
char* msg = "Hello, world!";
char inbuf[MSGSIZE];
int p[2], pid;
if (pipe(p) 0) {
close(p[0]);
write(p[1], msg, MSGSIZE);
close(p[1]);
} else if (pid == 0) {
close(p[1]);
read(p[0], inbuf, MSGSIZE);
printf("%s\n", inbuf);
close(p[0]);
} else {
fprintf(stderr, "fork failed\n");
exit(2);
}
return 0;
}
二、消息队列
1、消息队列概述
消息队列是一种进程间通信的方式,进程可以通过消息队列来传递数据。消息队列在内核中维护,提供收发的缓存区,它是一种比较可靠的IPC机制。其中,每个消息都有一个类型属性,接收进程可以选择接收指定类型的消息。
2、使用消息队列进行进程间通信
#include
#include
#include
#include
#include
#define MSGSZ 128
struct msgbuf {
long mtype;
char mtext[MSGSZ];
};
int main()
{
int msqid;
key_t key;
struct msgbuf sndbuf, rcvbuf;
if ((key = ftok(".", 'A')) == -1) {
perror("ftok");
exit(1);
}
if ((msqid = msgget(key, IPC_CREAT | 0666)) == -1) {
perror("msgget");
exit(1);
}
sndbuf.mtype = 1;
sprintf(sndbuf.mtext, "hello, world!");
if (msgsnd(msqid, &sndbuf, MSGSZ, IPC_NOWAIT) == -1) {
perror("msgsnd");
exit(1);
}
if (msgrcv(msqid, &rcvbuf, MSGSZ, 1, 0) == -1) {
perror("msgrcv");
exit(1);
}
printf("receive: %s\n", rcvbuf.mtext);
if (msgctl(msqid, IPC_RMID, 0) == -1) {
perror("msgctl");
exit(1);
}
return 0;
}
三、信号量
1、信号量概述
信号量是一种进程间通信的方式,它用来保持多个进程之间同步或互斥。其中,信号量的值用来表示可用资源的个数,进程可以通过执行P操作(申请资源)和V操作(释放资源)来更改信号量的值。当信号量的值为0时,执行P操作的进程会进入阻塞状态。
2、使用信号量进行进程间通信
#include
#include
#include
#include
#include
#define SEM_NUM 1
int main()
{
key_t key;
int semid, shmid;
char *shmaddr;
struct sembuf sembuf;
if ((key = ftok(".", 'A')) == -1) {
perror("ftok");
exit(1);
}
if ((semid = semget(key, SEM_NUM, IPC_CREAT | 0666)) == -1) {
perror("semget");
exit(1);
}
if ((shmid = shmget(key, 1024, IPC_CREAT | 0666)) == -1) {
perror("shmget");
exit(1);
}
if ((shmaddr = shmat(shmid, NULL, 0)) == (void *)-1) {
perror("shmat");
exit(1);
}
sembuf.sem_num = 0;
sembuf.sem_op = 1;
sembuf.sem_flg = SEM_UNDO;
semctl(semid, 0, SETVAL, 1);
if (fork() == 0) {
sembuf.sem_op = -1;
semop(semid, &sembuf, 1);
printf("child process write\n");
sprintf(shmaddr, "hello, world!");
sembuf.sem_op = 1;
semop(semid, &sembuf, 1);
exit(0);
} else {
sembuf.sem_op = -1;
semop(semid, &sembuf, 1);
printf("parent process read: %s\n", shmaddr);
sembuf.sem_op = 1;
semop(semid, &sembuf, 1);
}
return 0;
}
四、共享内存
1、共享内存概述
共享内存是一种高效的进程间通信方式,它通过将内存缓冲区映射到多个进程的虚拟地址空间,让多个进程之间共享数据。共享内存通常需要配合其他进程同步机制,如信号量一起使用。但存在一个问题,即多个进程共享内存容易引发数据一致性问题。
2、使用共享内存进行进程间通信
#include
#include
#include
#include
int main()
{
int shmid, pid;
char *shmaddr;
if ((shmid = shmget(IPC_PRIVATE, 1024, IPC_CREAT | 0666)) == -1) {
perror("shmid");
exit(1);
}
if ((shmaddr = shmat(shmid, NULL, 0)) == (void *)-1) {
perror("shmat");
exit(1);
}
if ((pid = fork()) == 0) {
printf("child process write\n");
strcpy(shmaddr, "hello, world!");
exit(0);
} else if (pid > 0) {
wait(NULL);
printf("parent process read: %s\n", shmaddr);
} else {
perror("fork");
exit(1);
}
if (shmctl(shmid, IPC_RMID, NULL) == -1) {
perror("shmctl");
exit(1);
}
return 0;
}
原创文章,作者:GLBNI,如若转载,请注明出处:https://www.506064.com/n/332858.html
微信扫一扫
支付宝扫一扫