筆記三 程序間的通訊(管道)

2021-07-27 12:20:10 字數 4852 閱讀 3902

筆記三:程序間的通訊(管道)

1)核心空間的物件是不存在的;

2)程序間的通訊每一種通訊方式都是基於檔案io思想;open函式,read函式,write函式,close函式等等;

3)通過open函式開啟或者建立乙個檔案(只能建立普通檔案),當我們開啟乙個檔案,就會在核心空間開闢乙個快取,通過write往核心寫,以及使用者空間從核心read;

物件不一樣意味著通訊方式不一樣

2.有哪幾種通訊方式?

管道通訊:

無名管道、有名管道(檔案系統中有名)

訊號通訊:

訊號(通知)通訊包括:訊號的傳送、訊號的接收和訊號的處理。

ipc(inter-process communication)通訊:

共享記憶體、訊息佇列和訊號燈。

以上是單機模式下的程序通訊(只有乙個linux核心)

socket通訊:

存在於乙個網路中兩個程序之間的通訊(兩個linux核心)。

管道:無名管道和有名管道(管道其實就是乙個佇列)只能在兩端就行插入和刪除出隊:讀   入隊:寫

無名管道:

在檔案系統中無檔案節點或者說無檔名(特殊的檔案);

有名管道:

在檔案系統中有檔案節點或者說有檔名(特殊的檔案);

二:無名管道

通訊原理:

管道檔案是乙個特殊的檔案,是由佇列來實現的。

無名管道通過pipe函式建立特殊檔案(管道)返回乙個檔案描敘符

在檔案io中建立乙個檔案或開啟乙個檔案是由open函式來實現的,它不能建立管道檔案。只能用pipe函式來建立管道。

函式形式:int pipe(int fd[2])

功能:建立管道,為系統呼叫:unistd.h

引數:就是得到的檔案描述符。可見有兩個檔案描述符:fd[0]和fd[1],管道有乙個讀端fd[0]用來讀和乙個寫端fd[1]用來寫,這個規定不能變。

返回值:成功是0,出錯是-1;

例1:pipe函式使用

/*無名管道*/

#include "unistd.h"

#include "string.h"

#include "stdio.h"

int main()

; ret=pipe(fd);//建立管道

if(ret < 0)

printf("%d,%d\n",fd[0],fd[1]);//fd[0] read fd[1] write

write(fd[1],buf,sizeof(buf));//往管道中寫

read(fd[0],readbuf,128);

printf("readbuf=%s",readbuf);

memset(readbuf,0,128);//清空陣列

read(fd[0],readbuf,128);//從管道中讀取

printf("second read :readbuf=%s",readbuf);

close(fd[0]);

close(fd[1]);

return 0;

}

注意:

管道中的東西,讀完了就刪除了;佇列

如果管道中沒有東西可讀,則會讀阻塞。

例2:驗證讀阻塞。

讀取完以後如果在讀取程序將處於阻塞狀態

例3:驗證寫阻塞:可以計算出核心開闢的管道有多大。5456 處於不阻塞 5457處於阻塞狀態

/*無名管道*/

#include "unistd.h"

#include "string.h"

#include "stdio.h"

int main()

; ret=pipe(fd);//建立管道

if(ret < 0)

printf("%d,%d\n",fd[0],fd[1]);//fd[0]:read fd[1]:write

while(i < 5500)

/*總共寫5500次(hello linux),如果阻塞已經超過範圍,那麼下面一句話將不會列印出來*/

printf("write pipe end\n");

close(fd[0]);

close(fd[1]);

return 0;

}

例4:實現程序通訊

通過管道實現使用者間的程序通訊(實現a與b通訊,要對同乙個管道進行通訊)通過fork函式把父程序都進行了拷貝,除了pid號

/*通過pipe管道實現兩個程序間的通訊,如果沒有管道程序是無法在使用者空間進行通訊的*/

#include "unistd.h"

#include "stdio.h"

#include "stdlib.h"

int main()

}while(1);

}if(pid > 0)

flag =1 ;

write(fd[1],&flag,1);

while(1);

}return 0;

}

