从windows到*nix(五) IO重定向与管道
2009-12-28 09:59
141 查看
标准IO
stdin,stdout,stderr,分别是标准输入,标准输出,标准错误。windows和*nix下都有的。
默认情况下,标准输入相当于从键盘输入,标准输出和标准错误相当于向屏幕输出。
C语言中,这三个是FILE*类型(文件指针),例如你用printf,那么内容直接输出到标准输出,等价于fprintf(stdout,...);你用scanf,直接从标准输入读取,等价于fscanf(stdin,...)。
它们有什么用呢?对windows来说,好像只能用来写实验性的小程序。
实际上,*nix中,它们是用户界面的重要组成部分,另外,还可以用来做重定向。
IO重定向
重定向的基本用法,在*nix的shell中如下使用:
这里echo命令用来原样输出,>号把标准输出重定向到文件,随后用cat命令显示那个文件的内容。
再看一个重定向标准输入的例子:
这里用<号把文件的内容送给wc程序去统计字符数
管道
前面shell中的的输入输出重定向都是只限于文件,管道则提供一种通用的方式。
这里管道符|把两个进程的输出和输入连接起来了。同样实现了统计字符数的目的。
类似的用法,在windows的cmd中也一样的,用兴趣的同学可以去发掘一下。
但是这两者之间有一个重大的区别在于,*nix下有一种软件模式,叫做过滤器,是windows软件所不具备的。
过滤器
正是由于过滤器模式的存在,使得*nix可以用大量小工具集合,做到“一行shell胜过万行C”。
过滤器是指这样一种程序行为,它顺序读取命令行指定的一个或多个文件,如果没有指定文件名,则从标准输入读取,然后把处理结果写入标准输出,如果这中间有任何错误发生,则把错误写入标准错误中。
从上面的描述,我们很容易想象,多个遵循过滤器模式的程序可以用管道符串成一个链式处理。信息的传递通过标准输入和标准输出来传递,而错误信息则送到标准错误中,以免干扰到真正的信息流。
日常经常用到的通用目的过滤器有下面这些:
cat 把输入拷贝到输出
head 截取开始数行
tail 截取结尾数行
cut 截取列
grep 执行按行搜索功能
wc 执行计数功能
sort 执行排序
一些利用过滤器的实例(这些例子大家可以分段去用,自然就知道每一部分含义):
ps -ef | grep httpd | grep -v grep | wc -l
输出当前系统中httpd进程的数目
cut -d' ' -f 1 access.log | sort | uniq -c|sort -nr
从apache日志文件中截取一列,并按照出现次数排序
即使不是严格遵循过滤器模式,只要程序有着规范的标准输出,仍然可以用做管道的起始位置。并且,它也可以被其他程序轻松的复用。
举个例子,windows下要获取文件列表,只好用操作系统提供的API,或者C库函数。
但是*nix下可以直接调用ls命令获取结果
作为一个反例,我们看看windows中的dir命令是怎么设计的
这样的结果,要从中提取出一个文件列表来,非常的困难,其难度远大于使用API或者库函数。(dir /w 的结果看起来好一点,但是它的问题更多)
应该说,从设计之初,windows的命令行工具就没想要与其他程序交互。
管道在程序中的应用
前面我们看到,输入输出不仅仅可以重定向到文件,它还可以通过管道传递到其他进程中去,借助这个特性,我们可以让它重定向到网络,用C写过CGI的应该可以理解这一点,设想一下,我们不需要socket,仅仅用scanf,printf等等标准IO函数,就可以实现一个网络协议的服务端,而网络连接的实际建立,是通过通用的网络服务程序来建立的。例如tcpd建立通用的基于tcp的网络服务,每当有连接进来,tcpd启动你的程序,它接收到得数据将写入你的标准输入,而你的标准输出将被tcpd发送到客户端。
类似的开发思想,我们可以不用修改任何代码,就为你的服务器程序增加SSL的支持。
管道在windows中也有实现,但是由于开发氛围,或者其他技术原因,应用的不是很普遍。
管道编程上,windows和*nix大体流程一致,
windows:
1.创建管道对
CreatePipe(&hReadPipe,&hWritePipe...)
2.创建新的进程
CreateProcess
这个函数需要的参数STARTUPINFO结构体,有hStdOutput,hStdInput,hStdErr三个成员,根据需要,把前面的hReadPipe或者hWritePipe传入。
如果需要,步骤1可以创建多对管道,反正你要写,就把读的给子进程,反之你要读的,就把写的给子进程。
3.往新进程的标准输入中写数据,或从新进程的标准输出中读数据。
在读或写之前,用CloseHandle把传入子进程的句柄(hReadPipe,hWritePipe之一)关掉。
然后用ReadFile或者WriteFile开始读写。
*nix:
1. 创建管道对
pipe(int pipefd[2])
2. 创建进程
首先fork,然后子进程用dup2把pipefd[0]复制到STDIN_FILENO(就是0),然后关闭pipefd[1],或者把pipefd[1]复制到STDOUT_FILENO(就是1),然后关闭pipefd[0]。
之后调用exec去载入要创建的进程。
3. 读或写
用read或者write。注意读写之前要把子进程使用的那一个用close函数关闭掉。
区别在*nix创建进程分两步,fork然后exec。windows只一步。
区别2,*nix要手工dup来复制文件描述符,windows在创建进程的API内部做好了这件事。
*nix步骤多一些,但是灵活,可以变化出多种模式来,例如fork之后,不仅仅子进程可以exec,父进程也可以exec,完完全全实现像“ls|wc -l”这样的功能。也就是子进程用wc去替代,父进程用ls去替代。
windows步骤少,模式固定,它要实现上述功能,反而更加繁琐,需要创建两个进程,并把它们对接,然后等待两个进程结束。
stdin,stdout,stderr,分别是标准输入,标准输出,标准错误。windows和*nix下都有的。
默认情况下,标准输入相当于从键盘输入,标准输出和标准错误相当于向屏幕输出。
C语言中,这三个是FILE*类型(文件指针),例如你用printf,那么内容直接输出到标准输出,等价于fprintf(stdout,...);你用scanf,直接从标准输入读取,等价于fscanf(stdin,...)。
它们有什么用呢?对windows来说,好像只能用来写实验性的小程序。
实际上,*nix中,它们是用户界面的重要组成部分,另外,还可以用来做重定向。
IO重定向
重定向的基本用法,在*nix的shell中如下使用:
~/test $echo Hello Hello ~/test $echo Hello >a.txt ~/test $cat a.txt Hello ~/test $
这里echo命令用来原样输出,>号把标准输出重定向到文件,随后用cat命令显示那个文件的内容。
再看一个重定向标准输入的例子:
~/test $wc <a.txt 1 1 6 ~/test $
这里用<号把文件的内容送给wc程序去统计字符数
管道
前面shell中的的输入输出重定向都是只限于文件,管道则提供一种通用的方式。
~/test $cat a.txt | wc 1 1 6 ~/test $
这里管道符|把两个进程的输出和输入连接起来了。同样实现了统计字符数的目的。
类似的用法,在windows的cmd中也一样的,用兴趣的同学可以去发掘一下。
但是这两者之间有一个重大的区别在于,*nix下有一种软件模式,叫做过滤器,是windows软件所不具备的。
过滤器
正是由于过滤器模式的存在,使得*nix可以用大量小工具集合,做到“一行shell胜过万行C”。
过滤器是指这样一种程序行为,它顺序读取命令行指定的一个或多个文件,如果没有指定文件名,则从标准输入读取,然后把处理结果写入标准输出,如果这中间有任何错误发生,则把错误写入标准错误中。
从上面的描述,我们很容易想象,多个遵循过滤器模式的程序可以用管道符串成一个链式处理。信息的传递通过标准输入和标准输出来传递,而错误信息则送到标准错误中,以免干扰到真正的信息流。
日常经常用到的通用目的过滤器有下面这些:
cat 把输入拷贝到输出
head 截取开始数行
tail 截取结尾数行
cut 截取列
grep 执行按行搜索功能
wc 执行计数功能
sort 执行排序
一些利用过滤器的实例(这些例子大家可以分段去用,自然就知道每一部分含义):
ps -ef | grep httpd | grep -v grep | wc -l
输出当前系统中httpd进程的数目
cut -d' ' -f 1 access.log | sort | uniq -c|sort -nr
从apache日志文件中截取一列,并按照出现次数排序
即使不是严格遵循过滤器模式,只要程序有着规范的标准输出,仍然可以用做管道的起始位置。并且,它也可以被其他程序轻松的复用。
举个例子,windows下要获取文件列表,只好用操作系统提供的API,或者C库函数。
但是*nix下可以直接调用ls命令获取结果
$ls -FLa >~/dir.log $cat ~/dir.log ./ ../ bin/ boot/ dev/ etc/ home/ lib/ lost+found/ mnt/ opt/ proc/ root/ sbin/ sys/ tmp/ tony.tgz usr/ var/ $
作为一个反例,我们看看windows中的dir命令是怎么设计的
C:/>dir 驱动器 C 中的卷没有标签。 卷的序列号是 B0B5-18AD C:/ 的目录 2009-12-21 12:47 <DIR> 360Rec 2004-09-08 10:54 0 AUTOEXEC.BAT 2004-09-08 10:54 0 CONFIG.SYS 2009-11-18 09:19 <DIR> dell 2006-06-22 17:27 <DIR> Documents and Settings 2009-11-17 14:04 <DIR> Downloads 2009-11-17 17:44 <DIR> i386 2009-07-07 14:31 4,128 INFCACHE.1 2009-12-29 17:37 <DIR> Program Files 2009-07-07 14:37 <DIR> Temp 2009-12-21 12:31 <DIR> WINDOWS 3 个文件 4,128 字节 8 个目录 9,779,306,496 可用字节 C:/>
这样的结果,要从中提取出一个文件列表来,非常的困难,其难度远大于使用API或者库函数。(dir /w 的结果看起来好一点,但是它的问题更多)
应该说,从设计之初,windows的命令行工具就没想要与其他程序交互。
管道在程序中的应用
前面我们看到,输入输出不仅仅可以重定向到文件,它还可以通过管道传递到其他进程中去,借助这个特性,我们可以让它重定向到网络,用C写过CGI的应该可以理解这一点,设想一下,我们不需要socket,仅仅用scanf,printf等等标准IO函数,就可以实现一个网络协议的服务端,而网络连接的实际建立,是通过通用的网络服务程序来建立的。例如tcpd建立通用的基于tcp的网络服务,每当有连接进来,tcpd启动你的程序,它接收到得数据将写入你的标准输入,而你的标准输出将被tcpd发送到客户端。
类似的开发思想,我们可以不用修改任何代码,就为你的服务器程序增加SSL的支持。
管道在windows中也有实现,但是由于开发氛围,或者其他技术原因,应用的不是很普遍。
管道编程上,windows和*nix大体流程一致,
windows:
1.创建管道对
CreatePipe(&hReadPipe,&hWritePipe...)
2.创建新的进程
CreateProcess
这个函数需要的参数STARTUPINFO结构体,有hStdOutput,hStdInput,hStdErr三个成员,根据需要,把前面的hReadPipe或者hWritePipe传入。
如果需要,步骤1可以创建多对管道,反正你要写,就把读的给子进程,反之你要读的,就把写的给子进程。
3.往新进程的标准输入中写数据,或从新进程的标准输出中读数据。
在读或写之前,用CloseHandle把传入子进程的句柄(hReadPipe,hWritePipe之一)关掉。
然后用ReadFile或者WriteFile开始读写。
*nix:
1. 创建管道对
pipe(int pipefd[2])
2. 创建进程
首先fork,然后子进程用dup2把pipefd[0]复制到STDIN_FILENO(就是0),然后关闭pipefd[1],或者把pipefd[1]复制到STDOUT_FILENO(就是1),然后关闭pipefd[0]。
之后调用exec去载入要创建的进程。
3. 读或写
用read或者write。注意读写之前要把子进程使用的那一个用close函数关闭掉。
区别在*nix创建进程分两步,fork然后exec。windows只一步。
区别2,*nix要手工dup来复制文件描述符,windows在创建进程的API内部做好了这件事。
*nix步骤多一些,但是灵活,可以变化出多种模式来,例如fork之后,不仅仅子进程可以exec,父进程也可以exec,完完全全实现像“ls|wc -l”这样的功能。也就是子进程用wc去替代,父进程用ls去替代。
windows步骤少,模式固定,它要实现上述功能,反而更加繁琐,需要创建两个进程,并把它们对接,然后等待两个进程结束。
相关文章推荐
- IO重定向&管道&元字符
- 玩转linux第三天通配符、组合键、IO重定向及管道详解(四)
- Linux上的IO重定向及管道的使用
- 8月1日 课堂笔记 IO重定向及管道和用户、组和权限管理
- bash的基本特性之文件名通配 及IO重定向,管道详解
- 管道和IO重定向
- 《鸟哥的Linux私房菜》学习笔记(6)——管道及IO重定向
- Linux管道及IO重定向小练习
- linux基础知识之:IO重定向和管道
- Linu Shell 编程基础--基本IO重定向和管道
- IO重定向及管道操作
- Windows管道与StdIn、StdOut重定向
- Linux基础之IO重定向及管道详解(涉及tr、tee命令)
- windows下使用重叠IO(OVERLAPPE)命名管道服务端
- 探秘linux-文件管理(inode理解)及管道和IO重定向
- 管道及IO重定向
- Linux系统介绍(四)IO重定向与管道
- windows环境编程: 线程创建函数 设置线程名 隐藏DOS窗口 重定向IO
- 管道与IO重定向之输出重定向
- Linux基础管理—— " 标准IO、重定向及管道 "