Linux网络编程学习(六) ----- 管道(第四章)
1、管道的定义
管道就是将一个程序的输出和另外一个程序的输入连接起来的单向通道,比如命令: ls -l|more,就建立了一个管道,获取ls -l的输出作为more的输入,数据就沿着管道从管道的左边流到了管道的右边。
实际上内核为进程建立了两个句柄f1和f2,进程通过句柄f1向管道写入数据,同时通过f2从管道读出数据,这里是同一个进程建立了自己的管道
进程间的管道:通过fork出来的子进程,与父进程一样,拥有对同一个管道的读写句柄,但管道是单向的,因此要决定数据流向,如父进程到子进程或者子进程到父进程,那么不需要的句柄就要关闭
2、管道的建立和使用
1)通过pipe()函数建立管道,函数声明是int pipe(fd[2]) ,其中fd[0]用来从管道读,fd[1]向管道写
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main(void)
{
int fd[2], nbytes;
pid_t childpid;
char string[] = “Hello, world!\n”;
char readbuffer[80];
pipe(fd);
if((childpid = fork()) == -1)
{
perror(“fork”);
exit(1);
}
if(childpid == 0)
{
/* 子进程关闭管道的读句柄 */
close(fd[0]);
/* 通过写句柄向管道写入信息 */
write(fd[1], string, strlen(string));
_exit(0);
}
else
{
/* 父进程关闭管道的写句柄 */
close(fd[1]);
/* 通过读句柄从管道读出信息 */
nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
printf(“Received string: %s”, readbuffer);
}
return(0);
}
假定了数据流向是子进程到父进程,那么就由子进程写,父进程读,所以子进程要关闭读句柄,而父进程要关闭写句柄
2)使用popen()/pclose()函数,函数声明是FILE* popen(char * command, char *type)
popen()首先调用pipe()建立一个管道,然后用fork()函数建立一个子进程,运行一个shell环节,然后在这个环境中运行"command"参数指定的程序,数据管道流向由type控制,要么为"r"或者为"w",两者取其一,且type只取一个字符,比如"rw",那么只取"r",最后用pclose()关闭即可
#include <stdio.h>
#define MAXSTRS 5
int main(void)
{
int cntr;
FILE *pipe_fp;
char *strings[MAXSTRS] = { "roy", "zixia", "gouki","supper", "mmwan"};
/* 用popen 建立管道 */
if (( pipe_fp = popen("sort", "w")) == NULL)
{
perror("popen");
exit(1);
}
/* Processing loop */
for(cntr=0; cntr<MAXSTRS; cntr++)
{
fputs(strings[cntr], pipe_fp);
fputc('\n', pipe_fp);
}
/* 关闭管道 */
pclose(pipe_fp);
return(0);
}
popen()可以节省源代码,同时还可以在"command"中使用任意合法的shell指令,包括重定向和管道,如下均为合法
popen("ls ~roy", "r");
popen("sort > /tmp/zixia", "w");
popen("sort | uniq | more", "w");
如下例子为建立了两个管道,一个读管道,一个写管道
#include <stdio.h>
int main(void)
{
FILE *pipein_fp, *pipeout_fp;
char readbuf[80];
/* 用popen 建立一个通向"ls:的读管道*/
if (( pipein_fp = popen("ls", "r")) == NULL)
{
perror("popen");
exit(1);
}
/* 用popen 建立一个通向"sort"的写管道 */
if (( pipeout_fp = popen("sort", "w")) == NULL)
{
perror("popen");
exit(1);
}
/* 进程循环 */
while(fgets(readbuf, 80, pipein_fp))
{
fputs(readbuf, pipeout_fp);
} /* 关闭打开的管道 */
pclose(pipein_fp);
pclose(pipeout_fp);
return(0);
}
3、tips
1)pipe()调用必须在fork()前
2)及时关闭不需要的管道句柄
3)管道只能实现父子进程之间的通信,若两个进程没有fork()关系,必须考虑其他进程通信方式
Linux网络编程学习(六) ----- 管道(第四章)的更多相关文章
- Linux网络编程学习(五) ----- 信号(第四章)
1.基本概念 进程阻塞: 进程执行条件得不到满足,就自动放弃CPU资源而进入休眠状态,以等待条件满足,当条件满足时,系统就将控制权还给该进程进行未完成的操作 共享资源: 进程间协调使用的系统资源 锁定 ...
- Linux网络编程学习计划
由于网络编程是很重要的一块,自己这一块也比较欠缺,只知道一些皮毛,从今天开始系统学习<Linux网络编程>一书,全书分为十四个章节: 第一章 概论 P1-16 第二章 UNIX ...
- Linux网络编程学习路线
转载自:https://blog.csdn.net/lianghe_work/article 一.网络应用层编程 1.Linux网络编程01——网络协议入门 2.Linux网络编程02——无连接和 ...
- Linux网络编程学习(十二) ----- 结语
该书提前看完了,重点看了第四章和第六章,第七章以后只是大致浏览了一下,如果以后工作中涉及这一块再仔细研究一下,大概花了二十天的样子,主要了解了进程间的通信方式.socket编程以及五种I/O模式,看的 ...
- Linux网络编程学习(七) ----- 有名管道(第四章)
1.什么是有名管道?为什么有了管道还需要有名管道? 有名管道是解决管道不能提供非父子进程间通信的缺陷.管道在Linux系统内部是以文件节点(inode)的形式存在,但由于其对外的不可见性(“无名”性) ...
- Linux网络编程学习(十) ----- Socket(第六章)
前言:由于第五章主要介绍了TCP和UDP协议以及两者的包头的字段以及相应的功能,这里就不介绍了,对着字段看功能就好了,后续开始学习第六章 1.Socket Socket实质上就是提供了通信的端点,每个 ...
- Linux网络编程学习(九) ----- 消息队列(第四章)
1.System V IPC System V中引入的几种新的进程间通信方式,消息队列,信号量和共享内存,统称为System V IPC,其具体实例在内核中是以对象的形式出现的,称为IPC 对象,每个 ...
- Linux网络编程学习(十一) ----- 五种I/O模式(第六章)
1.五种I/O模式是哪几个? 阻塞I/O,非阻塞I/O,I/O多路复用,信号驱动I/O(SIGIO),异步I/O 一般来讲程序进行输入操作有两个步骤,一是等待有数据可读,二是将数据从系统内核中拷贝到程 ...
- Linux网络编程学习(八) ----- 文件和记录锁定(第四章)
1.什么是文件和记录锁定? 文件锁定的是整个文件,而记录锁定只锁定文件的一部分,文件和记录锁分为咨询式锁定和强制锁定 1)咨询式锁定 某个进程对某个文件进行了咨询式锁定,其他想访问该文件的进程将会被操 ...
随机推荐
- CreateThread给线程函数传递的参数
HANDLE WINAPI CreateThread ( __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, // 指向SECURITY_ATTR ...
- APP打包提交审核的步骤
- 【leetcode】453. Minimum Moves to Equal Array Elements
problem 453. Minimum Moves to Equal Array Elements 相当于把不等于最小值的数字都减到最小值所需要次数的累加和. solution1: class So ...
- 【转】@RequestBody注解出现的三点错误
错误1 { "timestamp": 1529747704259, "status": 415, "error": ...
- Python全栈之路----函数----局部变量
全局变量是定义在函数外部以及代码的变量,全局能用. 局部变量就是定义在函数里的变量,只能在局部生效. 在函数内部,可以引用全局变量. 如果全局和局部都有一个名字相同的变量,在函数内会优先调用函数内的局 ...
- CH3401 石头游戏(矩阵快速幂加速递推)
题目链接:传送门 题目: 石头游戏 0x30「数学知识」例题 描述 石头游戏在一个 n 行 m 列 (≤n,m≤) 的网格上进行,每个格子对应一种操作序列,操作序列至多有10种,分别用0~9这10个数 ...
- 学习笔记TF015:加载图像、图像格式、图像操作、颜色
TensorFlow支持JPG.PNG图像格式,RGB.RGBA颜色空间.图像用与图像尺寸相同(height*width*chnanel)张量表示.通道表示为包含每个通道颜色数量标量秩1张量.图像所有 ...
- js中常用的内置对象
Arguments 函数参数集合 arguments[ ] 函数参数的数组 Arguments 一个函数的参数和其他属性 Arguments.callee 当前正在运行的函数 Argument ...
- MySQL查询不使用索引汇总 + 如何优化sql语句
不使用索引原文 : http://itlab.idcquan.com/linux/MYSQL/918330.html MySQL查询不使用索引汇总 众所周知,增加索引是提高查询速度的有效途径,但是很多 ...
- oracle批量删除某个用户下的所有表
打开sql developer,输入如下语句,把USERNAME替换为需要删除的的用户名 然后把查询出来的结果复制出来执行一遍就行了. SELECT 'DROP table '||table_name ...