原博客地址:http://blog.csdn.net/bv1315008634/article/details/52916849
1、管道通信的特点:
(1)管道是半双工的,先进先出的,它把一个进程的输出和另一个进程的输入连接在一起
(2)一个进程(写进程)在管道的尾部写入数据,另一个进程(读进程)从管道的头部读出数据
2、无名管道和有名管道分别适用的进程是什么?
无名管道用于父子进程之间的通信;有名管道用于运行同一个系统中的任意两个进程间的通信
3、无名管道和有名管道创建的步骤
无名管道:创建管道——读管道——写管道——关闭管道
有名管道:创建管道——删除管道——打开管道——关闭管道——读管道——写管道
管道用于不同进程间的通信,通常先创建一个管道,在通过fork函数创建一个子进程,该子进程会继承父进程所创建的管道
4、管道通信函数
Pipe
原型:int pipe(int filedes[2])
参数:新建的两个描述符由filedes数组返回。filedes[0]表示管道的读取端,filedes[1]表示管道的写入端
返回值:成功:0;出错:-1
头文件:#include<unistd.h>
实验代码:
#include <unistd.h> #include <sys/types.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> int main() { int pipe_fd[2]; pid_t pid; char buf_r[100]; char* p_wbuf; int r_num; memset(buf_r,0,sizeof(buf_r)); if(pipe(pipe_fd)<0) { printf("pipe create error\n"); return -1; } if((pid=fork())==0) { printf("\n"); close(pipe_fd[1]); sleep(2); if((r_num=read(pipe_fd[0],buf_r,100))>0) { printf( "%d numbers read from the pipe is %s\n",r_num,buf_r); } close(pipe_fd[0]); exit(0); } else if(pid>0) { close(pipe_fd[0]); if(write(pipe_fd[1],"Hello",5)!=-1) printf("parent write1 Hello!\n"); if(write(pipe_fd[1]," Pipe",5)!=-1) printf("parent write2 Pipe!\n"); close(pipe_fd[1]); sleep(3); waitpid(pid,NULL,0); exit(0); } return 0; }
如果实现无名管道双方向的读写是否可行?
#include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<string.h> int main() { int filedes[2]; pid_t pid; char buf[100]; int byte_read; memset(buf,0,sizeof(buf)); if(pipe(filedes)< 0) { printf("Fail to creat pipe!\n"); } if((pid = fork()) == 0) { close(filedes[1]); sleep(2); if((byte_read = read(filedes[0],buf,100))>0) { printf("%d bytes haved been read from the pipe is %s\n",byte_read,buf); } /* if(write(filedes[1],"hello",5) != -1) { printf("child has read hello\n"); } */ close(filedes[0]); exit(0); } else if(pid > 0) { close(filedes[0]); /* if((byte_read = read(filedes[0],buf,100))>0) { printf("%d bytes haved been read from the pipe is %s\n",byte_read,buf); } */ if((write(filedes[1],"world",5)) != -1) { printf("parent process has writen world\n"); } if((write(filedes[1],"peace",5)) != -1) { printf("parent process has writen peace\n"); } close(filedes[1]); sleep(3); waitpid(pid,NULL,0); exit(0); } return 0; }
实现验证:不可实现双向的读写,说明无名管道是一端读一端写的,是半双工的
有名管道的创建
mkfifo函数
函数的作用:创建一个有名管道
原型:int mkfifo(const char *filename,mode_t mode)
函数的参数:filename:有名管道的路径,名称
Mode:管道的方式
O_NONBLOCK:FIFO打开的时候会立刻返回,非阻塞
返回值:成功:0;出错:-1
实例(先读再写):写
#include <sys/types.h> #include <sys/stat.h> #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #define FIFO_SERVER "/tmp/myfifo" main(int argc,char** argv) { int fd; char w_buf[100]; int nwrite; fd=open(FIFO_SERVER,O_WRONLY|O_NONBLOCK,0); if(argc==1) { printf("Please send something\n"); exit(-1); } strcpy(w_buf,argv[1]); if((nwrite=write(fd,w_buf,100))==-1) { printf("The FIFO has not been read yet.Please try later\n"); } else printf("write %s to the FIFO\n",w_buf); }
读:
#include <sys/types.h> #include <sys/stat.h> #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #define FIFO "/tmp/myfifo" main(int argc,char** argv) { char buf_r[100]; int fd; int nread; if((mkfifo(FIFO,O_CREAT|O_EXCL)<0)&&(errno!=EEXIST)) printf("cannot create fifoserver\n"); printf("Preparing for reading bytes...\n"); memset(buf_r,0,sizeof(buf_r)); fd=open(FIFO,O_RDONLY|O_NONBLOCK,0); if(fd==-1) { perror("open"); exit(1); } while(1) { memset(buf_r,0,sizeof(buf_r)); if((nread=read(fd,buf_r,100))==-1) { if(errno==EAGAIN) printf("no data yet\n"); } printf("read %s from FIFO\n",buf_r); sleep(1); } pause(); unlink(FIFO); }