日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

linux进程间通信:shell管道 | 的实现

發布時間:2023/11/27 生活经验 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux进程间通信:shell管道 | 的实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

      • 介紹
      • 重定向函數介紹
      • 總結

linux terminal輸入如下命令,其中"|"符號即為我們上文中所說的無名管道

介紹

正如我們上文中所描述的"|“無名管道提供了具有親緣關系的進程之間的通信,它由于直接使用系統調用,運行效率較高。則linux系統下可以大批量的使用”|"來提供命令直接輸入輸出的重定向。

具體shell中管道的實現可以參考如下圖:

當我們直接執行lsmod時,此時進程文件描述符默認會打開標準輸入,標準輸出,標準錯誤三個文件。lsmod的輸出內容會寫到標準輸出設備,即linux terminal顯示屏。當我們加入了管道,其最終將標準輸出重定向到管道的f[1]寫描述符。

具體流程如下:
a. 將命令封裝成進程:通過fork/exec系統調用
b. 該進程此時會默認打開stdin 0 ,stdout 1 ,sdterr 2 連接到終端上
c. 運行的命令從鍵盤讀取數據并且把輸出和錯誤消息寫到屏幕上(標準輸出一般默認是屏幕)
d. 通過重定向,可以從指定文件讀取數據,或將數據輸出到指定文件
e. 重定向IO的功能是由shell本身實現,標準流與文件連接
f. 程序本身并不知道數據最后流向哪里,他只知道將自身輸出寫到標準輸出中
g. 通過命令:cmd > file 告訴shell將stdout定位到的文件file,于是shell就將文件描述符與指定的文件連接起來,程序將輸出放入file而不是默認的屏幕

重定向函數介紹

如下三個函數

#include <unistd.h>
int dup(int oldfd); //將old文件描述符重定向給返回值
int dup2(int oldfd, int newfd); //重定向成功,則返回重定向后新的文件句柄#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include <fcntl.h>              /* Obtain O_* constant definitions */
#include <unistd.h>
int dup3(int oldfd, int newfd, int flags);

以上dup,dup2,dup3函數在shell中實現了將輸入輸出設備和管道聯系了起來,將輸入輸出重定向到具體文件之中

  • int dup(int oldfd)
    其中dup函數實現了將舊的文件描述符拷貝給新的文件描述符,此時old_fd和new_fd將會共享同一個文件的狀態標記(讀寫權限等),文件偏移地址等

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <fcntl.h>int main()
    {int fd,new_fd;//打開文件fd = open("write.txt",O_RDWR | O_CREAT,777);if(fd == -1){perror("open failed");exit (-1);}//將fd文件描述符拷貝到新的文件描述符,兩個文件描述符共享同一個文件new_fd = dup(fd);write(fd, "hello",strlen("hello"));write(new_fd, "world", strlen("world"));write(fd, "zhang", strlen("world"));//緊接著new_fd對文件寫操作之后的偏移地址進行寫close(fd);close(new_fd);return 0;
    }
    

    如果我們將以上中new_fd置為1(1的文件句柄代表標準輸出),則write的結果將輸出到屏幕
    如下代碼:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>int main()
    {int new_fd;new_fd = dup(1); //將new_fd重定向到標準輸出,即copy一個標準輸出到new_fdwrite(1,"hello",strlen("hello"));write(new_fd,"world\n",strlen("wrold\n")); //此時操作系統為該進程文件重新分配一個文件句柄3,因為0,1,2已經被占用//printf("new_fd = %d\n",new_fd);close(new_fd);return 0;
    }
    
  • int dup2(int old_fd,int new_fd)
    dup2函數和dup函數可以指定 我們想要重定向到的文件句柄,比如我們想將標準輸出重定向到指定的文件
    查看如下代碼:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <fcntl.h>int main()
    {int fd,new_fd;char *ptr = "hello world\n";fd = open("data.log",O_RDWR | O_CREAT,664);if (fd == 0) {perror("open failed");exit(-1);}new_fd = dup2(fd,1); //將標準輸出重定向到fd文件句柄,即data.log文件if (new_fd == -1) {perror("open failed ");exit(-1);}printf("fd : %d \n new_fd :%d\n",fd,new_fd); //同樣是標準輸出,那么它的輸出也會輸出到 fd文件句柄。同時對new_fd的操作即為對標準輸出的操作write(1,ptr,strlen(ptr));write(new_fd,"i am new\n",strlen("i am new\n"));//向new_fd中寫入,即向標準輸出中寫入,但是此時標準輸出已經重定向到了data.log中close(fd);return 0;
    }
    

    輸出如下:
    此時這個輸出很有意思,可以發現c語言的面向過程式有點不太對,為什么write(" i am new")是在printf之后調用,但是它的輸出結果確是在prinf前輸出呢?這里很明顯,printf函數的同樣是標準輸出,但是它是在程序執行完成之后將結果重定向到標準輸出的,而我們調用write(“i am new”)確是已經在運行過程中將結果通過標準輸出重定向到文件,所以此時printf的輸出會晚于用重定向函數的結果

    [root@node1 /]# cat data.log 
    hello world
    i am new
    fd : 3 new_fd :1
    

    通過管道以及重定向實現如下操作lsmod |grep snd
    基本流程如下

    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <string.h>
    #include <fcntl.h>int main()
    {int pipe_fd [2]; if (pipe(pipe_fd) == -1) {//創建一個管道perror("pipe");exit (-1);} else {int ret;ret = fork();if (ret == 0) { //標準輸出重定向到管道的寫端,即lsmod的輸出將重定向到f[1]dup2(pipe_fd[1],1);execlp("lsmod","lsmod",NULL,NULL);}else {dup2(pipe_fd[0],0); //從f[0]讀出f[1]寫入的內容到標準輸入close(pipe_fd[1]); execlp("grep","grep","snd",NULL);}}return 0;
    }
    

總結

通過以上探討,我們了解了linux shell中管道以及重定向符的實現原理,通過dup系列函數對進程文件句柄的復制實現。有意思~

總結

以上是生活随笔為你收集整理的linux进程间通信:shell管道 | 的实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。