Linux下的管道编程
来源:互联网 发布:阿里云cdn节点ip 编辑:程序博客网 时间:2024/06/05 04:59
什么是管道
管道是内核中一个单向的数据通道,有一个读取端和一个写入端,可以连接两个进程。
进程有三个标准数据流:
- 标准输入(stdin),文件描述符0
- 标准输出(stdout),文件描述符1
- 标准错误输出(stderr),文件描述符2
管道将一个进程的输出和另一个进程的输入连接起来,数据便可以从一个进程传递到另一个进程。
pipe函数
可以用pipe函数来创建管道
头文件:#include <unistd.h>
函数原型:result = pipe(int array[2])
参数:array[0]为从管道读取数据端的文件描述符
array[1]为写入管道数据端的文件描述符
他们是输出参数。
返回值:-1代表错误,0代表成功
pipe调用
使用最低可用文件描述符。一般情况下,0,1,2被标准
数据流占用,所以array[0],array[1],分别是3,4.
下面的程序展示了如何创建管道,并用管道向自己发送数据
数据流向是这样的
#include <stdio.h>#include <unistd.h>int main(){ int len,i,apipe[2]; char buf[BUFSIZ]; /*get a pipe*/ if(pipe(apipe) == -1) { perror("Could not make pipe"); exit(1); } printf("Got a pipe! It's file descriptors: { %d %d}\n",apipe[0],apipe[1]); /*read from stdin, write into pipe, read from pipe, print*/ while(fgets(buf,BUFSIZ,stdin)) { len=strlen(buf); /*将buf写入进管道*/ if( write( apipe[1],buf,len) != len) { perror("writing to pipe"); break; } /*将原来的buf数组清空*/ for(i=0; i<len; i++) buf[i]='X'; /*从管道中读取数据放在buf中*/ len = read(apipe[0],buf,BUFSIZ); if( len == -1) { perror("reading from pipe"); break; } /*将buf中的数据写到标准输出(文件描述符为1)中*/ if( write(1,buf,len) != len) { perror("writing to stdout"); break; } } return 0;}
相关函数:
write
目标:将函数中的数据写入文件
头文件:#include <unistd.h>
函数原型:ssize_t result = write(int fd, void* buf, size_t amt);
参数:fd是文件描述符
buf是内存数据
amt是要写的字节数
返回值:成功则返回写入的字节数,失败返回-1
注:有些情况写入成功,但写入的字节数并不等于要写的字节数,比如磁盘空间不足等,所以要检查。result是否等于amt
read
目标:把数据读入缓冲区
头文件:#include <unistd.h>
函数原型:ssize_t numread = read(int fd, void* buf, size_t qty);
参数:fd是文件描述符
buf是存放数据的缓冲区
qty是要读取的字节数
返回值:成功则返回读取的字节数,失败返回-1
注:有些情况读取成功,但读取的字节数不一定等于要读的字节数,比如文件里没那么多数据
截图
当然,很少有进程会用管道给自己发送数据
下面的程序展示了如何用fork函数实现两个进程共享一个管道
当进程创建了一个管道后,该进程就又连向管道两端的连接。当调用fork函数后,子进程也得到了这个连接。这时父进程和子进程都可以读写这个管道
#include <stdio.h>#define CHILD_MESS "I want a cookie\n"#define PAR_MESS "testing...\n"#define oops(m,x) {perror(m);exit(x);}int main(){ int pipefd[2]; int len; char buf[BUFSIZ]; int read_len; /*建立一个管道*/ if( pipe( pipefd ) == -1) oops("cannot get a pipe", 1); /*这个switch很巧妙啊,复制一个进程,然后判断父进程还是子进程*/ /*这里的switch里没有break,虽然这个程序不会用到break,但我觉得还是写上比较好*/ switch( fork() ){ case -1: oops("cannot fork", 2); /*child writes to pipe every 5 seconds*/ case 0: len = strlen(CHILD_MESS); while(1){ /*将GHILD_MESS写入管道*/ if(write( pipefd[1], CHILD_MESS,len) != len ) oops("write",3); sleep(5); } /*parent reads from pipe and also write to pipe*/ default: len = strlen(PAR_MESS); while(1){ if( write( pipefd[1], PAR_MESS, len) != len) oops("write",4); sleep(1); read_len = read( pipefd[0], buf, BUFSIZ); if( read_len <= 0) break; write(1, buf, read_len); /*将buf写到标准输出中*/ } } return 0;}
截图
- Linux下的管道编程
- Linux下的管道编程
- Linux下的管道编程技术
- Linux下的管道编程技术
- Linux下的管道编程技术
- Linux下的管道编程技术
- Linux下的管道编程技术
- Linux下的管道编程技术
- Linux下的管道编程技术
- Linux下的管道编程技术
- Linux下的管道编程技术
- linux下的管道
- [转]Linux下的管道编程技术:dup dup2 popen
- Linux下的管道编程技术 dup dup2 popen
- Linux下的管道编程技术:dup dup2 popen
- Linux下的管道编程技术 dup dup2 popen
- 尝试linux下c编程之管道
- 在Linux下使用管道进行编程
- T- SQL性能优化详解
- CSU 1617: Itself is Itself(强连通缩点)思想转换到图论
- 安卓实习期间整理知识点(十三)
- date0405/EhanshiLanhanshi.java
- date0405/SingleDemo.java
- Linux下的管道编程
- OC--面向对向的三大特性(二)
- 字符串反转实现的几种方式
- JAVA学习第7天(2)java当中的异常2
- How to upload your project to GitHub
- oracle修改列的类型
- date0405/SingleTest.java
- 3.5 Mediator(中介者) -- 对象行为型模式
- leetcode-Search Insert Position