成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

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

系統 Linux
本文中會有多個地方使用 Unix 這個術語(而不是Linux),因為管道的概念起源于 Unix。

我們在命令行中經常會用到類似 cmd0 | cmd1 | cmd2 的寫法。其實,這是管道重定向(pipe redirection),用于將一個命令的輸出作為輸入重定向到下一個命令。

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

注:本文中會有多個地方使用 Unix 這個術語(而不是Linux),因為管道的概念起源于 Unix。

Linux 中的管道:總體思路

以下是關于“什么是 Unix 管道?”的內容:

Unix 管道是一種 IPC(Inter Process Communication,進程間通信)機制,它將一個程序的輸出轉發到另一程序的輸入。

現在,我們換一種更加專業且易懂的語言重新解釋一下:

Unix 管道是一種 IPC(Inter Process Communication,進程間通信)機制,它接收程序的標準輸出(stdout),并通過緩沖區將其轉發給另一個程序的標準輸入(stdin)。

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

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

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

管道將標準輸出重定向到標準輸入,但不是作為命令參數

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

如果我們不帶任何參數使用 cat 命令,它默認會從 stdin 讀取內容。看下面的例子:

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

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

現在,看如下命令:

echo hey | cat

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

為了演示這個區別,我們可以創建一個名為 hey 的文件,并在其中添加一些文本。參見下圖:

Linux 中的管道類型

Linux 中有兩種類型的管道:

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

2)命名管道。

匿名管道

顧名思義,匿名管道就是沒有名稱。當你使用 | 符號時,它們就會由 Unix shell 動態創建了。

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

命名管道

這個稍有不同,命名管道在文件系統中確實存在。它們像普通文件一樣存在,可以使用下面的命令創建命名管道:

mkfifo pipe

這將創建一個名為 pipe 的文件,執行以下命令:

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

請注意開頭的“p”,這意味著該文件是一個管道。現在我們來使用這個管道。

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

echo hey > pipe

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

cat pipe

我們看下兩個終端的輸出結果,如下圖所示:

驚訝嗎?這兩個命令同時完成了執行。

這是普通文件和命名管道之間的基本區別之一。在其他進程讀取管道之前,不會將任何內容寫入管道。

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

命名管道不會占用磁盤上的任何內存。

如果我們執行命令 du -s pipe,就會發現它不會占用任何空間。這是因為命名管道就像從內存緩沖區讀寫的端點。寫入命名管道的任何內容實際上都存儲在臨時內存緩沖區中,當從另一個進程執行讀取操作時,該緩沖區將被刷新。

節省 IO

因為寫入命名管道意味著將數據存儲到內存中的緩沖區中,因此如果涉及大文件的操作的話,就會大幅減少磁盤 I/O。

兩個不同進程之間的通信

通過使用命名管道,可以高效地從另一個進程實時獲取事件的輸出。因為讀和寫同時發生,所以沒有等待時間。

較低層次的管道理解(針對高級用戶和開發人員)

接下來我們更深入的討論一下管道,以及具體的實現。這些需要對以下內容有基本的了解:

  • C 程序工作原理;
  • 什么是系統調用;
  • 什么是進程;
  • 什么是文件描述符。

我們不會很詳細的介紹這些概念,只討論與管道相關的內容。對于大多數Linux用戶來說,下面的內容可以選擇性的閱讀。

為了進行編譯,在文章最后提供了一個示例 makefile。當然,這只是用來說明的偽代碼。

看以下程序:

// 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() 函數創建了一個匿名管道,傳遞了一個長度為 2 的帶符號整數數組。

這是因為管道只是一個包含兩個無符號整數的數組,代表兩個文件描述符。一個用于寫,一個用于讀。它們都指向內存上的緩沖區位置,通常為1mb。

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

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

下面是一個示例程序,它執行與前一個程序相同的操作,但它創建的不是匿名管道,而是命名管道:

// 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 系統調用來創建命名管道。如你所見,雖然在完成時刪除了管道,但你可以不使用它,只需要打開并寫入本例中的 npipe 文件,就可以輕松的實現在不同進程之間的通信。

其實現實中,我們也不必創建兩個管道來實現雙向通信,匿名管道就是這樣的。

以下是一個簡單的 Makefile 的源代碼示例(只是示例),將其與前面的程序放在同一個目錄中(分別為 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

以上就是本次分享的關于 Unix 管道的全部內容,歡迎討論。

責任編輯:龐桂玉 來源: TIAP
相關推薦

2020-12-09 11:10:12

shellLinux管道

2020-02-24 11:37:56

Linux重定向管道

2020-04-17 08:34:39

Linux管道

2009-06-17 17:13:40

UNIX

2018-09-10 08:45:04

Linux管道命令

2021-02-20 20:36:56

Linux無名管道

2009-06-17 09:11:24

Unix管道重定向

2021-07-02 16:30:01

CICDDevOps

2022-11-10 15:08:44

Linux輸入輸出

2023-08-08 07:18:17

協程管道函數

2023-01-30 15:55:08

2015-10-08 10:44:06

PB級數據管道處理Docker容器

2010-12-14 15:07:15

ICMP路由重定向

2017-01-19 19:14:20

Linux重定向命令

2010-03-09 16:11:59

Linux重定向

2023-05-05 08:18:38

Linuxsource命令

2021-07-13 11:12:49

Discover數據管道AI

2020-02-07 18:16:01

進程線程底層原理

2010-10-25 16:52:48

oracle管道函數

2014-07-02 21:20:56

CA TechnoloAPI
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲一区二区视频在线播放 | 日韩第一区| 久久手机视频 | 亚洲欧美视频一区二区 | 国产精品久久久久无码av | 午夜小视频在线播放 | 国产精品1区2区3区 男女啪啪高潮无遮挡免费动态 | 色精品视频 | 亚洲天堂中文字幕 | 99久久精品国产一区二区三区 | 日韩播放 | 欧美成年网站 | 在线资源视频 | 成年人黄色一级毛片 | 久久精品亚洲欧美日韩精品中文字幕 | 日韩一级免费大片 | 中文字幕1区2区3区 亚洲国产成人精品女人久久久 | 国产97人人超碰caoprom | 成人久久18免费网站麻豆 | 日韩成人免费在线视频 | 中文字幕色站 | 欧美亚洲国产一区 | 免费一看一级毛片 | 五月槐花香 | 自拍视频网站 | 久久大陆 | 国产免费拔擦拔擦8x高清 | 拍真实国产伦偷精品 | 久久精品视频一区二区三区 | 91精品国产欧美一区二区 | 欧美综合一区 | 亚洲成人综合网站 | 国产精品美女久久久久久久久久久 | 久久一级 | 成人av高清 | 国产探花| 国产一区久久 | 久久久激情视频 | 福利av在线 | 性一爱一乱一交一视频 | 欧美日韩大片 |