筆記三:程序間的通訊(管道)
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 只能在具有公共祖先的程序之間使用。乙個管道由乙個程序建立,然後該...