無名管道的缺點:只能實現父子程序(有親緣關係程序)之間的通訊,正由於這無名管道的缺點,對無名管道進行改進:有名管道。

所謂的有名,即檔案系統中存在這個一樣檔案節點,每乙個檔案節點都有乙個inode號

而且這是乙個特殊的檔案型別:p管道型別。1.

建立這個檔案節點,不可以通過open 函式,open 函式只能建立普通檔案,不能建立特殊檔案(管道-mkfifo,套接字-socket,字元裝置檔案-mknod,塊裝置檔案-mknod,符號鏈結檔案-ln –s,目錄檔案mkdir) 2.

管道檔案只有inode號,不佔磁碟塊空間,和套接字、字元裝置檔案、塊裝置檔案一樣。普通檔案和符號鏈結檔案及目錄檔案,不僅有inode號,還佔磁碟塊空間。

3.  mkfifo   用來建立管道檔案的節點,沒有在核心中建立管道。

只有通過open 函式開啟這個檔案時才會在核心空間建立管道。

有名管道(由於無名管道只能實現父子程序或有情緣關係程序的通訊,但是往往我們的程式(實際應用)都是無親緣關係,所以就衍生了有名管道)

普通檔案          ------------>    『_』      通過open函式建立

目錄檔案          ------------>   'd'       通過mkdir函式建立

鏈結檔案(主要是指軟鏈結)----------->     『l』   ln -s   選項建立

管道檔案      --------------->        通過mkfifo或者pipe系統呼叫函式建立

三.有名管道

mkfifo(只是生成了乙個檔案,並沒有在核心生成乙個管道,當通過open函式開啟這個節點時,會在核心空間生成乙個管道(快取))

函式形式:int mkfifo(const char *filename,mode_t mode);

功能:建立管道檔案

引數:管道檔案檔名,許可權,建立的檔案許可權仍然和umask有關係。

返回值:建立成功返回0,建立失敗返回-1。

例1:mkfifo的用法。

#include "unistd.h"

#include "stdio.h"

int main()

return 0;

}

例子:通過管道實現無情緣程序間的通訊

/*mkfifo建立管道(mkfifo.c)

*/

#include "stdio.h"

#include "unistd.h"

int main()

fd1 = mkfifo("./b.c",0777);

if(fd1 < 0)

return 0;

}

/*read端(read.c)*/

#include "unistd.h"

#include "fcntl.h"

#include "stdio.h"

#include "stdlib.h"

#include "string.h"

int main()

,readbuf[128] = ;

pid = fork();

if(pid < 0)

if(pid > 0)

}

if(pid == 0)

}

return 0;

}

/*write端(write.c)*/

#include "unistd.h"

#include "fcntl.h"

#include "stdio.h"

#include "stdlib.h"

#include "string.h"

int main()

,readbuf[128] = ;

pid = fork();

if(pid < 0)

if(pid > 0)

}

if(pid == 0)

}

return 0;

}

程序間通訊 管道

include int pipe int fd 2 返回值 若成功,返回0,若出錯,返回 1經由引數fd返回兩個檔案描述符 fd 0 為讀而開啟,fd 1 為寫而開啟。fd 1 的輸出是fd 0 的輸入。else if pid 0 子程序 else else if pid 0 父程序 printf ...

程序間通訊 管道

原文 程序間通訊 管道 管道簡介 常說的管道都是匿名半雙工管道,匿名半雙工管道在系統中是沒有實名的,並不可以在檔案系統中以任何方式看到該管道。它只是程序的一種資源,會隨著程序的結束而被系統清除。管道通訊是在unix系統中應用比較頻繁的一種方式,例如使用grep查詢 ls grep ipc 顧名思義,...

程序間通訊 管道

程序間通訊,又稱為ipc,包含以下型別 半雙工管道fifo 全雙工管道 訊息佇列 訊號 訊號量共享記憶體 套接字socket streams。一,管道是unix系統ipc的最古老形式,他具有兩種侷限性 1 資料只能在乙個方向上流動 2 只能在具有公共祖先的程序之間使用。乙個管道由乙個程序建立,然後該...