LINUX_C编程实战-第十章《进程间通信》-管道
来源:互联网 发布:五金行业erp软件报价 编辑:程序博客网 时间:2024/06/04 19:02
一、进程间的通信(IPC)-管道
管道分为无名管道(pipe),有名管道(FIFO)二种;
区别:无名管道是存在于内存的特殊文件,而有名管道是一个存在硬盘上的文件
无名管道的概念:管道是由内核管理的一个缓冲区,相当于放入内存的一个纸条。管道的一端连接一个进程的输出,这个进程会向管道中放入信息。管道的另一端连接一个进程的输入,这个进程取出被放入管道的信息。当管道中没有信息的话,从管道中读取的进程会等待,直到另一端的进程放入信息。当管道被放满信息的时候,尝试放入信息的进程会等待,直到另一端的进程取出信息。当两个进程都终结的时候,管道也自动消失
无名管道特点:1、半双工(单向通信)机制,数据只能有一个进程流入下一个进程(一个写管道,一个读管道);全双工通信需要创建两个管道;
2、数据只能在具有血缘关系的进程间通信;
3、管道没有名字,缓冲区大小一定(被分配一个页面作为缓冲区),是一种特殊的文件—PIPE_BUF;
无名管道的创建与打开:定义头文件 #include<unistd.h>
int pipe(int fd[2]); 成功返回0,数组中包含两个文件描述符,失败返回-1;
fd[0](管道读端) & fd[1](管道写端)用于描述管道的两端,读端只能读,写端只能写;可以用操作I/O文件的方式操作管道;
无名管道的读写:读端在读取数据时应该及时关闭不需要的管道的另一端(写端);写端亦如此
ps:必须再fork之前调用pipe函数创建管道,否则子进程无法继承管道的描述符
代码功能如下:主进程通过命令行向管道写入数据,子进程从标准输入里面读出该参数;将读端重定向到标准输入端
/* pipe.c文件*/#include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>#include<sys/types.h>#include<sys/stat.h>int main( int argc,char **argv){pid_t pid;int fd[2];int stat_val;if(pipe(fd)){printf("creat pipe failed\n");exit(1);}pid = fork();switch(pid){case 0:sleep(5);close(fd[1]);close(0);dup(fd[0]);//dup2(fd[0],0);execve("ctrlprocess",(void *)argv,NULL);exit(0);case -1:printf("fork failed\n");exit(0);default:close(fd[0]);write(fd[1],argv[1],strlen(argv[1]));close(fd[1]);wait(&stat_val);break;}return 0;}
可执行的代码:
/*ctrlprocess.c*/#include<string.h>#include<unistd.h>#include<sys/types.h>#include<sys/stat.h>#include<stdlib.h>#include<stdio.h>int main(int argc,char **argv){printf("I am here\n");char message[100];int n;while(1){n=read(0,message,90);printf("n= %d\n",n);if(n>0){printf("message= %s\n",message);}exit(0);}}程序执行如下:
有名管道(named pipe 或pipe)
特点:可以在非亲属关系中进行通信;以FIFO的文件形式存在文件系统中,是一个设备文件,相当于创建了一个文件,只要具有读写权限就可以访问
创建的方式二种:第一种,shell命令,mknod(mkfifo) 路径名>
第二种,系统函数:int mkfifo(const char *pathname,mode_t mode);//S_IFFO | 0666,表明文件存取权限
int mknod(const char *pathname,mode_t mode,dev_t dev);
成功返回0,失败返回-1;
注意:使用FIFO时要先使用open()函数将其打开;调用open打开有名管道的进程会阻塞,但如果以O_RDWR打开,一定不会阻塞;以O_RDONLY打开,则调用open的进程将会被阻塞直到有写方打开有名管道;以O_WRONLY打开,则调用open的进程也会被阻塞直到有读方打开有名管道;
/*writepipe.c*/#include<stdio.h>#include<stdlib.h>#include<sys/stat.h>#include<sys/types.h>#include<fcntl.h>#include<unistd.h>#define NAMEDPIPE "/home/czg/file/pipe"int main(char argc,char *argv[]){int fd,n;if(argc < 2)printf("input data\n");/* 非堵塞,只读的形式打开文件*/fd = open(NAMEDPIPE,O_WRONLY );if(fd<0){perror("open failed");}printf("fd = %d\n",fd);if(fd < 0)printf("open failed\n");n=write(fd,argv[1],3);printf("n=%d\n",n);close(fd);return 0;}
/* readpipe.c*/#include<stdio.h>#include<stdlib.h>#include<sys/stat.h>#include<sys/types.h>#include<fcntl.h>#include<unistd.h>#include<string.h>#include<unistd.h>#define NAMEDPIPE "/home/czg/file/pipe"int main(int argc,char **argv){int fd,n;char buf[200];memset(buf,0,sizeof(buf));/* 确认管道文件是否存在,有则删除*/if(access(NAMEDPIPE,F_OK)==0){printf("into access\n");execlp("rm","-f",NAMEDPIPE,NULL);}/* 创建管道,使其克读写执行*/if(mkfifo(NAMEDPIPE,0777) != 0){printf("mkfifo error\n");}/* 只读方式open管道时,进程被阻塞,至到有写方可打开管道,亦可加O_NONBLOCK(无堵塞)*/fd = open(NAMEDPIPE,O_RDONLY );printf("fd = %d\n",fd);sleep(5);while(1){memset(buf,0,sizeof(buf));n=read(fd,buf,2);if(n==-1)perror("read error");else if(n==0)printf("no data\n");else{printf("get data:%s\nn=%d\n",buf,n);sleep(2);}}close(fd);return 0;}
代码结果:
- LINUX_C编程实战-第十章《进程间通信》-管道
- LINUX_C编程实战—第十章《进程间的通信》-信号量
- LINUX_C编程实战—第十章《进程间的通信》-消息队列
- LINUX_C编程实战-《进程间的通信》-共享内存
- 进程间通信编程--管道
- 进程间通信编程--管道
- 进程间通信编程(2) - 无名管道
- 进程间通信编程(3) - 有名管道
- Linux编程:进程间通信--管道
- UNIX环境高级编程学习之第十五章进程间通信 - 通过有名管道(命名管道)实现进程间通信
- Unix网络编程--进程间通信--管道通信
- 进程间管道通信
- 进程间通信: 管道
- 进程间通信--管道
- 进程间通信----管道
- 进程间通信--管道
- 进程间通信--管道
- 进程间通信----管道
- 为了让手表更好用,苹果找人先“戴”了7年半
- 389. Find the Difference (hash&异或)
- JS复习 -- 函数柯里化
- jedate时间插件
- Ubuntu 16.04下deb包的安装及常用命令
- LINUX_C编程实战-第十章《进程间通信》-管道
- matlab添加当前文件夹及子文件夹到路径
- 栈和队列 构造数组的MaxTree
- Windows10下 opencv2.4.9+dlib19.7+Visual Studio 2017 配置教程
- 博客首记
- 大学英语单词Q
- 汇医慧影:700家合作医院,95%以上准确率,我们如何从40家影像AI公司中突围
- HTTP的请求方法OPTIONS
- 欢迎使用CSDN-markdown编辑器