1、管道数组
管道:管道是一种半双工的通讯方式,数据只能单方向流动,并且只能在具备亲缘关系的进程间使用,由于管道服务器
传递数据的单向性,管道又称为半双工管道。进程的亲缘关系一般是指父子进程关系。函数
管道的特色决定了其使用的局限性:ui
创建两个管道。spa
关系的进程不能使用管道。code
管道的建立:orm
Linux下建立管道能够经过函数pipe来完成。该函数若是调用成功则返回0,而且数组中将包含两个新的文件描述符;blog
若是有错误发生,返回-1,该函数返回两个文件描述符:pipefd[0]和pipefd[1]。前者打开来读,后者打开来写。该函进程
数的原型为:ip
#include <fcntl.h>
#include <unistd.h>
int pipe(int pipefd[2]);
1. 下面是经过创建管道和建立父子进程间的通讯:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <fcntl.h> #include <string.h> #include <sys/wait.h> int main() { int fd[2]; pid_t pid; int ret; ret= pipe(fd); if(ret== -1) { perror("pipe.\n"); exit(1); } pid= fork(); if(pid== -1) { perror("fork.\n"); exit(1); } else if(pid== 0) { char buff[256]; close(fd[1]); read(fd[0],buff,256); printf("Form parent say: %s\n",buff); close(fd[0]); } else { char *say= "Hello Linux."; close(fd[0]); write(fd[1],say,strlen(say)+ 1); close(fd[1]); int status; wait(&status); } return 0; }
这是父子进程间利用管道进行通讯的一个例子。
2. 下面是经过创建两个管道来实现父子进程间全双工通讯:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <fcntl.h> #include <sys/wait.h> int main() { char *parent_talk[]= {"Hello","Can you tell me what time is it?","Ok,I must go,Bye",NULL}; char *child_talk[]= {"Hi","No problem","See you,Bye",NULL}; int fd1[2],fd2[2]; pid_t pid; int ret; ret= pipe(fd1); if(ret== -1) { perror("pipe1.\n"); exit(1); } ret= pipe(fd2); if(ret== -1) { perror("pipe2.\n"); exit(1); } pid= fork(); if(pid== -1) { perror("fork.\n"); exit(1); } else if(pid== 0) { char buff[256]; close(fd1[1]); close(fd2[0]); int i= 0; char *talk= child_talk[i]; while(talk!= NULL) { read(fd1[0],buff,256); printf("Parent say: %s\n",buff); write(fd2[1],talk,strlen(talk)+ 1); talk= child_talk[++i]; } close(fd1[0]); close(fd2[1]); } else { char buff[256]; close(fd1[0]); close(fd2[1]); int i= 0; char *talk= parent_talk[i]; while(talk!= NULL) { write(fd1[1],talk,strlen(talk)+ 1); read(fd2[0],buff,256); printf("Child say: %s\n",buff); talk= parent_talk[++i]; } close(fd1[1]); close(fd2[0]); int status; wait(&status); } return 0; }
这是经过创建两个管道来实现父子进程间全双工通讯的例子。
2、有名管道
管道的有一个不足之处是没有名字,所以,只能用于具备亲缘关系的进程间通讯,在有名管道(FIFO)提出后,该
限制获得了克服。FIFO不一样于管道之处在于它提供一个路径名与之关联,以FIFO的文件形式存储于文件系统中。有名
管道是一个设备文件,所以,即便进程与建立FIFO的进程不存在亲缘关系,只要能够访问该路径,就可以经过FIFO相
互通讯。须要注意的是,FIFO老是按照先进先出的原则工做,第一个被写入的数据将首先从管道中读出。
有名管道的建立:
Linux下有两种方式建立有名管道。一是在Shell下交互地创建一个有名管道,二是在程序中使用系统函数创建有
名管道。Shell方式下可以使用mkfifo或mknod命令。建立有名管道的系统函数有两个:mkfifo和mknod。两个函数均定义
在头文件sys/stat.h中,函数的原型为:
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname,mode_t mode);
int mknod(const char *pathname,mode_t mode,dev_t dev);
函数mkfifo参数中pathname为建立的有名管道的全路径名;mode为建立的有名管道的模式,指明其存取权限;函
数mknod参数中pathname为建立的有名管道的全路径名;mode为建立的有名管道的模式,指明其存取权限;dev为设
备值,该值取决于文件建立的种类,它只在建立设备文件时才会用到。这两个函数调用成功都返回0,失败都返回-1。
下面是使用有名管道创建一个客户端/服务器的例子:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <sys/wait.h> #define BUFFER_SIZE 256 const char *write_fifo= "write_fifo"; const char *read_fifo= "read_fifo"; int main() { if(access(write_fifo,F_OK)) { int ret= mkfifo(write_fifo,0755); if(ret== -1) { perror("mkfifo"); exit(1); } } int write_fd= open(write_fifo,O_WRONLY); if(write_fd== -1) { perror("open write_fifo."); exit(1); } int read_fd; while(1) { read_fd= open(read_fifo,O_RDONLY); if(read_fd== -1) { sleep(1); continue; } break; } char sendbuf[BUFFER_SIZE]; char recvbuf[BUFFER_SIZE]; while(1) { printf("Ser:"); scanf("%s",sendbuf); if(strcmp(sendbuf,"quit")== 0) { unlink(write_fifo); break; } write(write_fd,sendbuf,strlen(sendbuf)+ 1); read(read_fd,recvbuf,BUFFER_SIZE); printf("Cli:%s\n",recvbuf); } close(write_fd); close(read_fd); return 0; }
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <sys/wait.h> #define BUFFER_SIZE 256 const char *write_fifo= "write_fifo"; const char *read_fifo= "read_fifo"; int main() { int read_fd= open(write_fifo,O_RDONLY); if(read_fd== -1) { perror("open write_fifio."); exit(1); } if(access(read_fifo,F_OK)) { int ret= mkfifo(read_fifo,0755); if(ret== -1) { perror("mkfifo"); exit(1); } } int write_fd= open(read_fifo,O_WRONLY); if(write_fd== -1) { perror("open read_fifo."); exit(1); } char sendbuf[BUFFER_SIZE]; char recvbuf[BUFFER_SIZE]; while(1) { read(read_fd,recvbuf,BUFFER_SIZE); printf("Ser:%s\n",recvbuf); printf("Cli:"); scanf("%s",sendbuf); if(strcmp(sendbuf,"quit")== 0) { unlink(read_fifo); break; } write(write_fd,sendbuf,strlen(sendbuf)+ 1); } close(write_fd); close(read_fd); return 0; }