一、管道
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-hant/n/332858.html