(转)Linux中的位图
原文:https://www.jianshu.com/p/74626c2d2916
什么是位图
位图(bitmap)的定义
- 维基百科中关于位图的介绍:
一种数据结构,代表了有限域中的稠集(dense set),每一个元素至少出现一次,没有其他的数据和元素相关联。在索引、数据压缩等方面有广泛应用。
- 自己的理解
位图就是按位(bit)来记录、索引某个对象状态的图表(map),即用每一位(bit)来存放每一个对象的某种状态(例如分别用0和1表示的话,可以表示同一对象的两种状态)。
这在数据规模大、而数据状态又不是很多的情况下,用来索引判断某个数据的状态(如存不存在、有没有被使用等)很方便。
Linux内核中的位图
位图接口的声明
位图在Linux内核中被大量使用。下面的源代码文件包含这些位图结构的通用接口:
- lib/bitmap.c
- include/linux/bitmap.h
除了这两个文件,还有一个特定的架构头文件,对特定架构的位运算进行优化。对于x86_64架构,使用下面头文件:
- arch/x86/include/asm/bitops.h
在Linux内核中,位图是一个unsigned long
类型的数组。因此,一个位图可以简单地声明为:
unsigned long my_bitmap[16]; /* 声明一个16比特的位图 */
它就像这个样子:
将数据【5,1,7,15,0,4,6,10】存入后,结构变为:
实际上,在Linux内核中有一个专门的DECLARE_BITMAP
宏来声明位图(该宏位于头文件include/linux/types.h
中):
#define DECLARE_BITMAP(name,bits)
unsigned long name[BITS_TO_LONGS(bits)]
其中,参数name
是位图的名字,bits
是位图中比特的总数目。
Linux内核源码中对位图的介绍:
19 /*
20 * bitmaps provide an array of bits, implemented using an an
21 * array of unsigned longs. The number of valid bits in a
22 * given bitmap does _not_ need to be an exact multiple of
23 * BITS_PER_LONG.
24 *
25 * The possible unused bits in the last, partially used word
26 * of a bitmap are 'don't care'. The implementation makes
27 * no particular effort to keep them zero. It ensures that
28 * their value will not affect the results of any operation.
29 * The bitmap operations that return Boolean (bitmap_empty,
30 * for example) or scalar (bitmap_weight, for example) results
31 * carefully filter out these unused bits from impacting their
32 * results.
33 *
34 * These operations actually hold to a slightly stronger rule:
35 * if you don't input any bitmaps to these ops that have some
36 * unused bits set, then they won't output any set unused bits
37 * in output bitmaps.
38 *
39 * The byte ordering of bitmaps is more natural on little
40 * endian architectures. See the big-endian headers
41 * include/asm-ppc64/bitops.h and include/asm-s390/bitops.h
42 * for the best explanations of this ordering.
43 */
位图的两个重要操作
置位(set bit)和清零(clear bit)是位图的两种重要的操作,在头文件arch/x86/include/asm/bitops.h
实现了这些操作。在这两类操作中,每个函数分两种类型:原子类型和非原子类型。非原子类型的实现比较简单,介绍如下:
置位操作
/**
* __set_bit - Set a bit in memory
* @nr: the bit to set (位图中的比特数目)
* @addr: the address to start counting from (位图中某个比特需要设值的地址)
*
* Unlike set_bit(), this function is non-atomic and may be reordered.
* If it's called on the same region of memory simultaneously, the effect
* may be that only one operation succeeds.
*/
static inline void __set_bit(long nr, volatile unsigned long *addr)
{
asm volatile("bts %1,%0" : ADDR : "Ir" (nr) : "memory");
}
在该函数中,指令bts
用来选择位图中的某个比特值 来作为首个操作数,然后将已选择的比特值 存入寄存器CF标签中,并设置此比特位。
清零操作
static inline void __clear_bit(long nr, volatile unsigned long *addr)
{
asm volatile("btr %1,%0" : ADDR : "Ir" (nr));
}
该函数用来清除某个地址的某个比特值。
指令btr
与指令bts
类似,选择某个比特值作为首个操作数,然后将其值存入寄存器CF标签中,并清除位图中的这个比特值,并且将位图作为指令的第二个操作数。
位图在Ext2文件系统中的应用
Ext2文件系统结构图示意如下:
在Ext2文件系统中,采用了位图来存储信息的结构有:
- 组描述符表(GDT,Group Descriptor Table,可用
df
命令查看) - 块位图(Block Bitmap)
- inode位图(inode Bitmap)
各项具体含义参考文章
查找文件流程
以查找/home/slot
目录下的文件myfile
为例,该文件的完整路径就是/home/slot/myfile
,系统首先从根目录/
开始查找,根目录/
的inode编号固定为2
:
在根目录/
下的目录项中查找名字为home
的目录:
实际上目录文件的结构非常简单,就是一系列目录项(dirent)的列表。每个目录项由以下几部分组成:
- 所包含文件的文件名;
- 文件名对应的inode编号;
- 文件类型;
- 记录长度。
接下来根据文件名找到其对应的inode编号:
(同理依次找到目录slot
下文件myfile
的inode编号。)
再接下来,根据inode编号
,查看inode table
,找到具体的inode,inode中记录了两类信息:
- 文件属性;
- 文件指针。
其中,文件指针指向磁盘上的数据块(data block),文件的具体信息就存储在这些block上。所以,最终根据这些文件指针找到文件内容。
注意:
最后三个文件指针都是间接指针,指向间接寻址块(Indirect Block)(一级、二级、三级间接寻址),而非数据块。
整个流程如下图所示:
删除文件流程
当使用命令 rm filename
删除一个文件时,系统实际上是删除了其inode编号,具体是每调用一次 rm filename
命令,就将filename对应的inode编号的硬连接数减一(并删除相应目录下的目录项),当硬连接数减为0时系统才释放该inode编号,以待分配给其它新的文件使用。
系统每次分配inode编号,是从所有可用的inode编号中选择最小的那个。
当然,在删除inode编号之前,系统要先释放数据块(即将bitmap中对应的位清零)。
所以,使用rm命令实际上只是删除了文件的inode编号(这也是为什么一般删除操作都很快),而文件数据仍然存放在磁盘上,只是无法再查看到。因此,只要找到文件对应的inode信息,就可以将文件内容恢复出来(前提是这些数据block没有被后来的其它数据所覆盖。所以在误删文件后,应立即停止所有写操作,以防止原有数据被覆盖)。
(转)Linux中的位图的更多相关文章
- Linux中的磁盘
Linux的磁盘管理 (很重要请注意高能预警) 硬盘:几个盘片,双面,磁性颗粒, 处理速率不同步:借助于一个中间层 文件系统(FileSystem) 可以实现对磁盘行的文件进行读写 文 ...
- 浅析linux中的fork、vfork和clone
各种大神的混合,做个笔记. http://blog.sina.com.cn/s/blog_7598036901019fcg.html http://blog.csdn.net/kennyrose/ar ...
- [GUI] Linux中的图形管理
转:http://www.cnblogs.com/yongpenghan/p/4555619.html 做了一段时间linux下与QT事件相关的工作,经常会遇到X11,总是苦于无法完全理解其与linu ...
- SQLSERVER中NULL位图的作用
SQLSERVER中NULL位图的作用 首先感谢宋沄剑提供的文章和sqlskill网站:www.sqlskills.com,看下面文章之前请先看一下下面两篇文章 SQL Server误区30日谈-Da ...
- 在 Linux 中安装 Oracle JDK 8 以及 JVM 的类加载机制
参考资料 该文中的内容来源于 Oracle 的官方文档 Java SE Tools Reference .Oracle 在 Java 方面的文档是非常完善的.对 Java 8 感兴趣的朋友,可以直接找 ...
- Linux中find常见用法示例
·find path -option [ -print ] [ -exec -ok command ] {} \; find命令的参数: pathname: find命 ...
- Linux中检索文件
1 , Use locate command It is a fast way to find the files location, but if a file just created ,it w ...
- 如何在Linux中搭建禅道8.4.1(httpd+php+mysql)
1.安装httpd 命令:yum install httpd 然后一路y即可 2.安装php 命令:yum install php 3.安装php-mysql 命令:yum install php ...
- Linux中的用户和用户组
在Linux中,有三种用户: Root 用户:也称为超级用户,对系统拥有完全的控制权限.超级用户可以不受限制的运行任何命令.Root 用户可以看做是系统管理员. 系统用户:系统用户是Linux运行 ...
随机推荐
- hfs快速搭建HTTP文件服务器
HFS全称为http file server,他是一个专门实现文件共享的工具,通过WWW服务将要共享的目录或文件发布,从而让需要下载者直接通过IE浏览器访问发布的这个共享站点,然后随意下载共享资源.和 ...
- gj10 python socket编程
10.1 HTTP.Socket.TCP这几个概念 五层网络模型 socket 不属于任何协议,是一个API,通过socket 可以和传输层的打交道,然后在之上可以实现自己的功能和协议 10.2 cl ...
- VMware + LInux + Xshell 连接环境设置(心得体会)
准备好VMware软件,和Linux 和xshell三款软件,下载和安装好,这里VMware是十二,Linux是CentOs 6 ,xshell是5 其实没有什么区别只要版本兼容就行,我们就可以实现远 ...
- (KMP 根据循环节来计算)Period -- hdu -- 1358
http://acm.hdu.edu.cn/showproblem.php?pid=1358 Period Time Limit: 2000/1000 MS (Java/Others) Memo ...
- Scala包和引用
1.包 Scala包的命名方式有两种.一种和Java一样,通过把package子句放在文件顶端的方式,把整个文件的内容放进包里.如: package scala.actors.Actor 另一种方式可 ...
- 我的成长比价系列:java web开发过程中遇到的错误一:sql语句换行错误
字符串换行导致的错误,确切的说是马虎的错误,自己在编写简单的servlet项目时,在StudentDao.java 中的 查询语句:String sql= "SELECT Type,fl ...
- [翻译] Virtual method interception 虚方法拦截
原文地址:http://blog.barrkel.com/2010/09/virtual-method-interception.html 注:基于本人英文水平,以下翻译只是我自己的理解,如对读者造成 ...
- Nodejs-- web服务器
第一篇关于nodejs的东西,代码在此作为备份. 该代码目前未完成,是一个阻塞式的代码. 1.index.js ar server=require('./server'); var route=req ...
- wpf使用DynamicDataDisplay插件,修改x轴的样式,改成透明的。
时光偷走的,永远都是我们眼皮底下看不见的珍贵. 问题:X轴会显示灰色拖动条. 解决:将X轴颜色改为透明. DDD插件是开源的,但是网上的参考资料却很少,所以,很多问题在网上搜索不到,因为没有找到该插件 ...
- Asp.Net从相对路径获取绝对路径的方法(不需要httpcontext上下文也可)
//如果拿不到当前HttpContext上下文的话可以用该方法取得绝对路径 var filePath = HostingEnvironment.MapPath("需要获取绝对路径 的 相对路 ...