相關知識:
1、有名管道
一個可以在文件系統中長期存在的、具有路徑名的文件。用系統調用mknod( )建立。它克服無名管道使用上的局限性,可讓更多的進程也能利用管道進行通信。因而其它進程可以知道它的存在,並能利用路徑名來訪問該文件。對有名管道的訪問方式與訪問其他文件一樣,需先用open( )打開。
2、無名管道
一個臨時文件。利用pipe( )建立起來的無名文件(無路徑名)。只用該系統調用所返回的文件描述符來標識該文件,故只有調用pipe( )的進程及其子孫進程才能識別此文件描述符,才能利用該文件(管道)進行通信。當這些進程不再使用此管道時,核心收回其索引結點。
3、pipe文件的建立
分配磁盤和內存索引結點、為讀進程分配文件表項、為寫進程分配文件表項、分配用戶文件描述符
4、讀/寫進程互斥
內核為地址設置一個讀指針和一個寫指針,按先進先出順序讀、寫。
為使讀、寫進程互斥地訪問pipe文件,需使各進程互斥地訪問pipe文件索引結點中的直接地址項。因此,每次進程在訪問pipe文件前,都需檢查該索引文件是否已被上鎖。若是,進程便睡眠等待,否則,將其上鎖,進行讀/寫。操作結束后解鎖,並喚醒因該索引結點上鎖而睡眠的進程。
1、pipe( )
建立一無名管道。
系統調用格式
pipe(filedes)
參數定義
int pipe(filedes);
int filedes[2];
其中,filedes[1]是寫入端,filedes[0]是讀出端。
該函數使用頭文件如下:
#include <unistd.h>
#inlcude <signal.h>
#include <stdio.h>
2、read( )
系統調用格式
read(fd,buf,nbyte)
功能:從fd所指示的文件中讀出nbyte個字節的數據,並將它們送至由指針buf所指示的緩沖區中。如該文件被加鎖,等待,直到鎖打開為止。
參數定義
int read(fd,buf,nbyte);
int fd;
char *buf;
unsigned nbyte;
3、write( )
系統調用格式
read(fd,buf,nbyte)
功能:把nbyte 個字節的數據,從buf所指向的緩沖區寫到由fd所指向的文件中。如文件加鎖,暫停寫入,直至開鎖。
參數定義同read( )。
無名管道程序源碼:
#include <unistd.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> int pid1,pid2; int main() { int fd[2]; char outpipe[100],inpipe[100]; pipe(fd); /*創建一個管道*/ while ((pid1=fork()) == -1); if(pid1 == 0) { lockf(fd[1],1,0); sprintf(outpipe,"I am a child 1 "); /*把串放入數組outpipe中*/ write(fd[1],outpipe,50); /*向管道寫長為50字節的串*/ sleep(1); /*自我阻塞5秒*/ lockf(fd[1],0,0); exit(0); } else { sleep(1);//延時等待子進程1結束 while((pid2=fork()) == -1); if(pid2 == 0) { lockf(fd[1],1,0); /*互斥*/ sprintf(outpipe,"I am a child 2 "); write(fd[1],outpipe,50); sleep(1); lockf(fd[1],0,0); exit(0); } else { wait(0); /*同步*/ read(fd[0],inpipe,50); /*從管道中讀長為50字節的串*/ printf("%s\n",inpipe); wait(0); read(fd[0],inpipe,50); printf("%s\n",inpipe); exit(0); } } }
有名管道程序源碼:
#include <unistd.h> #include <stdio.h> #include <string.h> #include <fcntl.h> #include <stdlib.h> #include <signal.h> int pid1,pid2; int main() { char *filename = "fifo"; int res = mkfifo(filename,0666);//創建文件 if(res < 0) { perror("mkfifo error"); return -1; } int fd = open(filename,O_RDWR);//打開文件 if(fd < 0) { perror("open error"); return -2; } while((pid1=fork()) == -1);//創建子進程1 if(pid1 == 0) { char *str1 = "I am a child 1"; int len1 = write(fd,str1,strlen(str1)); } else { sleep(1);//等待子進程1結束 while((pid2=fork()) == -1); if(pid2 == 0) { char *str2 = " I am a child 2"; int len2 = write(fd,str2,strlen(str2)); } else { wait(0); wait(0); int len; char buf[128] = {0}; len = read(fd,buf,sizeof(buf) - 1); printf("%s\n",buf); } } close(fd); unlink(filename); }