摘要:本文从分析ls命令基本功能入手,层层深入。分析了ls命令所使用的系统调用,并着重分析了内核态
下的系统调用服务例程,以阐明ls命令的最基本的功能是如何实现的。
一、ls命令的功能分析:
*
使用man ls命令查看ls命令手册(功能描述和主要选项摘录如下):
List information about the FILEs (the current directory by default).
Sort entries alphabetically if none of -cftuvSUX nor --sort.
列出文件(默认当前目录)信息,如果没有-cftuvSUX和--sort选项,就按照字母顺序排序。
*
-a, --all do not ignore entries starting with .
不忽略以.开始的隐藏文件
-A, --almost-all do not list implied . and ..
不列出 .(当前目录)和..(上级目录)
-B, --ignore-backups do not list implied entries ending with ~
忽略以~结尾的备份文件
-c with -lt: sort by, and show, ctime (time of last modification of file status information)
with -l: show ctime and sort by name
otherwise: sort by ctime
和-lt一起使用,则显示ctime(最后修改文件信息的时间),并按ctime排序显示;和-l一起使用,则显示
ctime,但只按文件名的字母顺序排序;其他,按ctime排序显示。
/*该选项和-t选项在单独使用的时候是等价的,但在和-l选项配合使用的时候,-c的功能会被屏蔽,而-t选项不会*/
-d, --directory list directory entries instead of contents, and do not derefer�
ence symbolic links
不是列出该目录的文件信息,而是列出该目录项。不追踪符号链接的实际位置。
-F, --classify append indicator (one of */=>@|) to entries
在每个entry后面加上标识文件内容的符号:
* : 标识可执行文件 / : 标识目录 = : 套接字文件
@ : 符号链接文件 | : 管道文件
-l use a long listing format
以长格式显示。
二、ls所用到的系统调用:
使用strace ls命令我们可以查看ls命令使用到的系统调用,其中最重要的几个为:
open(".", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC) = 3
getdents64(3, /* 68 entries */, 32768) = 2240
getdents64(3, /* 0 entries */, 32768) = 0
close(3) = 0
1、open系统调用:
打开当前目录文件,返回获得的文件描述符。
O_RDONLY:只读 O_NONBLOCK:以非阻塞的方式打开文件 O_LARGEFILE:允许打开大文件
O_DIRECTORY:如果路径不是目录,则打开错误 O_CLOEXEC:在创建新的进程后关闭文件描述符
2、close系统调用:
关闭文件描述符。
3、getdents64:
读取当前目录下的文件。
三、getdents64的系统调用服务例程:
由于getdents64实现了ls核心功能,下面着重分析getdents64系统调用在内核态下的实现。getdents64在fs/readdir.c中定义如下:
275(, unsigned int, ,
276 struct *, , unsigned int, )
277{
278 struct * ;
279 struct * ;
280 struct ;
281 int ;
282
283 = -;
284 if (!(, , ))
285 goto ;
286
287 = -;
288 = ();
289 if (!)
290 goto ;
291
292 .current_dir = ;
293 . = ;
294 . = ;
295 . = 0;
296
297 = (, , &);
298 if ( >= 0)
299 = .;
300 = .;
301 if () {
302 (->) = ->;
303 if ((, &->))
304 = -;
305 else
306 = - .;
307 }
308 ();
309:
310 return ;
311}
getdents64首先调用fget函数得到目录文件的file结构体,再调用虚拟文件系统提供的函数,读取目录项,该函数的定义也在fs/readdir64中:
int (struct *, , void *)
24{
25 struct * = ->.->;
26 int = -;
27 if (!-> || !->->)
28 goto ;
29
30 = security_file_permission(, );
31 if ()
32 goto ;
33
34 = (&->);
35 if ()
36 goto ;
37
38 = -;
39 if (!()) {
40 = ->->(, , );
41 ();
42 }
43 (&->);
44:
45 return ;
46}
该函数首先通过file结构体得到inode,然后从inode中获得并执行file_operations结构体
中的读取目录函数(底层文件系统提供)->->(, , )。
综上所述,实际上对文件进行操作的是底层文件系统提供的函数,它通过file_operations结
构体可被上层的虚拟文件系统调用,而用户程序又可通过系统调用进入内核态,调用虚拟文件系统提供
的接口函数。
阅读(5501) | 评论(0) | 转发(0) |