自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Linux進(jìn)程通信之管道解析

系統(tǒng) Linux
所謂的管道,也就是內(nèi)核里面的一串緩存,從管道的一段寫入的數(shù)據(jù),實(shí)際上是緩存在內(nèi)核中的,令一端讀取,也就是從內(nèi)核中讀取這段數(shù)據(jù)。

 [[409600]]

概述

管道是 UNIX系統(tǒng) IPC的最古老的形式,所有的UNIX系統(tǒng)都提供此種通信。所謂的管道,也就是內(nèi)核里面的一串緩存,從管道的一段寫入的數(shù)據(jù),實(shí)際上是緩存在內(nèi)核中的,令一端讀取,也就是從內(nèi)核中讀取這段數(shù)據(jù)。對(duì)于管道傳輸?shù)臄?shù)據(jù)是無(wú)格式的流且大小受限。對(duì)于管道來(lái)說(shuō),也分為匿名管道和命名管道,其中命名管道也被叫做 FIFO,下面則分別闡述這兩種管道。

匿名管道

默認(rèn)情況下,在 Shell命令執(zhí)行過(guò)程中,任何一個(gè)命令都有一個(gè)標(biāo)準(zhǔn)輸入設(shè)備(鍵盤)、標(biāo)準(zhǔn)輸出設(shè)備(顯示器)和標(biāo)準(zhǔn)輸出設(shè)備(顯示器),使用管道"|"可以將兩個(gè)命令連接起來(lái),從而改變標(biāo)準(zhǔn)的輸入輸出方式,下面是在 Linux 端運(yùn)行命令行的一個(gè)截圖:

上述命令中的意思也就是,將ls命令得到的結(jié)果作為 grep tags命令的輸入。

連接輸入輸出的中間設(shè)備即為一個(gè)管道文件,綜上,也就是說(shuō)使用管道可以將一個(gè)命令的輸出作為另一個(gè)命令的輸入(在運(yùn)行的時(shí)候,一個(gè)命令將創(chuàng)建一個(gè)進(jìn)程),而這種管道是臨時(shí)的,命令執(zhí)行完畢之后就會(huì)自動(dòng)消失,這類管道稱為無(wú)名管道。

匿名管道例子

匿名管道在使用前要先創(chuàng)建,其函數(shù)的聲明如下:

  1. extern int pipe (int __pipedes[2]); 

此函數(shù)的參數(shù)是一個(gè)整型數(shù)組,如果執(zhí)行成功,pipe 將存儲(chǔ)兩個(gè)整型文件描述符于__pipedes[0]和__pipedes[1]中,他們分別指向管道的兩端。如果系統(tǒng)調(diào)用失敗,則返回 -1。

讀無(wú)名管道,該函數(shù)的聲明如下:

  1. extern ssize_t read (int __fd, void *__buf, size_t __nbytes); 

第一個(gè)參數(shù)fd為打開的文件描述符,buf為讀出數(shù)據(jù)的存儲(chǔ)位置,nbytes為讀取數(shù)據(jù)的大小,調(diào)用 read 函數(shù)將從 fd 指向的文件描述符指定的打開文件中宏讀 n 字節(jié)到 buf 指向的緩沖區(qū)內(nèi)。

如果試圖向已經(jīng)填滿的管道寫入,系統(tǒng)會(huì)自動(dòng)阻塞。一個(gè)管道不能同時(shí)被兩個(gè)進(jìn)程打開。

  1. extern ssize_ t write(int __fd, __const void *__buf, size_t __n); 

從 buf指向的緩沖區(qū)中向管道中寫入nbytes字節(jié),且每次寫入的內(nèi)容都附件在管道的末端。

那要如何使用管道在兩個(gè)進(jìn)程之間通信呢,我們可以使用 fork()創(chuàng)建子進(jìn)程,創(chuàng)建的子進(jìn)程會(huì)復(fù)制父進(jìn)程的文件描述符,這樣就做到了兩個(gè)進(jìn)程各有兩個(gè)fd[0]與fd[1],兩個(gè)進(jìn)程就可以通過(guò)各自的fd寫入和讀取同一個(gè)管道文件實(shí)現(xiàn)進(jìn)程通信了,具體原理如下所示:

