Linux输入输出重定向

参考文章:

Linux下的管道编程技术-dup函数和dup2函数

http://www.xxlinux.com/linux/article/development/soft/20071214/13347.html

 

Linux下的管道编程技术

http://tech.it168.com/o/2006-11-07/200611061433947.shtml

http://publish.itpub.net/o/2006-11-07/200611061433947.shtml

 

Linux管道的实现机制

http://www.kerneltravel.net/kernel-book/%E7%AC%AC%E4%B8%83%E7%AB%A0%20%E8%BF%9B%E7%A8%8B%E9%97%B4%E9%80%9A%E4%BF%A1/7.1.1.htm

 

UNIX环境高级编程(第2版) 3.12 dup和dup2函数

http://book.csdn.net/bookfiles/418/10041815074.shtml

 

1、基本概念回顾

系统调用级概念--文件描述符/文件描述符表

0  标准输入

1  标准输出

2  标准错误

这三个文件描述符所指向的内核struct file结构默认指向的设备为进程所属终端,即tty、pst等等。

 

C运行库级概念--FILE结构

stdin    标准输入FILE结构指针,其所关联的文件描述符为0

stdout  标准输出FILE结构指针,其所关联的文件描述符为1

stderr   标准错误FILE结构指针,其所关联的文件描述符为2

 

C++标准库级概念--流

cin    标准输入流对象,其所关联的文件描述符为0

cout  标准输出流对象,其所关联的文件描述符为1

cerr   标准错误流对象,其所关联的文件描述符为2

 

FILE结构和流这两个概念都是在语言层次对系统调用级概念文件描述符的封装,没有本质的区别。

 

2、输入输出重定向的概念和目的

 

3、输入输出重定向的用法

command >file 2>&1,等价于command &>file

以w的方式(参见fopen文件打开模式)打开文件file,>file等价于1>file,首先将文件file对应的文件描述符的文件指针复制到文件描述符1,即重定向标准输出到文件file,接着将文件描述符1的文件指针复制到文件描述符2,即同时重定向标准错误到文件file。其本质工作原理是调用dup2函数。特别注意的是重定向的顺序,如果写成command 2>&1 >file,其意义是首先将标准错误重定向到标准输出(这个时候标准输出还是指向终端),接着将标准输出重定向到文件file,其最终表现是标准错误还是输出到终端,标准输出才是输出到文件file。反射

另外是以w的方式打开文件file的,所以file文件中只能记录command最后一次运行的标准输出和标准错误。

 

:>file 或 >file

这两个命令表示将文件file设置为空,即清空文件内容。如果文件不存在,则创建一个空文件(等同于touch命令)。

:表示一个空输出

这两个命令的唯一区别就是>file不是在所有shell中都可以正常工作。

 

command >>file 2>&1

以a的方式打开文件file,其他与上面的命令相同。>>file等价于1>>file。

由于是以a的方式打开文件file,所以command每次运行的标准输出和标准错误都记录在文件file中。

 

command <file

以r的方式打开文件file,<file等价于0<file,将文件file对应的文件描述符的文件指针复制到文件描述符0,即重定向标准输入到文件file,即标准输入将从文件file中读取。 

 

exec

 

echo 123456789 >file  #把字符串写到文件file中,文件file内容为123456789
exec 3<>file                 #把文件file以读写方式打开,并指定文件描述符为3
read -n 4 <&3              #从文件file中读4个字符,文件file的读写指针已经指到第四个字符末尾
echo -n . >&3               #在第5个字符处写一个点,覆盖第5个字符,-n表示不换行
exec 3>&-                    #关闭文件描述符3

cat file                          #文件file的内容现在变成了1234.6789

说明:

exec n<file     把文件file以读方式打开,并指定其文件描述符为n

exec n>file     把文件file以写方式打开,并指定其文件描述符为n

exec n<>file   把文件file以读写方式打开,并指定其文件描述符为n

exec n>&-                        关闭输出文件描述符n
exec n<&-                        关闭输入文件描述符n
exec 0<&- 或 exec <&-    关闭标准输入

exec 1>&- 或 exec >&-    关闭标准输出

 

注意:3-9号描述符都是保留给shell脚本使用的。

 

4、输入输出重定向的实现原理

输入输出重定向是通过在头文件unistd.h中定义的dup和dup2系统调用函数来实现的,定义如下:

  
  
#include <unistd.h>
int dup( int oldfd );
int dup2( int oldfd, int targetfd )

 

利用函数dup,我们可以复制一个描述符。传给该函数一个既有的描述符,它就会返回一个新的描述符,这个新的描述符是传给它的描述符的拷贝。这两个描述符指向同一个内核struct file结构。例如,如果我们对一个文件描述符执行lseek操作,得到的第一个文件的位置和第二个是一样的。下面是用来说明dup函数使用方法的代码片段:

  
  
int fd1, fd2;
...
fd2 = dup( fd1 );

    需要注意的是,我们可以在调用fork之前建立一个描述符,这与调用dup建立描述符的效果是一样的,子进程也同样会收到一个复制出来的描述符。

 

dup2函数跟dup函数相似,但dup2函数允许调用者规定一个有效描述符和目标描述符的id。dup2函数成功返回时,目标描述符(dup2函数的第二个参数)将变成源描述符(dup2函数的第一个参数)的复制品,换句话说,两个文件描述符现在都指向同一个文件,并且是函数第一个参数指向的文件。下面我们用一段代码加以说明:

  
  
int oldfd;
oldfd = open("app_log", (O_RDWR | O_CREATE), 0644 );
dup2( oldfd, 1 );
close( oldfd );

本例中,我们打开了一个新文件,称为“app_log”,并收到一个文件描述符,该描述符叫做oldfd。我们调用dup2函数,参数为oldfd和1,这会导致用我们新打开的文件描述符替换掉由1代表的文件描述符(即标准输出)。任何写到标准输出的东西,现在都将改为写入名为“app_log”的文件中。需要注意的是,dup2函数在复制了oldfd之后,会立即将其关闭,但不会关掉新近打开的文件描述符,因为文件描述符1现在也指向它。 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值