thread出來之後,就可以單純的使用共用的memory,在thread之間溝通是比較方便(當然有其他問體衍生出來)
由IPC學習,漸漸的感覺到,對於unix like的系統來說,幾乎啥都是被當作file
高階的pipe使用兩個函數
#include 〈stdio.h〉
FILE *popen(const char *command, const char *open_mode)
pclose(FILE *stream_to_close);
FILE *popen(const char *command, const char *open_mode)
pclose(FILE *stream_to_close);
比方說popen("uname -a","r"),可以看到popen回傳的是一個FILE指標,所以一個pipe也被當作了檔案來運作
高階pipe的運作方式是先建立一個shell然後把command執行類似execl的程序來取得資料,這樣一個運作方式其實還蠻消耗資源的
當然不是一定要透過類似command的模式執行,unix提供另外一種方式,直接套用低階的descriptor
#include 〈unistd.h〉
int pipe(int file_descriptor[2]);
int pipe(int file_descriptor[2]);
可以看到上面放入了兩個低階的file descriptor,可以將任何寫入file_descriptor[1]的資料透過file_descriptor[0]讀取,採用fifo的原理
回傳的value有可能是
EMFILE:已經超過單一process可用的file descriptor個數
ENFILE:已經超過系統可用的file descriptor個數
EFAULT:descriptor是錯的
這常用在fork後的process於parent/child process之間的溝通上
那如果跨越process呢?本身並沒有絕對的關連,那麼怎麼辦?我不知道unix是否有提供及他的模式可以讓process查詢其他process提供哪些介面的方式,所以他有一個named pipe,看到named就表示過去已經存在,也就是你程式在compile time已經決定名稱的pipe,這樣就可以知道如何存取pipe(以為已經有名字了),其實是透過
#include 〈sys/types.h〉
#include 〈sys/stat.h〉
int mkfifo(const char *filename,mode_t mode);
int mknod(const char *filename,mode_t mode|S_IFIFO,(dev_t) 0);
#include 〈sys/stat.h〉
int mkfifo(const char *filename,mode_t mode);
int mknod(const char *filename,mode_t mode|S_IFIFO,(dev_t) 0);
其中mknod在有些系統並不提供,其實這個函數就是建立了一個臨時的檔案,這樣一來就可以透過這個檔案然操作,有一點要注意的,可能mode會受到umask的影響,比方說umask為0022在乎叫函數的時候使用0777,ls指令出來的結果會是0755
以上的pipe方式可以看的出來unix like的系統的確把各種實體裝置、虛擬裝置都當成檔案,這樣的設計上當然有好有壞囉,好處是幾乎有統一的介面可以操作;壞處是這樣的特色可能在底層的運作上更麻煩,因為並不是每個裝置的特色都可以符合檔案的模式
沒有留言:
張貼留言