linux系统中的进程通信(管道和有名管道)

来源:互联网 发布:java版本 编辑:程序博客网 时间:2024/05/21 22:38

进程通信:多个进程需要协调工作,需要进行数据的交换。

管道:是unix中进程通信的一种方式,管道的一端连接着输入另一段连接这数据的输出。

管道(无名管道):用于父子进程之间的通信。

有名管道:由于不同进程之间的通信。


匿名管道:

#include <unistd.h>int pipe(int fdes[2]) /*创建匿名管道*/
fdes:管道的输入、输出端的描述字。

成功时返回 0,失败时返回 -1

#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <string.h>const int BUFFMAX = 100; int main(){pid_t pid;int n,mypipe[2];char buffer[BUFFMAX + 1],*some = "hello world!";if(pipe(mypipe))    /*创建管道*/{fprintf(stderr,"faile!\n");exit(1);}if((pid = fork()) < 0) /*创建子进程*/{fprintf(stderr,"faile!\n");exit(1);}if(pid == 0) /*如果是子进程*/{close(mypipe[1]);   /*关闭子进程管道的输出端*/n = read(mypipe[0],buffer,BUFFMAX); /*从管道中读取数据*/fprintf(stdout,"Pid %d Read %d %s\n",getpid(),n,buffer);}else{close(mypipe[0]); /*关闭父进程管道的输入端*/n = write(mypipe[1],some,strlen(some)); /*向管道写入数据*/                fprintf(stdout,"Pid %d Write %d %s\n",getpid(),n,some);}exit(0);}

一般通过fork创建子进程是为了调用exec( )系列函数运行新的程序,如果调用exec( )则子进程从父进程继承的文件描述已经被新的程序代替,在调用exec( )函数之前可以先把管道的输入端重定向到标准输入端,从而是新的程序能过通过管道和父进程通信。重定向一般使用dup2( old,new)函数实现,如果描述字new打开则先关闭,再用new代替old,这个函数的操作是原子。

#include <stdlib.h>#include <stdio.h>#include <unistd.h>#include <string.h>const int Max = 100;int main(){int fd[2];pid_t pid;char buffer[Max];if(pipe(fd))  /*创建管道*/{fprintf(stderr,"make falie!\n");exit(1);}if((pid = fork()) < 0) /*创建子进程*/{fprintf(stderr,"pid faile!\n");exit(1);}if(pid == 0)  /*如果是子进程*/{close(fd[1]); /*关闭子进程管道的输出端*/dup2(fd[0],0); /*把子进程的输入端重定向到标准输入端*/close(fd[0]);  /*关闭不需要的描述字*/if(execl("/bin/cat","cat",NULL) < 0)  /*调用execl()创建新的程序*/{fprintf(stderr,"make falie!\n");exit(1);}}else  /*如果是子进程*/{close(fd[0]); /*关闭父进程管道的标准输入*/fprintf(stdout,"Plase input line date!\n");dup2(fd[1],1); /*为了使用pets函数,把父进程管道出重定向到标准输出*/close(fd[1]);  /*关闭不用的描述字*/while(gets(buffer) != NULL) puts(buffer);}exit(0);}

有名管道(FIFO)

#include <sys/types.h>

#include <sys/stat.h>int mkfifo (const char *path,mode_t mode); /*创建有名管道*/
path:有名管道的路径级名字。

mode:有名管道的文件权限。

失败返回0

创建管道,并读取内容,如果还没有向管道写入内容,将阻塞等待。

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#define FIFO_FILE "fifo_file" /*有名管道的名称*/#define Max 5int main(){int fifo,fd;int n;        char buff[Max]; if(access(FIFO_FILE,F_OK) < 0) /*测试文件是否存在*/{if(mkfifo(FIFO_FILE,0666) < 0) /*创建管道*/{ fprintf(stderr,"mkdir falie!\n"); exit(1);}}if((fd = open(FIFO_FILE,O_RDONLY)) < 0) /*打开文件*/{fprintf(stderr,"Open falie!\n");exit(1);}printf("%d Open %s\n",getpid(),FIFO_FILE);while((n = read(fd,buff,Max)) > 0) /*读取管道内容*/{fprintf(stdout,"%d read %s\n",getpid(),buff);}close(fd); /*关闭文件*/fprintf(stdout,"%d over\n",getpid());exit(0);}

打开文件向管道写入数据,当管道内容还没有读取时将阻塞,等待读取完毕在写入。

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <errno.h>#define FIFO_FILE "fifo_file"#define Max 100int main(){int fifo,fd;int n;        char buff[Max + 1] = "hello fifo"; if((fd = open(FIFO_FILE,O_WRONLY)) < 0) /*打开文件*/{fprintf(stderr,"fifo1 Open falie!\n");exit(1);}printf("%d Open %s\n",getpid(),FIFO_FILE);n = write(fd,buff,strlen(buff)); /*向管道内写入文件*/fprintf(stdout,"%d write %d\n",getpid(),n);close(fd); /*关闭文件*/fprintf(stdout,"%d over\n",getpid());exit(0);}







0 0