為什麼程序間要通訊?
1、 資料傳輸
2、 資源共享
3、 通知事件
4、 程序控制
程序間通訊方式:
管道通訊、
共享記憶體、
訊息佇列、
訊號通訊、
一、管道通訊
管道是單向的、先進先出的,它把乙個程序的輸出和另乙個程序的輸入連線在一起。乙個程序(寫程序)在管道尾部寫入資料,另乙個程序(讀程序)從管道的頭部讀出資料。
(1)popen
兩個程式之間傳遞資料的一種簡單方法是使用popen和pclose。
#include
file *popen(const
char *command, const
char *type);
int pclose(file *stream);
popen函式允許乙個程式將另乙個程式作為新程序來啟動,並可以傳遞資料給它或者通過它接收資料。command字串是要執行的程式名和相應的引數。type必須是」r」或」w」。
如果type是」r」,被調程式的輸出就可以被呼叫程式使用,呼叫程式利用popen函式返回的file *檔案流指標,可以讀取被調程式的輸出;如果type是」w」,呼叫程式就可以向被調程式傳送資料,而被調程式可以在自己的標準輸入上讀取這些資料。
pclose函式只在popen啟動的程序結束後才返回。如果呼叫pclose時它仍在執行,pclose將等待該程序的結束。
#include
#define size 1024*100
int main()
char buf[size] = ;
int ret = fread(buf, sizeof(char), size-1, fp);
// printf ("讀到的資料:\n %s\n", buf);
file *fp2 = popen("grep a.out", "w");
if (fp2 == null)
fwrite (buf, sizeof(char), ret, fp2);
printf ("寫入完成\n");
pclose (fp);
pclose (fp2);
return
0;}
(2)管道
管道包括無名管道和有名管道兩種,前者用於父程序和子程序間的通訊,後者可用於執行於同一系統中的任意兩個程序間的通訊。
①無名管道
無名管道由pipe()函式建立:
int
pipe(int filedis[2]);
當乙個管道建立時,它會建立兩個檔案描述符:
filedis[0]用於讀管道,filedis[1]用於寫管道。
管道用於不同程序間通訊。通常先建立乙個管道,在通過fork函式建立乙個子程序,該子程序會繼承父程序所建立的管道描述符。
注意事項:
必須在系統呼叫fork()前呼叫pipe(),否則子程序將不會繼承檔案描述符。
注意:如果管道所有的讀端都被關閉,繼續寫資料系統預設的操作是使程式退出
父子程序通過管道進行通訊
#include
#include
#include
#include
#define size 1024
// 子程序通過管道從父程序接收資料
void child_do(int *fd)
buf[ret] = '\0';
printf ("子程序讀到 %d 位元組資料: %s\n", ret, buf);
}// 關閉讀端
close (fd[0]);
}// 父程序通過管道向子程序傳送資料
void father_do(int *fd)
// 關閉寫端
close (fd[1]);
}int main()
// 建立子程序
pid_t pid = fork();
switch (pid)
return
0;}
#include
#include
int mkfifo(const
char *pathname, mode_t mode);
pathname: fifo檔名
mode:屬性(同檔案操作)
一旦建立了乙個fifo,就可用open開啟它,一般的檔案訪問函式(close、read、write等)都可用於fifo。
當開啟fifo時,非阻塞標識(o_nonblock)將對以後的讀寫產生影響:
1、沒有使用o_nonblock:訪問要求無法滿足時程序將阻塞。如果試圖讀取空的fifo,將導致程序阻塞。
2、使用o_nonblock:訪問要求無法滿足時不阻塞,立刻出錯返回。errno是enxio。
#include
#include
#include
#include
#include
#include
#define size 1024
int main()
//寫端
char buf[size];
while (1)
//讀端
char buf[size];
while (1)
return
0;}
二、共享記憶體
共享記憶體實現分兩個步驟:
1、建立共享記憶體,使用shmget函式
2、對映共享記憶體,將這段建立的共享記憶體對映到具體的程序空間去,使用shmat函式。
①建立:
int shmget(key_t key, int
size, int shm***)
key:
1、0/ipc_private:當key的取值為ipc_private,則函式shmget()將建立一塊新的共享記憶體;如果key取值為0,而引數shm***中又設定ipc_private這個標誌,則同樣會建立一塊新的共享記憶體。
2、大於0的32位整數:視引數shm***來確定操作。
size:
1、大於0的整數:新建的共享記憶體大小,以位元組為單位0:
2、只獲取共享記憶體時指定為0
shm***:模式標誌引數,使用時需要與ipc物件訪問許可權(如0600)進行|運算來確定共享記憶體的訪問許可權
1、0:取共享記憶體識別符號,若不存在則函式會報錯
2、ipc_creat:當shm***&ipc_creat為真時,如果核心中不存在鍵值與key相等的共享記憶體,則新建乙個共享記憶體;如果存在這樣的共享記憶體,返回此共享記憶體的識別符號
3、ipc_creat|ipc_excl:如果核心中不存在鍵值 與key相等的共享記憶體,則新建乙個共享記憶體;如果存在這樣的共享記憶體則報錯
返回值:如果成功,返回共享記憶體識別符號;如果失敗,返回-1。
②對映:
void* shmat(int shmid, char *shmaddr, int flag)
引數:
第乙個引數,shm_id是由shmget函式返回的共享記憶體標識。
第二個引數,shm_addr指定共享記憶體連線到當前程序中的位址位置,通常為空,表示讓系統來選擇共享記憶體的位址。
第三個引數,shm_***是一組標誌位,通常為0。
int shmdt(char *shmaddr);
引數shmaddr是shmat函式返回的位址指標,呼叫成功時返回0,失敗時返回-1.
該函式用於將共享記憶體從當前程序中分離。注意,將共享記憶體分離並不是刪除它,只是使該共享記憶體對當前程序不再可用。
④共享記憶體控制
int
shmctl(int shm_id, int command, struct shmid_ds *buf);
第乙個引數,shm_id是shmget函式返回的共享記憶體識別符號。
第二個引數,command是要採取的操作,它可以取下面的三個值 :
ipc_stat:把shmid_ds結構中的資料設定為共享記憶體的當前關聯值,即用共享記憶體的當前關聯值覆蓋shmid_ds的值。
ipc_set:如果程序有足夠的許可權,就把共享記憶體的當前關聯值設定為shmid_ds結構中給出的值
ipc_rmid:刪除共享記憶體段
第三個引數,buf是乙個結構指標,它指向共享記憶體模式和訪問許可權的結構。
shmid_ds結構至少包括以下成員:
struct shmid_ds
;
建立共享記憶體
#include
#include
#include
#include
#include
typedef
struct _shm
shm;
int main()
// 2、將共享記憶體對映到當前的程序空間
shm* pshm = (shm*)shmat(shmid, null, 0);
if(pshm == (shm*)-1)
strcpy (pshm->msg, "hello");
// 解除共享記憶體對映,解除是值當前程序不能再使用共享記憶體
shmdt(pshm);
shmctl(shmid, ipc_rmid, null);
return
0;}
程序間通訊(一)
半雙工管道 fifo 全雙工管道 命名全雙工管道 訊息佇列 訊號量 共享記憶體 套接字 多機其它為單機 管道 包括無名管道 命名管道 訊息佇列 訊號量共享儲存 scoket streams 等。其中,scoket和stream支援不同主機上的兩個程序ipc。一 管道 管道,通常指無名管道,是unix...
程序間通訊 一)
測試 例子 從鍵盤讀取資料,寫入管道,讀取管道,寫到螢幕 include include include include intmain void memset buf,0x00 sizeof buf read from pipeif len read fds 0 buf,100 1 write t...
程序間通訊(一)
1.程序是一種單執行流,每個程序都私有 獨佔乙份系統資源,段共享但是資料段不共享,子程序寫資料時會觸發寫實拷貝,從而保證資源獨享。總的來說 每個程序各自有不同的使用者位址空間,任何乙個程序的全域性變數在另乙個程序中都看不到 所以程序之間要交換資料必須通過核心,在核心中開闢一塊緩衝區,程序1把資料從使...