java 解压ygb文件_文件系统-目录项缓存与散列表
Refer to <
内核源代码情景分析
>> and <>
Having any problems, send mails to viloner@163.com
目录项缓存与散列表
所谓缓存,是指把存在于磁盘中的操作系统运行时频繁使用到的信息读取到内存中去,以提高
CPU
读取这些信息的速度。所以目录项的缓存就是指把存在于磁盘上的目录项信息读取到内存中去,而这些目录信息就是一个个的
dentry
结构。当某个进程运行时用到某个目录项,但在内存中却没有相应的
dentry
结构,就需要在内存中建立
(
所谓的建立实际是从磁盘上把相应的
dentry
结构读取到内存中去
)
一个与该目录项对应的
dentry
结构。由于在操作系统运行的过程中,用到的目录项很多,因此读入到内存中的
dentry
结构就非常多,故有必要对已读入到内存中的所有
dentry
结构进行管理,内核中的
dentry_hashtable
便是用于此目的的。
首先分析一下
dentry
的结构,便可知内核是如何在内存中管理
dentry
结构的。
Dentry
结构中有
6
个
list_head,
即
d_vfsmnt
、
d_hash
、
d_lru
、
d_child
、
d_subdirs
、和
d_alias
。注意,
list_head
既可以用来作为一个队列的头部,也可以用来将其所在的数据结构挂入到某个队列中。其中
d_vfsmnt
仅在该
dentry
结构为一个安装点时才使用。一个
dentry
结构一经建立就通过其
d_hash
挂入杂凑表
dentry_hashtable
中的某个队列里,当共享计数变为
0
时则通过
d_lru
挂入队列
dentyr_unused
中。同时,
dentry
结构通过
d_child
挂入到其父节点
(
上一层目录
)
的
d_subdirs
队列中,同时又通过指针
d_parent
指向父目录的
dentry
结构。而它自己各个子目录的
dentry
结构则在它本身的
d_subdirs
队列中。一个有效的
dentry
结构必定有一个相应的
inode
结构,这是因为一个目录项要么代表一个文件,要么就代表着一个目录,而目录实际上也是文件。所以,只要是有效的
dentry
结构,则其指针
d_inode
必定指向一个
inode
结构。可是,反过来一个
inode
却可能对应着不止一个
dentry
结构,也就是说,一个文件可以有不止一个文件名
(
或路径名
)
。这是因为一个已经建立的文件可以被连接
(link)
到其他文件名。所以,在
inode
结构中有个队列
i_dentry
,凡是代表着这个文件的所有目录项都通过其
dentry
结构中的
d_alias
挂入相应
inode
结构中的
i_dentry
队列。此外,
dentry
结构中还有指针
d_sb,
指向其所在设备的超级块
super_block
数据结构,以及指针
d_op,
指向特定文件系统
(
指文件格式
)
的
dentry_operations
结构。也许可以说,
dentry
结构是文件系统的核心数据结构,也是文件访问和为文件访问而做的文件路径搜索操作枢纽。
下面是一个简要的总结:
1、
每个
dentry
结构都通过队列头
d_hash
链入杂凑表
dentry_hashtable
中的某个队列里。
2、
共享计数为
0
的
dentry
结构都通过队列头
d_lru
链入
LRU
队列
dentry_unused
,在队列中等待释放或者“东山再起”。
3、
每个
dentry
结构都通过指针
d_inode
指向一个
inode
数据结构。但是多个
dentry
结构可以指向同一个
inode
数据结构。
4、
指向同一个
inode
数据结构的
dentry
结构都通过队列头
d_alias
链接在一起,都在该
inode
结构的
i_dentry
队列中。
5、
每个
dentry
结构都通过指针
d_parent
指向其父目录节点的
dentry
结构,并通过队列头
d_child
跟同一目录中的其他节点的
dentry
结构链接在一起,都在父目录节点的
d_subdirs
队列中。
6、
每个
dentry
结构都通过指针
d_sb
指向一个
super_block
数据结构。
7、
每个
dentry
结构都通过指针
d_op
指向一个
dentry_operations
数据结构。
8、
每个
dentry
结构都有个队列头
d_vfsmnt,
用于文件系统的安装,详见“文件系统的安装与拆卸”。
在分析完
dentry
数据结构以后,现在来看一下
dentry_hashtable
杂凑表的
散列算法。
dentry_hashtable
是由
list_head
组成的数组
,
它们与
dentry->d_hash
相环接
,
形成短链
,
散列表中的
dentry
将均分布于这些短链上
;
散列表的索引确定于父目录项地址和目录名的
hash
值
; dentry_hashtable
的尺寸由系统内存大小分配
,
每
4M
内存分配一个页面
,
每个页面具有
512
项索引
;
哈希链表
dentry_hashtable
定义在
dcache.c
文件中,如下:
static struct list_head *dentry_hashtable;
d_hash(dentry,hash)
为散列函数
,
它将
dentry
地址和
hash
值相组合
,
映射到
dentry_hashtable
表中
,
返回相应的散列链
;
d_rehash(dentry)
将
dentry
加入散列表
;
d_drop(dentry)
将
dentry
从散列表中删除
;
d_lookup(dentry,qstr)
在散列中找出以
dentry
作为父目录项
,
名称为
qstr
的目录项
.
下面分别介绍一下这几个函数:
一、
d_hash(dentry,hash)
每一个
dentry
对象都通过其父目录
dentry
对象的指针和其文件名的哈希值
hash
来唯一地确定它所属的哈希链表的表头指针,这是通过
d_hash
函数来完成的:
static inline struct list_head * d_hash(struct dentry * parent, unsigned long hash)
{
hash += (unsigned long) parent / L1_CACHE_BYTES;
hash = hash ^ (hash >> D_HASHBITS) ^ (hash >> D_HASHBITS*2);
return dentry_hashtable + (hash & D_HASHMASK);
}
每个目录项文件名的哈希值是通过
full_name_hash()
函数(定义在
include/linux/dcache.h
文件中)来计算的,如下所示:
/* Compute the hash for a name string. */
static __inline__ unsigned int full_name_hash(const unsigned char * name, unsigned int len)
{
unsigned long hash = init_name_hash();
while (len--)
hash = partial_name_hash(*name++, hash);
return end_name_hash(hash);
}
可以看出,该函数又向下调用
partial_name_hash()
函数和
end_name_hash
()函数来完成哈希值的计算工作。
二、
d_rehash(dentry)
向哈希链表中增加一个
dentry
对象
函数
d_rehash()
实现这一功能,它首先通过
d_hash()
函数找到这个
dentry
对象应该挂到哪一个哈希链表中,然后设置
d_hash
指针。如下所示(
dcache.c
):
void d_rehash(struct dentry * entry)
{
struct list_head *list = d_hash(entry->d_parent, entry->d_name.hash);
spin_lock(&dcache_lock);
list_add(&entry->d_hash, list);
spin_unlock(&dcache_lock);
}
三、
d_drop(dentry)
从哈希链表中摘除一个
dentry
对象
函数
d_drop
()实现这一点,如下所示(
dcache.h
):
static __inline__ void d_drop(struct dentry * dentry)
{
spin_lock(&dcache_lock);
list_del(&dentry->d_hash);
INIT_LIST_HEAD(&dentry->d_hash);
spin_unlock(&dcache_lock);
}
头文件
dcache.h
中还定义了一个函数
d_unhashed()
,用来测试一个
dentry
对象是否没有链接在哈希链表中,如下:
static __inline__ int d_unhashed(struct dentry *dentry)
{
return list_empty(&dentry->d_hash);
}
四、
d_lookup(dentry,qstr)
在散列中找出以
dentry
作为父目录项
,
名称为
qstr
的目录项
struct dentry * d_lookup(struct dentry * parent, struct qstr * name)
{
unsigned int len = name->len;
unsigned int hash = name->hash;
const unsigned char *str = name->name;
struct list_head *head = d_hash(parent,hash);
struct list_head *tmp;
spin_lock(
tmp = head->next;
for (;;) {
struct dentry * dentry = list_entry(tmp, struct dentry, d_hash);
if (tmp == head)
break;
tmp = tmp->next;
if (dentry->d_name.hash != hash)
continue;
if (dentry->d_parent != parent)
continue;
if (parent->d_op parent->d_op->d_compare) {
; 如果文件系统提供了目录名比较的方法
if (parent->d_op->d_compare(parent, name))
continue;
} else {
if (dentry->d_name.len != len)
continue;
if (memcmp(dentry->d_name.name, str, len))
continue;
}
__dget_locked(dentry); 增加dentry的引用计数
dentry->d_flags |= DCACHE_REFERENCED;
spin_unlock(
return dentry;
}
spin_unlock(
return NULL;
)
java 解压ygb文件_文件系统-目录项缓存与散列表相关推荐
- Java解压Jar文件
今天写点java解压jar文件的东西,以前项目中用到过,很简单... java中有专门的文件类型对应jar文件,那就是JarFile,用于从任何可以使用java.io.RandomAccessFile ...
- java 解压tgz文件
java 解压tgz文件 pom 引入依赖 <dependency><groupId>org.apache.commons</groupId><artifac ...
- tar解压单个文件到特定目录_技术|如何解压 tar 文件到不同的目录中
我想要解压一个tar文件到一个叫/tmp/data的指定目录.我该如何在Linux或者类Unix的系统中使用tar命令解压一个tar文件到不同的目录中? 你不必使用cd命令切换到其他的目录并解压.可以 ...
- Java解压zip文件(文本)压缩包
2019独角兽企业重金招聘Python工程师标准>>> 说明:由于我们的日志收集到指定服务器上,会按天压缩成一个zip格式的压缩包,但是有时候需要对这些日志进行处理,人工解压在处理, ...
- java解压zip文件
package com.chuangqi.tools;import org.apache.tools.zip.ZipEntry; import org.apache.tools.zip.ZipFile ...
- java解压gz文件
http://panshaobinsb.iteye.com/blog/1566231 下面是网上的代码 http://www.iteye.com/topic/894879 Java代码 impor ...
- 用Java解压lz文件
可以使用 Apache Commons Compress 库来解压 lz 文件. 首先,需要在项目中导入这个库,可以使用 Maven 或者 Gradle 进行依赖管理. 然后,可以使用以下代码来解压 ...
- mac 命令行 解压7z文件_如何在Mac上快速压缩和解压文件?Mac上解压和压缩文件的方法...
苹果mac电脑怎么压缩和解压文件?Mac电脑仅默认支持把文件压缩成zip格式,解压成zip.tar.gz,bz2等格式,有些操作需要安装第三方软件来完成,这篇文章为大家带来几种关于在Mac上解压和压缩 ...
- java解压zip文件,处理文件名不能为中文
1.最近工作需要把压缩文件解压,经过测试有两种方法,一种是JDK自带的ZipFile, 另外一种是org.apache.tools.zip进行解压. 2.经测试,JDK自带的文件不能处理文 ...
- 你知道为什么手机qq解压压缩包文件会出现0项吗??
常见的压缩包格式有两种:zip和rar,而我们手机qq上自带的解压软件目前只支持zip,而rar是有专利的,不会集成在任何系统上,这就需要我们去下载第三方软件来解压. 注: (但是有时候我们会发现qq ...
最新文章
- SQL 查询总是先执行SELECT语句吗?你们都错了!
- 杭电oj2035c语言答案,杭电oj 2035
- php 百度逆地理编码,百度逆地址解析
- 通过MATLAB将数据转化为mif文件,供Quartusii软件的ROM核读取调用
- TalkingData大规模机器学习的应用
- 前端基础21:正则基础
- boost::variant2模块实现默认构造相关的测试程序
- 如何处理错误消息Unable to install breakpoint due to missing line number attributes
- 深度思考的能力,决定了你能走多远
- 微服务跨数据库联合查询_数据库跨库查询
- idea2017+kemulator搭建J2ME开发环境
- Web前端:木兰花令网页案例设计
- vue3中导出excel表格
- Flink 的状态保存和恢复
- 附近的人实现(Redis 3.2 以上版本和es 性能比较)
- 微博html5版登录,新浪微博模拟登录 支持手动处理验证码
- Fitbit协助执法部门破获一起犯罪案件
- opencv接口那些不为人知的事!
- 求数组中最长递增子序列
- uni-app学习(一)
热门文章
- 【路径规划】基于matlab HybridA_Star算法机器人路径规划【含Matlab源码 1390期】
- 【数字信号】基于matlab GUI简易电子琴(英文版)【含Matlab源码 873期】
- 【数学建模】基于matlab计划生育政策调整对人口数量、结构及其影响的研究【含Matlab源码 749期】
- 【图像融合】基于matlab PCA图像融合【含Matlab源码 723期】
- 【优化算法】多目标粒子群优化算法(MOPSO)【含Matlab源码 033期】
- 【图像增强】基于matlab区域相似变换函数和蜻蜓算法灰度图像增强【含Matlab源码 089期】
- b站 前端构架_技术干货:哔哩哔哩(B站)功能框架图
- 数据库的根据当前id查询所有父级菜单
- 例2.3 日期差值 - 九度教程第6题(日期类问题)
- data标签怎么爬虫_scrapy爬虫笔记(1):scrapy基本使用