UNIX環境變數 IPC之管道通訊

2021-10-04 22:26:33 字數 4087 閱讀 6590

無名管道是一種特殊型別的檔案,完全由作業系統管理和維護,因為其儲存位置只有親緣關係的程序知道,所以只能用於親緣關係的程序之間通訊,而且,其核心資源會在兩個通訊程序退出後自動釋放,無名管道建立函式為:

//from /usr/include/unistd.h

int pipe(int fd[2]);

函式pipe()返回兩個檔案描述符,其中fd[0]用來完成讀操作,fd[1]完成寫操作,預設阻塞方式。

以阻塞方式讀管道時:

(1)有讀程序,無寫程序:

管道內無資料時,立即返回

管道內資料不足,讀出所有資料

管道內資料充足,讀出期望資料

(2)有讀程序,有寫程序:

以阻塞方式寫管道時:

(1)有寫程序,無讀程序:

(2)有寫程序,有讀程序,且管道內有寫空間:

另外可以使用fcntl()函式使用o_ndelay或o_nonblock屬性,設定管道為非阻塞模式。

#include file * popen(const char *command , const char *type );

int pclose(file *stream);

作用:popen函式允許乙個程式將另外乙個程式作為新程序來啟動,並可以傳遞資料或者通過它接受資料。

其內部實現為呼叫 fork 產生乙個子程序,執行乙個 shell, 以執行命令來開啟乙個程序,這個程序必須由 pclose() 函式關閉

引數說明:

command: 是乙個指向以 null 結束的 shell 命令字串的指標。這行命令將被傳到 bin/sh 並使用 -c 標誌,shell 將執行這個命令。

type : 只能是讀或者寫中的一種。如果 type 是 「r」 則檔案指標連線到 command 的標準輸出;如果 type 是 「w」 則檔案指標連線到 command 的標準輸入。。

缺點:

使用popen的不好影響是,針對每個popen呼叫,不僅要啟動乙個被請求的程式,還要啟動乙個shell,即每個popen呼叫將多啟動兩個程序。

例項:

#include#include#includeint main() 

;

memset(buff,0,sizeof(buff));

fp=popen("ls -l","r");//將命令ls-l 通過管道讀到fp

fh=fopen("shell.c","w+");// 建立乙個可寫的檔案

fread(buff,1,127,fp);//將fp的資料流讀到buff中

fwrite(buff,1,127,fh);//將buff的資料寫入fh指向的檔案中

pclose(fp);

fclose(fh);

return 0;

}

執行結果:

[lol@localhost practice]$ ls

popen popen.c shell.c

[lol@localhost practice]$ cat shell.c

total 12

-rwxrwxr-x. 1 lol lol 5478 may 24 15:39 popen

-rw-rw-r--. 1 lol lol 473 may 24 15:39 popen.c

-rw-rw-r--. 1 lol lol [lol@localhost practice]$ vim popen.c

[lol@localhost practice]$

有名管道可以通過mknod 命令建立,也可以使用函式mkfifo()建立,可以使用在系統中任意兩個程序之間進行通訊,且建立的管道檔案儲存在硬碟上,不會隨著程序結束而消失。mknod使用如下:

root@wangmumu-virtual-machine:/home/wangmumu/桌面/shares/fifo# mknod fifo p

root@wangmumu-virtual-machine:/home/wangmumu/桌面/shares/fifo# ls -l

總用量 24

prw-r--r-- 1 root root 0 8月 26 00:30 fifo

-rwxr--r-- 1 nobody nogroup 872 8月 25 23:57 fifo_read.c

-rwxr--r-- 1 nobody nogroup 884 8月 25 23:52 fifo_write.c

-rwxr-xr-x 1 root root 7613 8月 25 23:57 read

-rwxr-xr-x 1 root root 7651 8月 25 23:52 write

mkfifo()函式宣告如下:

// from /usr/include/sys/stat.h

int mkfifo(char* path,mode_t mode);

函式的第乙個引數為有名管道檔案,函式呼叫時,必須不存在,執行成功返回0,失敗返回-1。

(1)如果沒有指定o_nonblock方式開啟時(預設情況),當程序以寫或讀的方式開啟管道檔案,必須有另乙個程序以相對應的讀或寫方式也開啟該檔案,否則該程序將阻塞在open()位置。

(2)如果指定o_nonblock方式開啟,則唯讀open將立即返回0,但是如果目前沒有讀程序開啟,而直接以寫方式開啟檔案,則open將返回-1,並將errno置為enxio,所以建議一般先以讀方式開啟有名管道。

(3)若兩個程序都已開啟,但中途某程序退出,則:

讀程序退出,返回sigpipe訊號

寫程序退出,讀程序將不再阻塞,直接返回 0

示例:

以下為有名管道**實現,寫程序不斷獲取終端輸入,並寫到有名管道上,讀程序阻塞讀取管道中資料,並將資料列印出來。

寫程序**實現:

#include #include #include #include #include #include #include #include #define fifo_name "fifo"

int main()

; if(access(fifo_name,f_ok) == -1)

}printf("mkfifo success,open o_wronly!\n");

fd = open(fifo_name,o_wronly);

if(fd < 0)

else

memset(buffer,0,sizeof(buffer));

sleep(1);}}

close(fd);

return 0;

}

讀程序**實現:

Unix 環境變數

linux 下處理環境變數常見的幾個操作 env 顯示當前所有的環境變數 set 顯示當前bash下使用者自定義的變數和環境變數 export 把自定義的變數轉換成環境變數 環境表 unix 下的每乙個程式都會有一張環境表,其實我們可以想象,main函式使如下這種形式 int main int ar...

UnixC( 五)之管道和環境變數

1.1 環境變數 1.1.1 概念理解 1.1.2 檢視當前程序的環境變數 例項 zenv.c include int main return 0 執行 gcc zenv.c o zenv zenv 執行得到的環境變數是 當前程序的環境變數,而不是bash程序的環境變數 1.1.3 int main...

Unix環境變數 執行緒基礎

標頭檔案 include 返回值 若相等則返回非0值,否則返回0值 作用 判斷兩個執行緒id是否相等 pthread t pthread self void 標頭檔案 include 返回值 呼叫執行緒自身的執行緒id intpthread create pthread t tidp,const p...