具體的例子如下所示:

  1. #include<unistd.h> 
  2. #include<stdio.h> 
  3. #include<stdlib.h> 
  4.  
  5. int main(int argc, char *argv[]) 
  6.     pid_t pid; 
  7.     int temp
  8.     int pipedes[2]; 
  9.     char s[14] = "test message!"
  10.     char d[14]; 
  11.  
  12.     if (pipe(pipedes) == -1) // 創(chuàng)建管道 
  13.     { 
  14.         perror("pipe"); 
  15.         exit(EXIT_FAILURE); 
  16.     } 
  17.  
  18.     if (pid == fork() == -1) 
  19.     { 
  20.         perror("fork"); 
  21.         exit(EXIT_FAILURE); 
  22.     } 
  23.     else if (pid == 0)      // 子進(jìn)程 
  24.     { 
  25.         printf("now,write data to pipe\n"); 
  26.         if (write(pipedes[1], s, 14) == -1)   // 寫數(shù)據(jù)到管道 
  27.         { 
  28.             perror("write"); 
  29.             exit(EXIT_FAILURE); 
  30.         } 
  31.         else 
  32.         { 
  33.             printf("the written data is:%s\n",s); 
  34.             exit(EXIT_SUCESS); 
  35.         } 
  36.     } 
  37.     else if (pid > 0)     // 父進(jìn)程 
  38.     { 
  39.         slepp(2); 
  40.         printf("now, read from pipe\n"); 
  41.         if ((read(pipedes[0], d, 14)) == -1) 
  42.         { 
  43.             perror("read"); 
  44.             exit(EXIT_FAILURE); 
  45.         } 
  46.         printf("the data from pipe is:%s\n",d); 
  47.     } 
  48.     return 0; 

代碼運(yùn)行的結(jié)果如下所示:

命名管道

命名管道又被稱之為是 FIFO ,未命名的管道只能在兩個(gè)相關(guān)的進(jìn)程之間使用,而且這兩個(gè)相關(guān)的進(jìn)程還要又一個(gè)共同創(chuàng)建了他們的祖先進(jìn)程,但是,通過(guò) FIFO ,不相關(guān)的進(jìn)程也能交換數(shù)據(jù)。

首先,介紹下是如何創(chuàng)建命名管道的:

  1. extern int mkfifo (__const char *__path, __mode_t __mode); 

mkfifo會(huì)根據(jù)參數(shù)建立特殊的有名管道文件,該文件必須不存在,而參數(shù)mode為該文件的權(quán)限。

下面是一個(gè)使用命名管道進(jìn)行進(jìn)程間通信的例子,例子分為兩個(gè)程序,分別是讀部分和寫部分,首先看先往管道寫數(shù)據(jù)的代碼,代碼如下所示:

  1. #include <stdio.h>  
  2. #include <string.h>  
  3. #include <fcntl.h>  
  4. #include <sys/stat.h>  
  5. #include <sys/types.h>  
  6. #include <unistd.h>  
  7.  
  8. int main()  
  9. {  
  10.     int fd;  
  11.  
  12.     // FIFO file path  
  13.     char * myfifo = "/tmp/myfifo";  
  14.  
  15.     // Creating the named file(FIFO)  
  16.     // mkfifo(<pathname>, <permission>)  
  17.     mkfifo(myfifo, 0666);  
  18.  
  19.     char arr1[80], arr2[80];  
  20.     while (1)  
  21.     {  
  22.         // Open FIFO for write only  
  23.         fd = open(myfifo, O_WRONLY);  
  24.         printf("The fd is:%d\n",fd); 
  25.  
  26.         // Take an input arr2ing from user.  
  27.         // 80 is maximum length  
  28.         fgets(arr2, 80, stdin);  
  29.  
  30.         // Write the input arr2ing on FIFO  
  31.         // and close it  
  32.         write(fd, arr2, strlen(arr2)+1);  
  33.         close(fd);  
  34.  
  35.         // Open FIFO for Read only  
  36.         fd = open(myfifo, O_RDONLY);  
  37.  
  38.         // Read from FIFO  
  39.         read(fd, arr1, sizeof(arr1));  
  40.  
  41.         // Print the read message  
  42.         printf("User2: %s", arr1);  
  43.         close(fd);  
  44.     }  
  45.     return 0;  

然后是先往管道讀數(shù)據(jù)的代碼,代碼如下所示:

  1. #include <stdio.h>  
  2. #include <string.h>  
  3. #include <fcntl.h>  
  4. #include <sys/stat.h>  
  5. #include <sys/types.h>  
  6. #include <unistd.h>  
  7.  
  8. int main()  
  9. {  
  10.     int fd1;  
  11.  
  12.     // FIFO file path  
  13.     char * myfifo = "/tmp/myfifo";  
  14.  
  15.     char str1[80], str2[80];  
  16.     while (1)  
  17.     {  
  18.         // First open in read only and read  
  19.         fd1 = open(myfifo,O_RDONLY);  
  20.         printf("The fd is:%d\n",fd1); 
  21.         read(fd1, str1, 80);  
  22.  
  23.         // Print the read string and close  
  24.         printf("User1: %s", str1);  
  25.         close(fd1);  
  26.  
  27.         // Now open in write mode and write  
  28.         // string taken from user.  
  29.         fd1 = open(myfifo,O_WRONLY);  
  30.         fgets(str2, 80, stdin);  
  31.         write(fd1, str2, strlen(str2)+1);  
  32.         close(fd1);  
  33.     }  
  34.     return 0;  
  35. }  

下面是代碼運(yùn)行的一個(gè)結(jié)果:

說(shuō)明一下,就是說(shuō)當(dāng)運(yùn)行 write程序的時(shí)候,會(huì)創(chuàng)建fifo文件,命名管道,然后,在 write文件中就執(zhí)行open操作,但是,這里存在的一個(gè)問(wèn)題就是,因?yàn)樵谶\(yùn)行 write程序的時(shí)候,沒(méi)有進(jìn)程打開讀端,也就阻塞了 open函數(shù)的運(yùn)行,只有運(yùn)行read操作,以讀的方式讀取管道的數(shù)據(jù),這樣才能使得write中的open函數(shù)繼續(xù)執(zhí)行。

綜上,也就是命名管道在進(jìn)程中通信的一個(gè)例子。

小結(jié)

上述就是本次進(jìn)程通信中關(guān)于管道的相關(guān)內(nèi)容,其中就包括匿名管道以及命名管道,他們之間存在著差別嗎,也各有各的應(yīng)用,本次的分享就到這里啦~

本文轉(zhuǎn)載自微信公眾號(hào)「wenzi嵌入式軟件」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系wenzi嵌入式軟件公眾號(hào)。

 

責(zé)任編輯:武曉燕 來(lái)源: wenzi嵌入式軟件
相關(guān)推薦

2021-09-30 10:45:33

Linux進(jìn)程通信

2019-05-13 10:00:41

Linux進(jìn)程間通信命令

2010-03-02 10:27:56

Linux進(jìn)程狀態(tài)

2010-03-02 10:43:45

Linux進(jìn)程狀態(tài)

2010-01-05 10:00:48

Linux進(jìn)程間通信

2011-06-22 16:50:09

Qt 進(jìn)程 通信機(jī)制

2010-01-21 11:22:35

Linux多線程同步

2023-03-05 16:12:41

Linux進(jìn)程線程

2011-06-24 14:01:34

Qt QCOP 協(xié)議

2009-12-24 14:47:42

Linux系統(tǒng)進(jìn)程

2018-01-12 14:35:00

Linux進(jìn)程共享內(nèi)存

2017-06-19 13:36:12

Linux進(jìn)程消息隊(duì)列

2023-03-02 23:50:36

Linux進(jìn)程管理

2011-06-22 17:27:19

QT 進(jìn)程通信

2021-02-14 21:05:05

通信消息系統(tǒng)

2009-02-23 15:55:29

ASP.NET.NET性能提升

2011-01-11 13:47:27

Linux管理進(jìn)程

2023-03-03 00:03:07

Linux進(jìn)程管理

2011-08-08 10:02:55

iPhone開發(fā) 進(jìn)程 通信

2019-05-08 11:10:05

Linux進(jìn)程語(yǔ)言
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)