|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
无论图形界面发展到什么水平这个原理是不会变的,Linux命令有许多强大的功能:从简单的磁盘操作、文件存取、到进行复杂的多媒体图象和流媒体文件的制作。
在Unix体系中,每一个历程都有STDIN、STDOUT和STDERR这3种尺度I/O,它们是程序最通用的输出输入体例。几近一切言语都有响应的尺度I/O函数,好比,C言语能够经由过程scanf从终端输出字符,经由过程printf向终端输入字符。熟习Shell的伴侣都晓得,我们能够便利地对Shell命令举行I/O重定向,好比find-name"*.java">testfile.txt把以后目次下的Java文件列表重定向到testfile.txt。多半情形下,我们只必要懂得I/O重定向的利用就够了,可是假如要编程完成相似Shell的I/O重定向和管道功效,那末就必要分明它的道理和完成。
上面本文就以Linux体系为详细例子,先容I/O重定向的道理和完成(文中实行情况为Ubuntu12.04,内核版本3.2.0-59)。
文件形貌符表
了解I/O重定向的道理必要从Linux内核为历程所保护的关头数据布局动手。对Linux历程来说,每一个翻开的文件都是经由过程文件形貌符(FileDescriptor)来标识的,内核为每一个历程保护了一个文件形貌符表,这个表以FD为索引,再进一步指向文件的具体信息。在历程创立时,内核为历程默许创立了0、1、2三个特别的FD,这就是STDIN、STDOUT和STDERR,以下图所表示:
<br>
所谓的I/O重定向也就是让已创立的FD指向其他文件。好比,上面是对STDOUT重定向到testfile.txt前后内核文件形貌符表变更的表示图
重定向前:
<br>
重定向后:
<br>
在I/O重定向的过程当中,稳定的是FD0/1/2代表STDIN/STDOUT/STDERR,变更的是文件形貌符表中FD0/1/2对应的详细文件,使用程序只体贴前者。实质上这和接口的道理是相通的,经由过程一个直接层把功效的利用者和供应者解耦。
上面我们经由过程strace命令跟踪一下echo命令的体系挪用:- dagang@ubuntu12:~$straceechohello2>&1>/dev/null|grepwritewrite(1,"hellon",6)=6
复制代码 我们能够看到write(1,"hellon",6)如许一个体系挪用,它的第一个参数1就是代表的STDOUT的FD,这申明关于echo程序,它尽管(经由过程尺度I/O函数从STDOUT)向FD1写进,而不体贴它们FD1究竟对应的是哪一个文件。
Shell恰是经由过程I/O重定向和管道这类特别的文件把多个程序的STDIN和STDOUT串连在一同构成更庞大功效的,上面是Shell中经由过程管道的表示图:
<br>
上面我们用一个实践的例子来体验一下:- dagang@ubuntu12:~$sleep30|sleep40&[1]5584dagang@ubuntu12:~$pgrep-lsleep5583sleep5584sleepdagang@ubuntu12:~$ll/proc/5583/fdtotal0lrwx------1dagangdagang64Feb2713:410->/dev/pts/3l-wx------1dagangdagang64Feb2713:411->pipe:[246469]lrwx------1dagangdagang64Feb2713:412->/dev/pts/3dagang@ubuntu12:~$ll/proc/5584/fdtotal0lr-x------1dagangdagang64Feb2713:410->pipe:[246469]lrwx------1dagangdagang64Feb2713:411->/dev/pts/3lrwx------1dagangdagang64Feb2713:412->/dev/pts/3
复制代码 下面我们启动了两个历程5583和5584,经由过程检察/proc//fd,我们看到历程5583的STDOUT和5584的STDIN被重定向到了pipe:[246469],如许就到达了毗连两个历程尺度I/O的目标。
dup2()体系挪用
下面先容了文件形貌符表和I/O重定向的道理,那末在Linux体系中怎样经由过程C程序完成I/O重定向呢?次要用到了dup2()这个体系挪用,man中关于dup2是如许说的:intdup2(intoldfd,intnewfd);
dup2()createacopyofthefiledescriptoroldfd.Afterasuccessfulreturnfromdup()ordup2(),theoldandnewfiledescriptorsmaybeusedinterchangeably.Theyrefertothesameopenfiledescription(seeopen(2))andthussharefileoffsetandfilestatusflags;forexample,ifthefileoffsetismodifiedbyusinglseek(2)ononeofthedescriptors,theoffsetisalsochangedfortheother. 这里我们经由过程一个实践的成绩来讲明它的利用办法:编写一个C程序,经由过程挪用sort这个Shell命令举行排序,请求把in.txt和out.txt分离重定向到sort的STDIN,STDOUT。 参考完成:- intmain(){intpid=0;//forkaworkerprocessif(pid=fork()){//waitforcompletionofthechildprocessintstatus;waitpid(pid,&status,0);}else{//openinputandoutputfilesintfd_in=open("in.txt",O_RDONLY);intfd_out=open("out.txt",O_CREAT|O_RDWR,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);if(fd_in>0&&fd_out>0){//redirectSTDIN/STDOUTforthisprocessdup2(fd_in,0);dup2(fd_out,1);//callshellcommandsystem("sort");close(fd_in);close(fd_out);}else{//...errorhandling}}return0;}
复制代码 下面的次要步骤包含:
1.起首fork一个子历程,后续步骤都在子历程中完成,父历程经由过程waitpid()体系挪用守候子历程停止;
2.翻开open()体系挪用翻开in.txt和out.txt,失掉它们的形貌符(在我的测试中,这两个值一般为3和4);
3.经由过程dup2()体系挪用把STDIN重定向到fd_in,把STDOUT重定向到fd_out(注重,重定向的影响局限是全部子历程);
4.经由过程system()体系挪用运转shell命令sort
要明白学好linux不是一件一蹴而就的事,一定要能坚持使用它,特别是在使用初期。 |
|