嵌入式Linux併發程式設計,程序間通訊方式,有名管道,有名管道特點,有名管道建立mkfifo()
阿新 • • 發佈:2018-12-20
1,有名管道的特點
- 對應管道檔案,可用於任意程序之間進行通訊:有名管道建立好之後,在系統中有實際的檔案和有名管道對應,任意兩個程序可以通過路徑和檔名指定同一個有名管道進行通訊
- 開啟管道時可指定讀寫方式:有名管道用open()開啟的時候可以指定不同的讀寫方式,從而可以確定讀端和寫端
- 通過檔案IO操作,內容存放在記憶體中:通過檔案IO read()和write()進行操作。雖然有名管道有一個實際的檔案被建立,在檔案系統中可見,但是往管道中寫入的所有內容實際上依然是存放在記憶體中的(跟無名管道一樣),當所有的讀端和寫端都關閉的時候,管道存放在記憶體中的內容都會被釋放
- 有名管道開啟的時候有可能會阻塞。當只有讀端或只有寫端的時候,open()會阻塞,只有當讀端和寫端同時存在的時候,open()才會返回,程式才會繼續執行。
2,有名管道的建立mkfifo()
#include <unistd.h> #include <fcntl.h> int mkfifo(const char *path, mode_t mode);
- 成功時返回0,失敗時返回EOF(如果建立的管道已經存在,建立就會失敗)
- path 建立的管道檔案路徑
- mode 管道檔案的許可權,如0666(管道檔案的許可權主要是讀寫許可權)
3,有名管道讀寫—示例
程序A:迴圈從鍵盤輸入並寫入有名管道myfifo,輸入quit時退出 程序B:迴圈統計程序A每次寫入myfifo的字串的長度
/* create_fifo.c */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
if(mkfifo("myfifo",0666) < 0)
{
perror("mkfifo");
exit(-1);
}
return 0;
}
/* write_fifo.c */
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#define N 32
int main(int argc, const char *argv[])
{
char buf[N];
int pfd;
if((pfd = open("myfifo",O_WRONLY)) < 0)
{
perror("open");
exit(-1);
}
printf("write myfifo\n");//程序開啟管道後顯示這一句
while(1)
{
printf("Please input a string (quite exit!\n");
fgets(buf,N,stdin);
if(strcmp(buf,"quite\n") == 0)break;
write(pfd,buf,N);
}
close(pfd);
return 0;
}
/* read_fifo.c */
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#define N 32
int main(int argc, const char *argv[])
{
char buf[N];
int pfd;
if((pfd = open("myfifo",O_RDONLY)) < 0)
{
perror("open");
exit(-1);
}
printf("read myfifo\n");//程序開啟管道後顯示這一句
while(read(pfd,buf,N) > 0)//寫端存在,管道中沒有資料的時候,讀管道阻塞;寫端不存在,管道中沒有資料的時候,read()返回0
{
printf("the length of string is %d\n",strlen(buf));
}
close(pfd);
return 0;
}
1,建立好三個c檔案,並編譯
[email protected]:~/test/stdio/fifo_sample$ ls
fifo_create.c fifo_read.c fifo_write.c
[email protected]:~/test/stdio/fifo_sample$ gcc fifo_create.c -o fifo_create.out
[email protected]:~/test/stdio/fifo_sample$ gcc fifo_write.c -o fifo_write.out
[email protected]:~/test/stdio/fifo_sample$ gcc fifo_read.c -o fifo_read.out
[email protected]:~/test/stdio/fifo_sample$ ls
fifo_create.c fifo_create.out fifo_read.c fifo_read.out fifo_write.c fifo_write.out
2,執行fifo_create.out,可以看到多了管道檔案
[email protected]:~/test/stdio/fifo_sample$ ./fifo_create.out
[email protected]:~/test/stdio/fifo_sample$ ll
total 44
drwxrwxr-x 2 linux linux 4096 11月 12 11:13 ./
drwxrwxr-x 6 linux linux 4096 11月 12 01:01 ../
-rw-rw-r-- 1 linux linux 185 11月 12 10:13 fifo_create.c
-rwxrwxr-x 1 linux linux 7418 11月 12 11:04 fifo_create.out*
-rw-rw-r-- 1 linux linux 379 11月 12 11:03 fifo_read.c
-rwxrwxr-x 1 linux linux 7647 11月 12 11:05 fifo_read.out*
-rw-rw-r-- 1 linux linux 438 11月 12 11:03 fifo_write.c
-rwxrwxr-x 1 linux linux 7681 11月 12 11:04 fifo_write.out*
prw-rw-r-- 1 linux linux 0 11月 12 11:13 myfifo|
- 可以看到管道檔案大小是0,實際上管道檔案大小永遠是0,因為管道中的內容是儲存在記憶體裡的,而不是磁碟上
3,執行fifo_read.out或fifo_write.out,可以看到程式處於阻塞狀態。以先執行fifo_read.out為例(先執行寫管道也一樣)
[email protected]:~/test/stdio/fifo_sample$ ./fifo_read.out
[email protected]:~/test/stdio/fifo_sample$ ps -aux |grep fifo
linux 3089 0.0 0.5 15196 6072 pts/10 S+ 10:49 0:01 vi fifo_read.c
linux 3306 0.0 0.0 2024 280 pts/12 S+ 11:15 0:00 ./fifo_read.out
linux 3314 0.0 0.0 6108 852 pts/0 S+ 11:18 0:00 grep --color=auto fifo
- 當程序開啟一個有名管道的時候,如果當前只有讀端或只有寫端,open()會阻塞 open()的下一條指令 printf(“read myfifo\n”);//程序開啟管道後顯示這一句 沒有執行
- 只有當讀端和寫端都存在是,兩個程序中的open()才能正常執行
4,在另一個終端執行
讀程序 | 寫程序 |
---|---|
[email protected]:~/test/stdio/fifo_sample$ ./fifo_read.out |
|
write myfifo |
[email protected]:~/test/stdio/fifo_sample$ ./fifo_write.out
write myfifo
Please input a string (quite exit!
|
the length of string is 4 |
qwe
Please input a string (quite exit!
|
the length of string is 2 |
w
Please input a string (quite exit!
|
[email protected]:~/test/stdio/fifo_sample$ |
quite
[email protected]:~/test/stdio/fifo_sample$
|
- 執行fifo_write.out後,管道有了寫端,讀程序和寫程序的open()才能正常執行,可以看到open()的下一條指令 printf(“read myfifo\n”);//程序開啟管道後顯示這一句 printf(“write myfifo\n”);//程序開啟管道後顯示這一句 正常執行了
- 當寫端輸入quite時,寫端不存在了,當寫端不存在了,並且管道中沒有資料資料,讀管道會立刻返回0,返回0,就會退出迴圈,程式結束