一点笔记

文件描述符 File descriptor

(之前面试的时候亮哥有问到这个问题,因为以前了解过相关的知识,所以能扯一点,不过还是说错了一部分。)

首先说说什么是文件描述符:

我们知道在Linux和Unix中有这样一个概念:“一切皆文件”。那么,我们的输入输出也都可以理解为文件。而且,既然是文件的话,那么就一定有一个实体,无论是真实的实体还是抽象出来的实体。

文件描述符就是这样一种实体,它代表了对文件操作的输入和输出的抽象实体。

然后我们再记住几个数字:

数字 含义
0 标准输入(stdin)
1 标准输出(stdout)
2 标准错误(stderr)

fd0就表示标准输入,fd1则是标准输出,fd2就是标准错误输出。

那么这些文件存放在哪儿呢? 在linux下,可以从这里找到他们:

/proc/process_id/fd/

做个实验:

打开一个终端,然后查看本进程的进程号:

进程号为14684,然后去寻找它的文件描述符:

(注:其实可以直接进入 /proc/self/fd/目录,两者是等价的。)

/proc/self This directory refers to the process accessing the /proc filesystem, and is identical to the /proc directory named by the process ID of the same process.

我们试着往里面写点东西:

看到了吗? 我们写入到1里面的话都输出到了上一个终端里面。

那么再试一下02

效果是一样的。为什么?因为0时输入,相当于键盘敲入的信息,1是输出,输出到了屏幕上,2是错误输出,也是输出。

细心的同学可能会问,文件描述符只有这几个吗?还有那个255是干什么的?

首先,文件描述符当然不是这几个,它是可以自己定义的,在Shell编程中,这是很有用的一点,巧妙地运用I/O重定向, 能够解析和粘合命令输出的各个片断。这样就可以产生报告与日志文件。

我们可以绑定一个描述符6到日志文件,绑定7到正常文件,绑定8到调试文件,这样我们就能将脚本产生的输出分流,从而分类审查不同类型的日志或者不同的调试信息。

多说一点,利用exec命令可以创建,绑定,关闭文件描述符。

exec 6>&1
#创建fd6,绑定到标准输出

echo hello >&6
#将输出重定向到fd6

exec 6>script.log
#将fd6的内容输出到script.log文件中
#上面的相当于 echo hello > script.log,但是在脚本中这样写会有点乱,尤其是当文件名比较长的时候。

exec 6>&-
#关闭fd6

可以看看下面这个来自《高级Shell脚本编程指南》的例子: https://raw.githubusercontent.com/wrfly/my-pastes/master/3-27.sh

也可以看看别人的博客,介绍的很详细: http://blog.chinaunix.net/uid-20671208-id-3588619.html

哦对了,还有一个tee命令,它可以建立一个“T型管道”(我给起得名字,哈哈),连接标准输出并且输入到文件中的同时还能输出到屏幕上。在 Computer Science from the Bottom Up - Ian Wienand这本书里有提到管道的原理,tee的原理可以从那里很好的理解。

/proc目录(process information pseudo-filesystem)

随便想到的。详情:TLDP- /proc

这个目录是虚拟出来的系统目录,也就是说,他并不实际存在于硬盘中,而是当系统启动时创建的。这里面包含了系统内存信息,磁盘挂载信息,硬件配置,进程信息等。

(妈蛋我又要翻译了) 下面是在进程目录下的一些杂七杂八的东西:

/proc/PID/cmdline
	命令行参数
/proc/PID/cpu
	当前和过去的CPU使用率
/proc/PID/cwd
	当前工作目录
/proc/PID/environ
	系统环境信息
/proc/PID/exe
	一个到当前进程执行的程序的软链接
/proc/PID/fd
	文件描述符所在的目录
/proc/PID/maps
	映射内存信息
/proc/PID/mem
	当前进程所占用的内存
/proc/PID/root
	进程的根目录
/proc/PID/stat
	进程状态
/proc/PID/statm
	进程内存状态
/proc/PID/status
	进程状态(易读)

管道

有名管道:

$ mkfifo named_pipe
$ ls named_pipe
prw-rw-r-- 1 mr mr 0  3月 27 22:07 named_pipe|

简单地说,有名管道就是一个有名字的管道文件,区别于无名管道,无名管道是pipe(|),看不到实体。

我们可以向有名管道中输入信息:

需要注意的是,在管道未被cat读取内容之前,是处于阻塞态的,也就是等待被读取,可以从别的进程继续往里输入,也可以理解为一个队列,先进先出。

而无名管道,可以简单地理解为 | 这个东西。因为他没有名字,没有实体,叫不上来,所以就叫他无名管道。(实际上它是内核在虚拟内存中创建的)

在系统中,这东西在父子进程中建立了一个联系,把父进程的输出传递给了子进程。管道连接的是两个进程。

详情: http://www.aliog.com/50368.html http://blog.163.com/xychenbaihu@yeah/blog/static/132229655201011177264875/

Unix 文件类型

在我们用ls -l的时候,文件的最前面会有一个标志位, 比如:

ls -l named_pipe test
prw-rw-r-- 1 mr mr    0  3月 27 22:12 named_pipe
-rw-rw-r-- 1 mr mr  391  1月 14 11:38 test

在这里最前面的这个p就表示pipe,管道文件。而test是一个一般文件,所以前面是一个-

列举如下:

标志位 含义
- 一般文件
d 目录文件
l 链接文件
p 有名管道
s socket文件
c 字符设备(文件流)
b 块设备(储存设备)
D Solaris特有,Door文件

PTS / TTY

TTY Definition: Teletypewriter originally and now also means any terminal on Linux/Unix systems. It also means any serial port on Unix/Linux systems.

PTS Definition: Stands for pseudo terminal slave.

The difference between TTY and PTS is the type of connection to the computer. TTY ports are direct connections to the computer such as a keyboard/mouse or a serial connection to the device. PTS connections are SSH connections or telnet connections. All of these connections can connect to a shell which will allow you to issue commands to the computer.

Virtual teletype (VTY) is a command line interface (CLI) created in a router and used to facilitate a connection to the daemon via Telnet, a network protocol used in local area networks. To connect to a VTY, users must present a valid password.

comments powered by Disqus