一点笔记
文件描述符 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
里面的话都输出到了上一个终端里面。
那么再试一下0
和2
:
效果是一样的。为什么?因为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.