程式間的幾種通訊方式
1、匿名管道pipe
匿名管道是半雙工的,並且只能在具有公共祖先的兩個程式之間使用。通常一個管道由一個程式建立,在程式呼叫fork之後,這個管道就能在父程式和子程式之間使用了。管道建立時會建立兩個檔案描述符,其中fd[0]為讀而開啟,fd[1]為寫而開啟。
#include "apue.h"
int main()
{
int n;
int fd[2];
pid_t pid;
char line[MAXLINE];
if (pipe(fd) < 0) {
err_sys("pipe error");
}
if ((pid = fork()) < 0) {
err_sys("fork error");
}
else if (pid > 0) {
close(fd[0]);
write(fd[1], "hello world\n", 12);
}
else {
close(fd[1]);
n = read(fd[0], line, MAXLINE);
write(STDOUT_FILENO, line, n);
}
exit(0);
}
2、命名管道FIFO
pipe只能在兩個相關的程式之間使用,而命名管道FIFO則可以在兩個不相關的程式之間使用,使用的範圍更廣。 使用FIFO時,首先需要使用mkfifo來建立它,建立之後,可以使用檔案的相關函式open、read、write、close等函式像普通檔案一樣操作這個命名管道。
- 一般情況下,如果沒有指定O_NONBLOCK,只讀open要阻塞到某個其他程式為寫而開啟這個FIFO為止。類似的,只寫open要阻塞到某個程式為讀而開啟它為止。如果指定了O_NONBLOCK,則只讀open立即返回。但是,如果沒有程式為讀而開啟一個FIFO,那麼open將返回-1,並將errno設定為ENXIO。
- 若write一個尚無程式為讀而開啟的FIFO,則產生訊號SIGPIPE,若某個FIFO的最後一個寫程式關閉了該FIFO,則將為該FIFO的讀程式產生一個檔案結束標誌。
從FIFO讀資料的程式:
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FIFO "/tmp/myfifo"
int main(int argc,char** argv)
{
char buf_r[100];
int fd;
int nread;
/* 建立FIFO */
if ((mkfifo(FIFO, O_CREAT|O_EXCL) < 0)&&(errno != EEXIST))
{
printf("cannot create fifoserver\n");
}
printf("Preparing for reading bytes...\n");
memset(buf_r, 0, sizeof(buf_r));
fd = open(FIFO, O_RDONLY|O_NONBLOCK, 0);
if (fd == -1)
{
perror("open");
exit(1);
}
while (1)
{
memset(buf_r, 0, sizeof(buf_r));
if ((nread = read(fd, buf_r, 100)) == -1)
{
if(errno == EAGAIN)
{
printf("no data yet\n");
}
}
printf("read %s from FIFO\n", buf_r);
sleep(1);
}
pause();
unlink(FIFO);
}
寫訊息到FIFO的程式:
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FIFO_SERVER "/tmp/myfifo"
int main(int argc,char** argv)
{
int fd;
char w_buf[100];
int nwrite;
fd = open(FIFO_SERVER, O_WRONLY | O_NONBLOCK, 0);
if (fd == -1)
{
if (errno == ENXIO)
{
printf("open error; no reading process\n");
}
}
if (argc == 1)
{
printf("Please send something\n");
}
strcpy(w_buf, argv[1]);
if ((nwrite = write(fd, w_buf, 100)) == -1)
{
if (errno == EAGAIN)
{
printf("The FIFO has not been read yet.Please try later\n");
}
}
else
{
printf("write %s to the FIFO\n", w_buf);
}
}
3、XSI IPC
訊號量、訊息佇列、共享儲存這種IPC被稱作XSI IPC,這三種IPC中,核心中都有一個非負整數的識別符號加以引用。識別符號是IPC的內部名,為此,每個IPC物件都與一個鍵(key)相關聯,將這個鍵作為該物件的外部名。可以呼叫ftok函式,傳入路徑名和專案ID建立一個鍵,然後可以在訊號量,訊息佇列和共享儲存之間使用。
#include <sys/ipc.h>
key_t ftok(const char *path, int id);
XSI IPC的幾個缺點:
- XSI IPC沒有引用計數,如果程式建立了一個訊息佇列,放入幾則訊息然後終止,那麼該訊息佇列及其內容不會被刪除。它會一直駐留在系統中直到另外一個程式從該訊息佇列讀訊息或者顯示刪除訊息佇列。而對於pipe和FIFO,最後一個引用的程式終止時,pipe和FIFO的資料已經被刪除了。
- 這些IPC結構在檔案系統中沒有名字,不能使用檔案系統的函式來訪問這些IPC,也不能對它們使用多路轉接IO函式(select、poll等)
3.1、訊息佇列
#include <sys/msg.h>
// 建立一個訊息佇列
int msgget(key_t, int flag);
// 將資料放到訊息佇列中
int msgsnd(int msqid, const void *ptr, size_t nbytes, int flag);
// 從訊息佇列中取資料
int msgrcv(int msqid, void *ptr, size_t nbytes, long type, int flag);
3.2、訊號量
訊號量與pipe、FIFO、訊息佇列同,它時一個計數器,用於多個程式提供對共享資料的訪問,即P操作和V操作。
#include <sys/sem.h>
// 建立訊號量
int semget(key_t key, int nsems, int flag);
// 設定訊號量的值
int semctl(int semid, int semnum, int cmd, .../* union semun arg */);
// 對訊號量進行P操作和V操作
int semop(int semid, struct sembuf semoparray[], size_t nops);
訊號量、記錄鎖、互斥量的比較
- 訊號量:建立訊號量集並且初始化為1,分配資源時sem_op為-1呼叫semop,釋放資源時sem_op為1呼叫semop。
- 記錄鎖:先建立一個空檔案,用該檔案的第一個位元組作為鎖位元組。分配資源時先對該位元組獲得一個寫鎖,釋放資源時,對該位元組解鎖。
- 互斥量:所有程式將相同的檔案對映到他們的地址空間裡,在檔案的相同偏移處初始化互斥量。分配資源時,對互斥量加鎖,為了釋放鎖,我們解鎖互斥量。
3.3、共享儲存
共享儲存允許兩個或者多個程式共享一個給定的儲存區,資料不用在多個程式間複製,因此這是最快的一種IPC。通常訊號量用於同步共享儲存的訪問,但是也可以使用記錄鎖或者互斥量。
#include <sys/shm.h>
// 獲取一個共享儲存識別符號
int shmget(key_t key, size_t, int flag);
// 對共享儲存的操作,包括獲取共享儲存的屬性、刪除共享儲存等
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
// 共享儲存連線到程式的地址空間中
void *shmat(int shmid, const void *addr, int flag);
// 從地址空間中解鎖共享儲存
int shmdt(const void *addr);
4、網路套接字socket
相關文章
- 幾種程式間的通訊方式
- 什麼是程式間通訊?Linux程式間通訊有幾種方式?Linux
- 程式間通訊是什麼?Linux程式間通訊有幾種方式?Linux
- React中元件間通訊的幾種方式React元件
- T面試題:程式間的通訊方式有哪幾種?面試題
- 程式間的8種通訊方式
- Android開啟多程式及程式間通訊的幾種方式Android
- 程式間的五種通訊方式介紹
- React中元件通訊的幾種方式React元件
- Windows程式間各種通訊方式淺談Windows
- 程式間的五種通訊方式介紹-詳解
- Linux程式間通訊的6種不同方式Linux
- Linux程式間通訊有幾種方式?這8個你都知道嗎?Linux
- windows下程式間通訊的方式Windows
- vue3 常用的幾種元件通訊方式Vue元件
- Vue元件之間通訊的三種方式Vue元件
- iOS App間常用的五種通訊方式iOSAPP
- 程式間的八種通訊方式----共享記憶體是最快的 IPC 方式記憶體
- 程式間通訊方式有哪些?
- vue通訊的N種方式Vue
- ros的幾種通訊機制及程式碼ROS
- C++程式間通訊的十一種方法C++
- Activity和Service跨程式通訊的兩種方式
- Vue 元件間的通訊方式Vue元件
- Activity之間的通訊方式
- Linux 程式間通訊的六種機制Linux
- Vue中元件間通訊的方式Vue元件
- React中元件間通訊的方式React元件
- 程式間的通訊
- 程式碼迭代的幾種方式
- 實現多個標籤頁之間通訊的幾種方法
- iOS app之間通訊方式iOSAPP
- 程式間通訊
- React中元件之間通訊的方式React元件
- 程式間的通訊實現(IPC)的11種方法 (轉)
- 我最喜歡的程式之間通訊方式-訊息匯流排
- Unix系統下程式間通訊方式及比較
- C#程式間通訊的各種途徑及解析C#