首页 > 学技术 > 技术网文 > Linux Shell > 正文

[保留] [原创]ls与devfs


来源 chinaunix.net 酷勤网整理

前两天yjh777问了一个/dev/fd的问题,当时没搞懂。这两天琢磨了一下想通了,贴出来供yjh777兄参考:

在较新的linux内核中引入了devfs,即/dev,有点类似/proc,它是一种虚拟文件系统。只是在需要时才动态地生成需要的设备文件,不像以前不管用不用必须先建好一大堆设备文件。

/dev/fd/下保存当前进程用到的文件句柄,对于不同的用户,不同的登录终端,不同的进程,使用的文件句柄的指向是不会一样的。
执行命令
cd /dev/fd

这样会进入当前shell对应的那一个“虚拟”的目录,此时当前的目录就是当前shell对应的devfs中的一个“凝固的”映像,请记住这一点。
这时ls -l会看到当前目录的文件,也就是当前的shell所使用的fd。因为列出的是一个“凝固的”映像的结果,所以如果使用watch,命令来监视的话,结果是不会看到任何改变的。

那么命令
ls -l /dev/fd/

会列出什么呢?同样是当前进程(这里的“当前进程”是当前shell吗?先想想,答案下面再给出)使用的fd,标准输入、标准输出和标准错误输出都是不变的。但是执行几次同样的命令,你会发现有一个fd的指向却每次执行时都在变化。
3 -> /proc/?????/fd

其中?????代表的数字也就是一个进程号,在不断地增大。
实际上我们随便看一个进程相应的/proc/?????/fd目录,里面存放的文件就是对应该进程使用的文件句柄。
那么我们再想想,ls -l /dev/fd/命令从何处取得当前进程的fd呢?我想是打开了/proc/?????/fd文件(这里取文件的广义含义,严格地说是一个伪文件系统下的一个目录文件),从其中读取了相应的fd。进程号?????对应的进程应该就是当前进程 -- ls命令,注意并不是当前shell!不过因为ls命令继承了当前shell的fd,除了用来读取fd的句柄fd-3之外,fd-0,fd-1和fd-2与当前shell使用的fd指向应该是相同的。

OK,让我们再看看命令
watch "ls -l /dev/fd/"

的显示。类似下面这样:
lrwx------  1 user user 64  6  2 18:17 0 -> /dev/null

l-wx------  1 user user 64  6  2 18:17 1 -> pipe:[280311]
lrwx------  1 user user 64  6  2 18:17 2 -> /dev/pts/0
lr-x------  1 user user 64  6  2 18:17 3 -> /proc/22698/fd

我们看到:
[list=1][*]标准输入被重定向到/dev/null,说明ls命令不用接受键盘输入。
[*]标准输出指向一个管道文件,可以想见,ls命令的输出通过管道交由watch命令处理。
[*]标准错误输出没有重定向,仍然指向我们远程登录的终端。
[*]fd-3指向文件/proc/22698/fd,我们在上面已经解释过了。[/list]
其中pipe后面的数字和/proc/后面的数字是不断地增大的,为什么?这个容易理解,watch命令不断地重新调用ls命令,新的ls命令的进程号不断地变大;用来接收ls命令输出的管道也自然每次都是新的,不过这里的数字代表什么含义,我还不清楚,知道的大牛请指教!

上面就是目前我对这个问题的理解。声明一下:我没看过devfs、ls、watch的源码,所以本贴有很多猜测的成份,说得不对的请大家指出。^_^

[ 本帖最后由 woodie 于 2006-6-5 08:38 编辑 ]



 woodie 回复于:2006-06-02 19:04:04

