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 dereference 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中定义如下:
275SYSCALL_DEFINE3(getdents64, unsigned int, fd,
276 struct linux_dirent64 __user *, dirent, unsigned int, count)
277{
278 struct file * file;
279 struct linux_dirent64 __user * lastdirent;
280 struct getdents_callback64 buf;
281 int error;
282
283 error = -EFAULT;
284 if (!access_ok(VERIFY_WRITE, dirent, count))
285 goto out;
286
287 error = -EBADF;
288 file = fget(fd);
289 if (!file)
290 goto out;
291
292 buf.current_dir = dirent;
293 buf.previous = NULL;
294 buf.count = count;
295 buf.error = 0;
296
297 error = vfs_readdir(file, filldir64, &buf);
298 if (error >= 0)
299 error = buf.error;
300 lastdirent = buf.previous;
301 if (lastdirent) {
302 typeof(lastdirent->d_off) d_off = file->f_pos;
303 if (__put_user(d_off, &lastdirent->d_off))
304 error = -EFAULT;
305 else
306 error = count - buf.count;
307 }
308 fput(file);
309out:
310 return error;
311}
getdents64首先调用fget函数得到目录文件的file结构体,再调用虚拟文件系统提供的vfs_readdir函数,读取目录项,该函数的定义也在fs/readdir64中:
int vfs_readdir(struct file *file, filldir_t filler, void *buf)
24{
25 struct inode *inode = file->f_path.dentry->d_inode;
26 int res = -ENOTDIR;
27 if (!file->f_op || !file->f_op->readdir)
28 goto out;
29
30 res = security_file_permission(file, MAY_READ);
31 if (res)
32 goto out;
33
34 res = mutex_lock_killable(&inode->i_mutex);
35 if (res)
36 goto out;
37
38 res = -ENOENT;
39 if (!IS_DEADDIR(inode)) {
40 res = file->f_op->readdir(file, buf, filler);
41 file_accessed(file);
42 }
43 mutex_unlock(&inode->i_mutex);
44out:
45 return res;
46}
该函数首先通过file结构体得到inode,然后从inode中获得并执行file_operations结构体中的读取目录函数(底层文件系统提供)file->f_op->readdir(file, buf, filler)。
综上所述,实际上对文件进行操作的是底层文件系统提供的函数,它通过file_operations结构体可被上层的虚拟文件系统调用,而用户程序又可通过系统调用进入内核态,调用虚拟文件系统提供的接口函数。
- 【Spark研究】用Apache Spark进行大数据处理第二部分:Spark SQL
- Android基础总结(2)——活动Activity
- Java实现的IP处理工具类——可用于项目
- 使用SQLServer同义词和SQL邮件,解决发布订阅中订阅库丢失数据的问题
- 一次误报引发的DNS检测方案的思考:DNS隧道检测平民解决方案
- Andriod基础——Adapter类
- ORM查询语言(OQL)简介--高级篇:脱胎换骨
- 用Java实现处理日期的工具类——常用日期处理方法
- ORM查询语言(OQL)简介--实例篇
- 漏洞预警 | 海洋CMS(SEACMS)0day漏洞预警
- 【机器学习】分类算法评价
- Java中图片处理工具类——能满足各种需求
- onclicklistener到底怎么用?
- 如何入侵联网智能灯泡——LIFX智能灯泡
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 剑指offer(61-67)题解
- 宇智波程序笔记8-【高并发】ThreadLocal学会了这些,你也能和面试官扯皮了!
- 情感分析数据预处理过程
- java的内部类和静态内部类(嵌套类)
- python爬取B站视频弹幕分析并制作词云
- mybatis扩展之自定义类型处理器处理枚举类型
- IMDB影评数据集预处理(使用word2vec)
- 【leetCode】使用两个栈搞一个队列day05
- bert训练代码
- mybatis文件映射之自定义返回结果集
- maven之第一个maven程序
- 【LeetCode】重建二叉树day04
- 【LeetCode】从尾到头反过来返回每个节点的值(用数组返回)day03
- mybatis文件映射之利用association进行关联查询(二)
- 【JUC】CountDownLatch你真的了解吗?