1. 程式人生 > >嵌入式Linux併發程式設計,程序間通訊方式,有名管道,有名管道特點,有名管道建立mkfifo()

嵌入式Linux併發程式設計,程序間通訊方式,有名管道,有名管道特點,有名管道建立mkfifo()

1,有名管道的特點

  1. 對應管道檔案,可用於任意程序之間進行通訊:有名管道建立好之後,在系統中有實際的檔案和有名管道對應,任意兩個程序可以通過路徑和檔名指定同一個有名管道進行通訊
  2. 開啟管道時可指定讀寫方式:有名管道用open()開啟的時候可以指定不同的讀寫方式,從而可以確定讀端和寫端
  3. 通過檔案IO操作,內容存放在記憶體中:通過檔案IO read()和write()進行操作。雖然有名管道有一個實際的檔案被建立,在檔案系統中可見,但是往管道中寫入的所有內容實際上依然是存放在記憶體中的(跟無名管道一樣),當所有的讀端和寫端都關閉的時候,管道存放在記憶體中的內容都會被釋放
  4. 有名管道開啟的時候有可能會阻塞。當只有讀端或只有寫端的時候,open()會阻塞,只有當讀端和寫端同時存在的時候,open()才會返回,程式才會繼續執行。

2,有名管道的建立mkfifo()

#include <unistd.h> #include <fcntl.h> int mkfifo(const char *path, mode_t mode);

  1. 成功時返回0,失敗時返回EOF(如果建立的管道已經存在,建立就會失敗)
  2. path 建立的管道檔案路徑
  3. 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
  1. 當程序開啟一個有名管道的時候,如果當前只有讀端或只有寫端,open()會阻塞 open()的下一條指令 printf(“read myfifo\n”);//程序開啟管道後顯示這一句 沒有執行
  2. 只有當讀端和寫端都存在是,兩個程序中的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$
  1. 執行fifo_write.out後,管道有了寫端,讀程序和寫程序的open()才能正常執行,可以看到open()的下一條指令 printf(“read myfifo\n”);//程序開啟管道後顯示這一句 printf(“write myfifo\n”);//程序開啟管道後顯示這一句 正常執行了
  2. 當寫端輸入quite時,寫端不存在了,當寫端不存在了,並且管道中沒有資料資料,讀管道會立刻返回0,返回0,就會退出迴圈,程式結束