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

Linux 中的管道是什么?管道重定向是如何工作的?

系統(tǒng) Linux
本文中會(huì)有多個(gè)地方使用 Unix 這個(gè)術(shù)語(而不是Linux),因?yàn)楣艿赖母拍钇鹪从?Unix。

我們?cè)诿钚兄薪?jīng)常會(huì)用到類似 cmd0 | cmd1 | cmd2 的寫法。其實(shí),這是管道重定向(pipe redirection),用于將一個(gè)命令的輸出作為輸入重定向到下一個(gè)命令。

那么,你知道它具體是怎么工作的嗎?今天我們來詳細(xì)了解一下。

注:本文中會(huì)有多個(gè)地方使用 Unix 這個(gè)術(shù)語(而不是Linux),因?yàn)楣艿赖母拍钇鹪从?Unix。

Linux 中的管道:總體思路

以下是關(guān)于“什么是 Unix 管道?”的內(nèi)容:

Unix 管道是一種 IPC(Inter Process Communication,進(jìn)程間通信)機(jī)制,它將一個(gè)程序的輸出轉(zhuǎn)發(fā)到另一程序的輸入。

現(xiàn)在,我們換一種更加專業(yè)且易懂的語言重新解釋一下:

Unix 管道是一種 IPC(Inter Process Communication,進(jìn)程間通信)機(jī)制,它接收程序的標(biāo)準(zhǔn)輸出(stdout),并通過緩沖區(qū)將其轉(zhuǎn)發(fā)給另一個(gè)程序的標(biāo)準(zhǔn)輸入(stdin)。

這樣的描述,大家應(yīng)該能理解了。參考下圖可以了解管道的工作原理:

管道命令的最簡單示例之一是將一些命令輸出傳遞給 grep 命令以搜索特定字符串。

比如,我們可以搜索名稱包含txt的文件,如下所示:

管道將標(biāo)準(zhǔn)輸出重定向到標(biāo)準(zhǔn)輸入,但不是作為命令參數(shù)

有個(gè)非常重要的一點(diǎn)需要注意,管道命令將標(biāo)準(zhǔn)輸出(stdout)傳遞到另一個(gè)命令的標(biāo)準(zhǔn)輸入(stdin),但不是作為參數(shù)。下面我們舉個(gè)例子來說明這一點(diǎn)。

如果我們不帶任何參數(shù)使用 cat 命令,它默認(rèn)會(huì)從 stdin 讀取內(nèi)容??聪旅娴睦樱?/p>

$ cat
Hello, my friend.
^D
Hello, my friend.

在上面的例子中,沒有帶任何參數(shù)使用了 cat,因此它默認(rèn)會(huì)讀取 stdin。接下來,我寫了一行文字,然后按鍵 Ctrl+d 告訴它我寫完了(Ctrl+d 表示 EOF 或文件結(jié)束)。隨后,cat 命令讀取 stdin,然后把之前我寫的那行文字輸出到了終端中。

現(xiàn)在,看如下命令:

echo hey | cat

管道右邊的命令并不等于 cat hey。這里,標(biāo)準(zhǔn)輸出(stdout)"hey" 被放在了緩沖區(qū)(buffer),并被傳輸?shù)搅?cat 命令的標(biāo)準(zhǔn)輸入(stdin)。由于沒有命令行參數(shù),所以 cat 默認(rèn)讀取 stdin,而 stdin 中恰好有了內(nèi)容(即“hey”),因此 cat 讀取了這個(gè)內(nèi)容,并將其打印到 stdout。

為了演示這個(gè)區(qū)別,我們可以創(chuàng)建一個(gè)名為 hey 的文件,并在其中添加一些文本。參見下圖:

Linux 中的管道類型

Linux 中有兩種類型的管道:

1)匿名管道,也就是未命名管道;

2)命名管道。

匿名管道

顧名思義,匿名管道就是沒有名稱。當(dāng)你使用 | 符號(hào)時(shí),它們就會(huì)由 Unix shell 動(dòng)態(tài)創(chuàng)建了。

我們通常所說的管道,就是指的匿名管道。它用起來很方便,作為最終用戶,我們不需要跟蹤它的運(yùn)行,shell 自動(dòng)會(huì)處理這一切。