下面是yjh777兄的原贴:
[url=http://bbs.chinaunix.net/viewthread.php?tid=765039&extra=page%3D3][color=blue]一个cd /dev/fd; ls -l 和 ls -l /dev/fd 的问题。[/color]


 Cygnus 回复于:2006-06-02 23:28:36

引用:原帖由 woodie 于 2006-6-2 19:00 发表
..........
其中pipe后面的数字和/proc/后面的数字是不断地增大的,为什么?这个容易理解,watch命令不断地重新调用ls命令,新的ls命令的进程号不断地变大;用来接收ls命令输出的管道也自然每次都是新的,不过这里的数字代表什么含义,我还不清楚 ... 



1 -> pipe:[[color=Red]280311[/color]]  

In which [color=Red]280311[/color] is pipe's kernel buffer size


 woodie 回复于:2006-06-05 11:33:21

引用:原帖由 Cygnus 于 2006-6-2 23:28 发表


1 -> pipe:[[color=Red]280311[/color]]  

In which [color=Red]280311[/color] is pipe's kernel buffer size 


谢谢您的回贴!不过我还是有点怀疑,一个是:一个pipe需要2~3百K的buffer吗?另外这个数字也会不断增大。


 yjh777 回复于:2006-06-05 18:11:04

首先谢谢 woodie 的热心回复! :D

SVR4实现了全双工管道,并允许两个文件描述符既可以被写入也可以被读取。
Linux采用了另外一种解决方法:每个管道的文件描述符仍然是单向的,但是在
使用一个描述符之前不必把另外一个描述符关闭。

that num may be pipe's fd(file descriptor)

[ 本帖最后由 yjh777 于 2006-6-5 18:52 编辑 ]


 Cygnus 回复于:2006-06-05 21:19:58

引用:原帖由 yjh777 于 2006-6-5 18:11 发表
... that num may be pipe's fd(file descriptor) ... 



Oh no.

How about to run lsof to check what it is. Thanks.

[ 本帖最后由 Cygnus 于 2006-6-5 21:28 编辑 ]


 waker 回复于:2006-06-06 08:28:40

美比是 pipe的kernel vfs vnode
不是说一切皆文件么?:D


 Cygnus 回复于:2006-06-06 08:51:13

引用:原帖由 waker 于 2006-6-6 08:28 发表
美比是 pipe的kernel vfs vnode
不是说一切皆文件么?:D 



Don't guess !

PLEASE run lsof to get all needed information for pipes.
You may have to read some documents to understand the details
of lsof output for special objects such as socket, pipe, etc..


 r2007 回复于:2006-06-06 09:45:13

r2007@www fd $ (ls -l /dev/fd/;lsof -d 0-9)|cat

total 0
lrwx------    1 r2007    users          64 Jun  6 08:46 0 -> /dev/pts/0
l-wx------    1 r2007    users          64 Jun  6 08:46 1 -> pipe:[3273895]
lrwx------    1 r2007    users          64 Jun  6 08:46 2 -> /dev/pts/0
lr-x------    1 r2007    users          64 Jun  6 08:46 3 -> /proc/29222/fd
COMMAND   PID  USER   FD   TYPE DEVICE SIZE       NODE NAME
bash    22459 r2007    0u   CHR  136,0             802 /dev/pts/0
bash    22459 r2007    1u   CHR  136,0             802 /dev/pts/0
bash    22459 r2007    2u   CHR  136,0             802 /dev/pts/0
bash    29220 r2007    0u   CHR  136,0             802 /dev/pts/0
bash    29220 r2007    1w  FIFO    0,5         3273895 pipe
bash    29220 r2007    2u   CHR  136,0             802 /dev/pts/0
cat     29221 r2007    0r  FIFO    0,5         3273895 pipe
cat     29221 r2007    1u   CHR  136,0             802 /dev/pts/0
cat     29221 r2007    2u   CHR  136,0             802 /dev/pts/0
lsof    29223 r2007    0u   CHR  136,0             802 /dev/pts/0
lsof    29223 r2007    1w  FIFO    0,5         3273895 pipe
lsof    29223 r2007    2u   CHR  136,0             802 /dev/pts/0
lsof    29223 r2007    3r   DIR    0,2    0          1 /proc
lsof    29223 r2007    4r   DIR    0,2    0 1915158536 /proc/29223/fd
lsof    29223 r2007    5w  FIFO    0,5         3273915 pipe
lsof    29223 r2007    6r  FIFO    0,5         3273916 pipe
lsof    29224 r2007    4r  FIFO    0,5         3273915 pipe
lsof    29224 r2007    7w  FIFO    0,5         3273916 pipe
r2007@www fd $

根据以上的实测
pipe:[3273895]和lsof中的节点号是一样的,难道是巧合?


 woodie 回复于:2006-06-06 10:11:49

cygnus的建议是对的,我也用lsof看了下。结果还是同意waker和r2007的看法,此处应该是内核vnode。
谢谢各位!


 waker 回复于:2006-06-06 10:15:38

引用:原帖由 r2007 于 2006-6-6 09:45 发表
根据以上的实测

pipe:[3273895]和lsof中的节点号是一样的,难道是巧合? 


什么是最好的算法?
step1:俺猜x=1是方程的一个解
step2:将x=1代入方程,两边在误差范围内守恒,所以x=1是方程的一个有效解

这是俺一直以来的一个信条


 r2007 回复于:2006-06-06 10:36:39

引用:原帖由 waker 于 2006-6-6 10:15 发表

什么是最好的算法?
step1:俺猜x=1是方程的一个解
step2:将x=1代入方程,两边在误差范围内守恒,所以x=1是方程的一个有效解

这是俺一直以来的一个信条

我说彩票咋老不中呢,原来是猜得不好
偶愚笨,只会正面作战


 woodie 回复于:2006-06-06 11:02:06

执行命令:
watch "{ ls -l /dev/fd/; lsof -d 1,3; }"

会看得更清楚些:
Every 2s: { ls -l /dev/fd/; lsof -d 1,3; }              Tue Jun  6 10:53:43 2006


total 0
lrwx------  1 user user 64 2006-06-06 10:53 0 -> /dev/pts/0
l-wx------  1 user user 64 2006-06-06 10:53 1 -> pipe:[7779083]
lrwx------  1 user user 64 2006-06-06 10:53 2 -> /dev/pts/0
lr-x------  1 user user 64 2006-06-06 10:53 3 -> /proc/18299/fd
COMMAND   PID  USER   FD   TYPE DEVICE SIZE    NODE NAME
bash    17936 user    1u   CHR  136,0            2 /dev/pts/0
watch   18261 user    1u   CHR  136,0            2 /dev/pts/0
watch   18261 user    3r  FIFO    0,5      7779083 pipe
sh      18298 user    1w  FIFO    0,5      7779083 pipe
lsof    18300 user    1w  FIFO    0,5      7779083 pipe
lsof    18300 user    3r   DIR    0,2    0       1 /proc


我的环境是debian sarge,kernel 2.4.27。cygnus兄的环境也许不同。^_^


 yjh777 回复于:2006-06-06 18:02:06

谢谢各位大侠!!
man lsof
引用:
  NODE       is the node number of a local file;

                  or the inode number of an NFS file in the server host;

                  or the Internet protocol type - e. g, ``TCP'';

                  or ``STR'' for a stream;

                  or ``CCITT'' for an HP-UX x.25 socket;

                  or the IRQ or inode number of a Linux AX.25 socket device.




/dev/fd是指向/proc/self/fd的一个连接,而/proc/self又[color=Green]动态的[/color]指向当前程序的信息目录/proc/??????/

ls /dev/fd/看到的是当前ls进程本身打开的文件信息。
cd /dev/fd 也是进到当前cd进程本身对应的 /proc/$cd's_PID/fd中。。。


 Cygnus 回复于:2006-06-07 10:29:21

引用:原帖由 woodie 于 2006-6-6 10:11 发表
cygnus的建议是对的,我也用lsof看了下。结果还是同意waker和r2007的看法,此处应该是内核vnode。
谢谢各位! 



请恕老夫眼拙了. 君不见 size 与 node 在 lsof 的输出中乃是 side by side 吗. 
对由此而引起的误导表示极度之遗憾.  哈哈.


 r2007 回复于:2006-06-07 11:50:36

引用:原帖由 Cygnus 于 2006-6-7 10:29 发表


请恕老夫眼拙了. 君不见 size 与 node 在 lsof 的输出中乃是 side by side 吗. 
对由此而引起的误导表示极度之遗憾.  哈哈. 



我说呢,还以为pipe后面的数据在不同的系统有不同的解释呢。谢谢Cygnus的再次验证。


 yjh777 回复于:2006-06-07 12:53:30

以前用的 ls -il 看到的是看的是符号连接文件本身的inode号,加L选项就可以看出来了。

watch "ls -ilL /dev/fd/"




原文链接:http://bbs.chinaunix.net/viewthread.php?tid=766712
转载请注明作者名及原文出处



收藏本页到: