您的位置:首页 > 运维架构 > Linux

《Unix-Linux编程实践教程》读书笔记(十)

2014-05-29 23:30 309 查看
第十章 I/O重定向和管道

1.      shell脚本中

# ls > my.file

                #who| sort > userlist

         两个命令引出:如何将一个程序的结果输出到文件而不是屏幕?shell如何将一个程序的输出与另外一个程序的输入相连接?本章阐述进程间一种特殊的通信方式:重定向和管道。

2.      每隔60秒查询当前登录系统的用户情况的shell程序watch.sh使用了重定向。comm命令的介绍。该脚本体现了:脚本与C程序相比简单;每隔软件工具完成一件特定、通用的功能;I/O重定向和管道的使用。

3.      标准I/O和重定向的若干概念

         1)  三个标准文件描述符:所有的Unix工具都是用文件描述符0(标准输入stdin)、1(标注输出stdout)、2(标准错误输出stderr)

         2)  默认的tty连接:通常通过shell运行Unix工具时,stdin、stdout、stderr连在终端上,因此工具从键盘读取数据并且把输出和错误消息写到屏幕。

                   大部分Unix工具处理从文件或者标准输入读入数据,如果给定文件,则从文件读取;否则从标准输入stdin读取。

                   相反的,大多数程序并不接收输出文件,而将输出送到stdout,将错误消息送到stderr。如果想把上述信息写入文件或者是其他进程的stdin,则需要使用重定向技术。

4.      重定向I/O的是shell而不是程序,程序还是按部就班的那三个文件描述符。

5.      最低可用文件描述符原则:当进程打开一个文件时,总是分配文件描述符数组中最低的可用文件描述符。

6.      如何将stdin定向到文件:实质是将文件描述符重定向到文件,而程序还是从文件描述符0中读取数据。

         1)  方法1:close then open:程序默认打开文件描述符0、1、2。按照最低可用文件描述符原则,先close 文件描述符0(stdin),然后再打开包含要读入的数据的文件,这时就会将最低可用文件描述符0分配给该文件,从而实现目的。

         2)  方法2:open(file)、close(0)、dup(fd)、close(fd):该方法同方法一大致相同,只是在调用dup(fd)时也会用到最低可用文件描述符的原则,将打开的数据文件的文件描述符fd复制到文件描述符0上,然后再关闭打开的数据文件描述符fd

                   将该方法中的close(0),dup(fd)合并成一个系统调用dup2(oldfd,newfd)

1)  方法3:open(file)、dup2、close

7.      如何将stdout重定向到文件#who> userlist

         核心就是利用fork和exec之间的时间空隙,完成子进程stdout的关闭和输出文件的打开,利用最低可用文件描述符原则可实现 stdout的重定向。此外,exec虽然“换脑”,但是会传递打开过的文件描述符。

8.      重定向到文件的小结:

         1)  标准输入、输出、错误输出分别对应文件描述符0、1、2

         2)  最低可用文件描述符原则

         3)  文件描述符集合通过exec调用传递,且不会改变

         4)  shell通过fork产生子进程执行新程序,在子进程调用exec执行新的程序之前来重定向标准输入和标准输出到文件。

9. 管道编程:用管道将一个进程的标准输出连接到另一个进程的标准输入上。

         1)  创建管道:pipe(int  arry[2]);

                   arry[0]:为数据输出端;arry[1]:为数据写入端;

                   pipe同样遵循 最低可用文件描述符原则;

                  pipedemo.c展示了如何创建管道向自己发送数据。

         2)  使用fork来共享管道

                   一个进程创建管道,该进程同时得到了管道的两端,通过调用fork,子进程也得到了该管道的两端。父进程和子进程都可以对管道进行读写。但是当一个进程读,另一个进程写的时候,管道效率最高

                   使用 pipe、fork、exec来实现# who >sort的程序 pipe.c

1)  技术细节:管道并非文件

write将数据写入管道,read从管道中读取数据;

像文件一样,管道式不带任何结构的字节序列;

         从管道中读取数据

         -->管道读取阻塞:当进程试图读取管道中的数据时,进程被挂起直到数据被写进管道。同步的方式。

         -->管道的读取结束标志:当所有的写数据段关闭时,试图从管道读取数据的调用返回0.意味着文件的结束

         -->多个读者可能引起麻烦:两个进程读取一个管道,很可能出现二者读到的数据不完整,除非同过某种机制来协调他们对管道的读取。

         向管道写数据

         -->写入数据阻塞直到管道有空间去容纳新的数据

         -->写入必须保证一个最小的块大小:不会拆分小于最小块大小的数据

         -->若无读者在读取数据,则写操作执行失败(发送信号SIGPIPE,write调用返回-1,且errno置为EPIPE)

10.小结

         1)  标准输入、输出、错误输出

         2)  文件描述符都会从父进程传递给子进程,且在exec时也会被传递

         3)  创建文件描述符的时候的“最低可用文件描述符原则”

         4)  管道是内核中的一个数据队列,程序使用pipe创建

         5)  只有具有共同父进程的进程之间才可以使用管道连接

         传统的Unix管道在进程之间进行数据的单向传输,若需要在两个进程之间来回进行数据的传输,或者没有关联的进程或两个进程在不同的机器上,如何进行通信?后面的章节将进一步研究管道及网络编程。

----------------------------------------------------------------------------------------

本文链接http://blog.csdn.net/yongchurui/article/details/27589061

2014.05.29
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息