命名管道

這個(gè)稍有不同,命名管道在文件系統(tǒng)中確實(shí)存在。它們像普通文件一樣存在,可以使用下面的命令創(chuàng)建命名管道:

mkfifo pipe

這將創(chuàng)建一個(gè)名為 pipe 的文件,執(zhí)行以下命令:

$ ls -l pipe
prw-r--r--. 1 gliu gliu 0 Aug 4 17:23 pipe

請(qǐng)注意開頭的“p”,這意味著該文件是一個(gè)管道?,F(xiàn)在我們來使用這個(gè)管道。

如前所述,管道將命令的輸出轉(zhuǎn)發(fā)給另一個(gè)命令的輸入。這就像快遞服務(wù),你把包裹從一個(gè)地址送到另一個(gè)地址。因此,第一步是提供包裹。

echo hey > pipe

我們會(huì)看到 echo 信息沒有打印出來,看起來像是被掛起了。新打開一個(gè)終端,嘗試讀取該文件:

cat pipe

我們看下兩個(gè)終端的輸出結(jié)果,如下圖所示:

驚訝嗎?這兩個(gè)命令同時(shí)完成了執(zhí)行。

這是普通文件和命名管道之間的基本區(qū)別之一。在其他進(jìn)程讀取管道之前,不會(huì)將任何內(nèi)容寫入管道。

那么,為什么要使用命名管道呢?我們來看一下。

命名管道不會(huì)占用磁盤上的任何內(nèi)存。

如果我們執(zhí)行命令 du -s pipe,就會(huì)發(fā)現(xiàn)它不會(huì)占用任何空間。這是因?yàn)槊艿谰拖駨膬?nèi)存緩沖區(qū)讀寫的端點(diǎn)。寫入命名管道的任何內(nèi)容實(shí)際上都存儲(chǔ)在臨時(shí)內(nèi)存緩沖區(qū)中,當(dāng)從另一個(gè)進(jìn)程執(zhí)行讀取操作時(shí),該緩沖區(qū)將被刷新。

節(jié)省 IO

因?yàn)閷懭朊艿酪馕吨鴮?shù)據(jù)存儲(chǔ)到內(nèi)存中的緩沖區(qū)中,因此如果涉及大文件的操作的話,就會(huì)大幅減少磁盤 I/O。

兩個(gè)不同進(jìn)程之間的通信

通過使用命名管道,可以高效地從另一個(gè)進(jìn)程實(shí)時(shí)獲取事件的輸出。因?yàn)樽x和寫同時(shí)發(fā)生,所以沒有等待時(shí)間。

較低層次的管道理解(針對(duì)高級(jí)用戶和開發(fā)人員)

接下來我們更深入的討論一下管道,以及具體的實(shí)現(xiàn)。這些需要對(duì)以下內(nèi)容有基本的了解:

  • C 程序工作原理;
  • 什么是系統(tǒng)調(diào)用;
  • 什么是進(jìn)程;
  • 什么是文件描述符。

我們不會(huì)很詳細(xì)的介紹這些概念,只討論與管道相關(guān)的內(nèi)容。對(duì)于大多數(shù)Linux用戶來說,下面的內(nèi)容可以選擇性的閱讀。

為了進(jìn)行編譯,在文章最后提供了一個(gè)示例 makefile。當(dāng)然,這只是用來說明的偽代碼。

看以下程序:

// pipe.c
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <errno.h>
extern int errno;
int main(){
signed int fd[2];
pid_t pid;
static char input[50];
static char buf[50];
pipe(fd);
if((pid=fork())==-1){
int err=errno;
perror("fork failed");
exit(err);
}
if(pid){
close(fd[1]);
read(fd[0], buf, 50);
printf("The message read from child: %s\n", buf);
} else {
close(fd[0]);
printf("Enter a message from parent: ");
for(int i=0; (input[i]=getchar())!=EOF && input[i]!='\n' && i<49; i++);
write(fd[1], input, 50);
exit(0);
}
return 0;
}

在第16行,我使用 pipe() 函數(shù)創(chuàng)建了一個(gè)匿名管道,傳遞了一個(gè)長度為 2 的帶符號(hào)整數(shù)數(shù)組。

