1.行程間通信的概述
什么是行程間通信?什么是執行緒間通信?
行程間通信:在用戶空間實作行程間通信是不可能的,通過Linux內核通信,
執行緒間通信:可以通過用戶空間就可以實作,比如通過全域變數通信,
2.Linux使用的行程間通信方式
管道通信:無名管道、有名管道(檔案系統中有檔案名)
信號通信
IPC(inter-Process Communitcation)通信:共享記憶體、訊息佇列、信號燈
套接字(socket)
3.行程通信的思想
行程間通信每一種通信方式都是基于檔案IO的思想
Open:功能:創建或打開行程通信物件(函式可能不一樣,形式一樣)
Write:功能:向行程中心寫入內容,(函式可能不一樣,形式一樣)
Read:功能:從行程通信物件中讀取內容,(函式可能不一樣,形式一樣)
Close:功能:關倍訓者洗掉行程通信物件,(函式可能不一樣,形式一樣)
4.管道通信
- 管道通信可分為無名管道(pipe)和有名管道(FIFO),無名管道可用于具有親緣關系行程間的通信;有名管道除具有管道相似的功能外,它還允許無親緣關系行程使用,
- 管道的結構是個順序佇列,
- 管道中的東西,讀完了就洗掉了,如果管道中沒有東西,就會讀阻塞,
- 如果管道寫滿了,也會寫阻塞,
- 有名管道檔案不占用記憶體空間,只是一個檔案描述符,只有當呼叫open函式去打開的管道檔案的的時候,才會在內核空間開辟一段快取,行程結束空間會自動釋放,
- 無名管道不存在檔案節點,只能實作有親緣關系間行程的通信,無名存在檔案節點,但是不占用記憶體空間,可實作無親緣關系行程間的通信,
5.管道通信示意圖

6.管道的使用
無名管道的創建
|
所需頭檔案 |
#include<unistd.h> |
|
函式原型 |
int pipe(int fd[2]) |
|
函式引數 |
兩個檔案描述符,f[0]用來讀,f[1]用來寫, |
|
函式回傳值 |
成功0,失敗-1 |
有名管道的創建
|
所需頭檔案 |
#include<unistd.h> |
|
函式原型 |
int mkfifo(const char *filename, mode_t mode); |
|
函式引數 |
filename:創建的管道檔案名 mod:檔案權限 |
|
函式回傳值 |
成功0,失敗-1 |
管道讀寫、打開、關閉
可直接呼叫系統IO函式write()進行寫,read()進行,open打開、close關閉
open函式
|
所需頭檔案 |
#include <fcntl.h> |
|
函式原型 |
int open(const char* pathname, int flags, mode_t mode); |
|
函式引數 |
pathname:檔案名 flag: O_RDONLY(只讀)、O_WRONLY(只寫) O_RDWR(讀寫) mod:檔案權限 |
|
函式回傳值 |
成功0,失敗-1 |
close函式
|
所需頭檔案 |
#include <fcntl.h> |
|
函式原型 |
int close(int fd); |
|
函式引數 |
fd:檔案描述符 |
|
函式回傳值 |
成功0,失敗-1 |
read函式
|
所需頭檔案 |
#include <fcntl.h> |
|
函式原型 |
ssize_t read(int fd, void * buf, size_t count); |
|
函式引數 |
fd:檔案描述符 buf:讀到哪 count:讀多少個位元組 |
|
函式回傳值 |
回傳值為實際讀取到的位元組數, 如果回傳0, 表示已到達檔案尾或是無可讀取的資料 |
write函式
|
所需頭檔案 |
#include <fcntl.h> |
|
函式原型 |
ssize_t write (int fd, const void * buf, size_t count); |
|
函式引數 |
fd:檔案描述符 buf:寫資料 count:寫多少個位元組 |
|
函式回傳值 |
如果順利write()會回傳實際寫入的位元組數(len),當有錯誤發生時則回傳-1,錯誤代碼存入errno中 |
7.無名管道程式示例
無名管道代碼運行預期結果是父行程先列印,在到子行程列印,
1 #include"stdio.h" 2 #include"unistd.h" 3 #include"sys/types.h" 4 #include"fcntl.h" 5 int main() 6 { 7 int pid; 8 int i; 9 int fd[2]; 10 int flag = 0; 11 if (pipe(fd) < 0) 12 { 13 printf("creat pipe fail\n"); 14 } 15 16 pid = fork(); 17 if (pid > 0) 18 { 19 for(i=0;i<5;i++) 20 { 21 printf("this is father process\n"); 22 usleep(100); 23 } 24 25 flag = 1; 26 write(fd[1], &flag, 1); 27 sleep(1); 28 } 29 30 if (pid == 0) 31 { 32 read(fd[0], &flag, 1); 33 while(flag == 0); 34 for(i=0;i<5;i++) 35 { 36 printf("this is child process\n"); 37 usleep(100); 38 } 39 } 40 }
8.有名管道程式示例
改程式有兩個.c檔案,fifoB.c是讀端程式,fifiA.c是寫端程式,此外還需要在當前目錄創建一個myfifo的管道檔案,編譯完先運行讀端程式,然后在運行寫端程式,程式運行的結果寫端先列印,讀端后列印,
1 //fifoA.c 寫端代碼 2 3 #include"stdio.h" 4 #include"unistd.h" 5 #include"fcntl.h" 6 int main() 7 { 8 int i; 9 char flag = 0; 10 int fd; 11 fd = open("./myfifo", O_RDWR); 12 if (fd < 0) 13 { 14 printf("open faild\n"); 15 return -1; 16 } 17 18 for(i = 0; i < 5; i++) 19 { 20 printf("this is A process\n"); 21 sleep(1); 22 } 23 flag = 1; 24 write(fd, &flag, 1); 25 while(1); 26 27 }
1 //fifoB.c 讀端代碼 2 3 #include"stdio.h" 4 #include"unistd.h" 5 #include"fcntl.h" 6 int main() 7 { 8 int i; 9 char flag = 0; 10 int fd; 11 fd = open("./myfifo", O_RDWR); 12 13 if (fd < 0) 14 { 15 printf("open falid\n"); 16 return -1; 17 } 18 read(fd, &flag, 1); 19 while(flag = 0); 20 for(i = 0; i < 5; i++) 21 { 22 printf("this is B process\n"); 23 sleep(1); 24 } 25 26 }
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/397114.html
標籤:嵌入式
