我是靠谱客的博主 闪闪服饰,这篇文章主要介绍Linux下的管道编程,现在分享给大家,希望可以做个参考。

什么是管道

管道是内核中一个单向的数据通道,有一个读取端和一个写入端,可以连接两个进程。
进程有三个标准数据流:

  • 标准输入(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.

下面的程序展示了如何创建管道,并用管道向自己发送数据

数据流向是这样的
这里写图片描述

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#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函数后,子进程也得到了这个连接。这时父进程和子进程都可以读写这个管道
这里写图片描述

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#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下内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(62)

评论列表共有 0 条评论

立即
投稿
返回
顶部