這是因?yàn)楣艿乐皇且粋€(gè)包含兩個(gè)無符號(hào)整數(shù)的數(shù)組,代表兩個(gè)文件描述符。一個(gè)用于寫,一個(gè)用于讀。它們都指向內(nèi)存上的緩沖區(qū)位置,通常為1mb。

這里我將變量命名為fd。fd[0] 是輸入文件描述符,fd[1] 是輸出文件描述符。在該程序中,一個(gè)進(jìn)程將字符串寫入 fd[1] 文件描述符,另一個(gè)進(jìn)程從 fd[0] 文件描述符讀取。

命名管道也一樣,使用命名管道(而不是兩個(gè)文件描述符),你可以從任何一個(gè)進(jìn)程中打開一個(gè)文件,并像其他文件一樣對(duì)其進(jìn)行操作。同時(shí)應(yīng)記住管道的特性。

下面是一個(gè)示例程序,它執(zhí)行與前一個(gè)程序相同的操作,但它創(chuàng)建的不是匿名管道,而是命名管道:

// fifo.c
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
extern int errno;
#define fifo "npipe"
int main(void){
pid_t pid;
static char input[50];
static char buf[50];
signed int fd;
mknod(fifo, S_IFIFO|0700, 0);

if((pid=fork())<0){
int err=errno;
perror("Fork failed");
exit(err);
}
if(pid){
fd=open(fifo, O_RDONLY);
read(fd, buf, 50);
close(fd);
printf("The output is : %s", buf);
remove(fifo);
exit(0);
} else {
fd=open(fifo, O_WRONLY);
for(int i=0; (input[i]=getchar())!=EOF && input[i]!='\n' && i<49; i++);
write(fd, input, strlen(input));
close(fd);
exit(0);
}
return 0;
}

在這里,我使用 mknod 系統(tǒng)調(diào)用來創(chuàng)建命名管道。如你所見,雖然在完成時(shí)刪除了管道,但你可以不使用它,只需要打開并寫入本例中的 npipe 文件,就可以輕松的實(shí)現(xiàn)在不同進(jìn)程之間的通信。

其實(shí)現(xiàn)實(shí)中,我們也不必創(chuàng)建兩個(gè)管道來實(shí)現(xiàn)雙向通信,匿名管道就是這樣的。

以下是一個(gè)簡單的 Makefile 的源代碼示例(只是示例),將其與前面的程序放在同一個(gè)目錄中(分別為 pipe.c 和 fifo.c)。

CFLAGS?=-Wall -g -O2 -Werror
CC?=clang
build:
$(CC) $(CFLAGS) -o pipe pipe.c
$(CC) $(CFLAGS) -o fifo fifo.c
clean:
rm -rf pipe fifo

以上就是本次分享的關(guān)于 Unix 管道的全部內(nèi)容,歡迎討論。

責(zé)任編輯:龐桂玉 來源: TIAP
相關(guān)推薦

2020-12-09 11:10:12

shellLinux管道

2020-02-24 11:37:56

Linux重定向管道

2020-04-17 08:34:39

Linux管道

2009-06-17 09:11:24

Unix管道重定向

2009-06-17 17:13:40

UNIX

2021-02-20 20:36:56

Linux無名管道

2018-09-10 08:45:04

Linux管道命令

2021-07-02 16:30:01

CICDDevOps

2022-11-10 15:08:44

Linux輸入輸出

2023-01-30 15:55:08

2017-01-19 19:14:20

Linux重定向命令

2010-03-09 16:11:59

Linux重定向

2023-08-08 07:18:17

協(xié)程管道函數(shù)

2015-10-08 10:44:06

PB級(jí)數(shù)據(jù)管道處理Docker容器

2010-12-14 15:07:15

ICMP路由重定向

2014-07-02 21:20:56

CA TechnoloAPI

2021-07-13 11:12:49

Discover數(shù)據(jù)管道AI

2014-08-07 10:23:24

linux重定向

2021-07-06 21:30:06

Linux進(jìn)程通信

2010-10-25 16:52:48

oracle管道函數(shù)
點(diǎn)贊
收藏

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