IPC -interprocesscommunication就是指進程間的通信。一個程序往往要有很多進程協作來完成。那麼各個進程間的通信就很重要了,這是在 Unix/Linux下經常遇到的問題之一,它的主要目的就是要多個進程可以相互訪問數據。
只有一個進程的程序,IPC沒有什麼意義。
這次主要學習管道通信。管道是最基本的,最簡單的IPC 方式。
管道在系統中並沒有一個實際的名字,它只存在於內存中,一旦程序運行結束,管道也就消失了。
創建管道:
int pipe(int fds【2】);
fd【2】 是一個整型數組,包含兩個元素,分別爲fd【0】和fd【1】,fd【0】表示管道的讀端,fd【1】表示管道的寫入端。管道兩端的功能是固定的,只能從fd【0】讀數據,只能從fd【1】寫數據。
該函數創建管道成功,返回0;否則返回-1.
管道通信主要用於具有共同祖先的進程間通信,及父子進程或兄弟進程間通信。
讀管道進行讀寫操作可以使用read()和write()。當對一個讀端已經關閉的管道寫入數據會產生SIGPIPE信號,表明管道讀端已經關閉。而write()操作會返回-1,errno的值爲EPIPE,對於SIGPIPE信號可以進行捕捉處理。
對一個管道進行讀操作,read()函數返回0有兩種可能,一種是管道中無數據並且管道寫端已經關閉,另一種就是,管道中無數據,但是管道寫入端依然存在,這兩種情況要分別處理。
下面演示一個簡單的父子進程間通信的例子。
我們可以先創建一個管道,然後fork()一個子進程。但是之後子進程會繼承父進程的數據段,也就是父子進程對創建的管道都具有操作權,父子進程間通信數據的流向要看我們如何維護剛創建的管道。
我們要達到從父進程向子進程傳遞消息的目的。我們可以把父進程中管道的讀端fd[0]關閉,只留寫入端 fd[1],而對於子進程我們可以把管道的寫入端fd[1]關閉,只保留讀出端fd[0]
下面是一段簡單的測試從父進程向子進程發送消息的代碼:
1#include<stdio.h>
2 #include<stdlib.h>
3 #include<unistd.h>
4 #include<limits.h>
5 #include<sys/types.h>
6 #include<fcntl.h>
7 #define BUFFERSIZE PIPE_BUF
8
9 int main()
10 {
11 pid_t pid;
12 int fd[2];
13 char buffer[BUFFERSIZE];
14 ssize_t len;
15
16 if((pipe(fd))<0)
17 {
18 perror("創建管道失敗!");
19 exit(1);
20 }
21
22 pid = fork();
23 if(pid<0)
24 {
25 perror("創建子進程失敗");
26 exit(1);
27 }else if(pid == 0)
28 {
29 close(fd[1]);
30 len = read(fd[0],buffer,BUFFERSIZE);
31 if(len < 0)
32 {
33 perror("讀取數據失敗");
34 exit(1);
35 }
36 else{
37 write(STDOUT_FILENO,buffer,len);
38 }
39 }else{
40 close(fd[0]);
41 write(fd[2],"this is a test to child\n",25);
42 exit(0);
43 }
44 return 0;
45 }
46
47
1,17 頂端
41,12-18 66%