概述
什么是管道
管道是内核中一个单向的数据通道,有一个读取端和一个写入端,可以连接两个进程。
进程有三个标准数据流:
- 标准输入(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 cookien"
#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下的管道编程所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复