linux 标准输入的文件描述符,Linux exec与文件描述符

看到好几篇文章讲述exec都是一知半解,所以我尽量说的清楚明白一些。本文首先讲述Linux文件描述符,然后是exec,最后举例说明exec I/O重定向及其用法。

1 Linux文件描述符介绍

在Linux系统中一切皆可以看成是文件,文件又可分为:普通文件、目录文件、链接文件和设备文件。文件描述符(file descriptor简称FD)是内核为了高效管理已被打开的文件所创建的索引,其是一个非负整数(通常是小整数),用于指代被打开的文件,所有执行I/O操作的系统调用都通过文件描述符。最前面的三个文件描述符(0,1,2)分别与标准输入(stdin),标准输出(stdout)和标准错误(stderr)对应。因此,函数 scanf() 使用 stdin,而函数 printf() 使用 stdout。你可以用不同的文件描述符改写默认的设置并重定向进程的 I/O 到不同的文件。Unix 操作系统通常给每个进程能打开的文件数量强加一个限制。

例如:要把标准输出(1)和标准错误(2)重定向到一个文件,使用如下命令

xx命令 2>&1 filename

查看LINUX默认的文件描述符数:

# ulimit -n1024

使用用如下命令来增大文件描述符数:

ulimit -HSn 65536

2 exec原理介绍

exec和source都属于bash内部命令(builtins commands),

source:source命令即点(.)命令。

在bash下输入man source,找到source命令解释处,可以看到解释”Read and execute commands from filename in thecurrent shell environment and …”。从中可以知道,source命令是在当前进程中执行参数文件中的各个命令,而不是另起子进程(或sub-shell)。

exec:

在bash下输入man exec,找到exec命令解释处,可以看到有”No new process is created.”这样的解释,这就是说exec命令不产生新的子进程。那么exec与source的区别是什么呢? exec命令在执行时会把当前的shell process关闭,然后换到后面的命令继续执行。

系统调用exec是以新的进程去代替原来的进程,但进程的PID保持不变。因此,可以这样认为,exec系统调用并没有创建新的进程,只是替换了原来进程上下文的内容。原进程的代码段,数据段,堆栈段被新的进程所代替。

一个进程主要包括以下几个方面的内容:

(1)一个可以执行的程序

(2) 与进程相关联的全部数据(包括变量,内存,缓冲区)

(3)程序上下文(程序计数器PC,保存程序执行的位置)

描述exec命令最贴切的说法是:它践踏了你当前的shell。

当这个脚本结束了,相应的会话可能也就结束了。

但是,exec在对文件描述符进行操作的时候(也只有在这个时候),它不会覆盖你当前的shell。

3 exec I/O重定向基本概念和应用案例

3.1 基本概念(可以大体看一下意思,等看到后面的例子再来参考)

1 常用FD(文件描述符)有3个,为0(stdin,标准输入)、1(stdout,标准输出)、2(stderr,标准错误输出),但你也可以指定其他数字作为文件描述符;

2 bash(ksh)执行命令的过程:分析命令-变量求值-命令替代(``和$( ))-重定向-通配符展开-确定路径-执行命令;

3 &- 关闭标准输出

4 n&- 表示将 n 号输出关闭

5 < filename 代表读入一个文件filename

6 > filename 代表写入一个文件filename

7 <>filename 以读写方式打开文件filename

3.2 应用案例

1、通过exec分配文件描述符

#!/bin/shexec3<>hello.txt # 以读写方式绑定到文件描述符"3"

echo "hello exec" >&3 # 写入"hello exec",如果之前有内容,这里将会从文件开头进行覆盖echo "hello world" >&3 # 写入"hello world“,新的一行!

exec 3>&-# 关闭写,禁止写,然而,实际上它也不能读了~

# 如果是exec3

打开文件,看到的结果如下

[[email protected] tmp]# cathello.txt

hello exec #首次插入的在第一行

hello world #第二次在新的一行

errfilename #下面的都是旧数据,依旧保留

hello.txt

systemd-private-CEGg3c

test

2、将标准输出重定向到hello.txt

#!/bin/shexec1>hello.txt # 将标准输出重定向到文件hello.txt,从此以后,当前环境(shell)中的的标准输出都将被写入文件hello.txtecho "hello exec"

echo "hello world"

这样,在终端再也见不着标准输出了,因为所有标准输出到放大文件hello.txt中了

如果你现在运行who am i命令,终端什么都不显示,打开另外一个终端

可以发现hello.txt文件的内容如下

[[email protected] tmp]# cathello.txt

hello exec

hello world

root pts/1 2016-03-18 23:27 (192.168.233.1) #这是who am i命令的输出,已经重定向到该文件中了

3、在上面这个示例中,标准输出被重定向了,如果要恢复怎么办?

#!/bin/shexec100>&1 # 将文件描述符100连接到标准输出,此时100 和1同时指向hello.txt,即echo "hello exec" >&100 和echo "hello exec"的效果一样,都写入hello.txt

# 由于之后还要输出到终端,所以我们不得不使用一个临时的描述符来保存它!

exec1>hello.txt # 首先清空hello.txt,并再次将标准输出重定向到文件hello.txt,从此以后,这个环境中的标准输出都将被写入文件hello.txtecho "hello exec"exec1>&100 100>&-# 将标准输出连接到100,这是之前保存的标准输出

# 将描述符100关了,一了百了,因为已经还原标准输出了,留着它实在没必要echo "oh, my god!" # 从这句开始将显示在终端上

4、标准输入的操作与2、3相似,只是使用的是"

注意,下面这个必须存到脚本里面执行,不然总是会退出登录

#!/bin/shexec100

read line1echo$line1

exec0&-# 将标准输入连接到100

# 将描述符100关了,一了百了,因为已经还原标准输入了,留着它实在没必要

read-p "please input:"custome #测试不是文件的标准输入echo "your input is :$custome"

参考

原文:http://www.cnblogs.com/lizhaoxian/p/5294158.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值