一、管道
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/zh-tw/n/332858.html
微信掃一掃
支付寶掃一掃