Linux中的缓冲区和缓存内存有什么区别

Linux中的缓冲区和缓存内存有什么区别,第1张

缓冲区与特定的块设备相关联,包括文件系统元数据的缓存以及页面跟踪。缓存只包含已停放的文件数据。

也就是说,缓冲区记住目录中的内容、文件权限是什么,并跟踪从某个块设备中写入或读取到哪些内存。

缓存只包含文件本身的内容。

一个缓冲头结构中标志了对应缓冲块的相关性质,采用缓冲头结构组来对整个缓冲区的缓冲块进行管理, *** 作方便。在缓冲区中,低端存储区存放的是对应缓冲头结构,高端区对应的是缓冲区数据结构,这是在进行缓冲区初始化过程中,初始化程序从整个缓冲区的两端开始,分别同时设置缓冲区头结构和对应的缓冲区。即第一个缓冲区头结构所对应的是最后一个缓冲数据块,如此递推下去。(缓冲块是1024个字节的块)

缓冲头结构的结构分析:

设备号、块号、状态(含有当前缓冲区状态)以及其他一些算法所需要的数据。

高速缓冲块采用hash表和包含所有缓冲区块的链表来进行管理 *** 作。

1块缓冲区即1024个字节,低端(对应各缓冲块的缓冲头结构)分别建立起对应各缓冲块的缓冲头结构buffer_head,这些缓冲头连接成链表,从而对整个缓冲区进行 *** 控。

下面这个是linux0.11内核中所定义的缓冲区头结构:

struct buffer_header{

char *b_data

unsigned short b_dev

unsigned char b_uptodate

unsigned char b_dirt

unsigned chart b_count

unsigned char b_lock

struct task_struct * b_wait

struct buffer_head *b_prev

struct buffer_head *b_next

struct buffer_head *b_prev_free

struct buffer_head *b_next_free

}

(我们所研究的缓冲区是磁盘块在主存中的拷贝,一个缓冲区的数据与文件系统上一个逻辑磁盘块中的数据想对应,并且内核是通过考察缓冲区头部中的标识字符来识别缓冲区内容的。缓冲区的内容并不是永久存在的,而是每隔一定时间间断就会发生更新的区域。)

b_block锁定标志,表示驱动程序正在对该缓冲区内容进行 *** 作,此时该缓冲区不能被第二者访问。这里可以发现,对缓冲区的直接 *** 作是驱动程序,而不是应用程序,应用程序通过调用系统调用来对缓冲区进行相应的 *** 作。

思考:向缓冲块中写数据的写 *** 作不由CPU控制,CPU起到 的只是控制管理功能而已。而缓冲块中写数据写 *** 作则是由硬件来完成,如何为完成???

b_count缓冲buffer使用之计数值,表示相应缓冲块正被各个进程使用的次数,主要用于对缓冲块的程序引用计数管理,所谓空闲块指b_count=0的块。

b_update是数据更新标志,说明缓冲块中数据是否有效。b_dirt和b_update标志的应用是很重要的,同时一很容易弄混淆,b_dirt所起到的作用是当缓冲区中的数据被改变时,相应的b_dir被赋值为1,表明此时缓冲区中的数据与磁盘块中的数据是不同的,这就意味着磁盘中的数据需要重新写,即更新,所使用的是延迟写。而b_update说明缓冲块中的数据是否有效。当我们将释放块时,这两个值被赋为0,表明该缓冲区中的数据无效,这里的释放块指的是将缓冲区的数据进行了释放更新,缓冲区中的数据已经不再被当前进程使用,而磁盘中的数据并没有丢失,只是缓冲区中的数据丢失了而已。当b_dir比指明为1时,用通俗的话说这个块脏了,需要将其中的内容写入磁盘块中,但是此时还没有将其放入到磁盘中,所以数据是无效的。只有当数据被写入到磁盘设备或者是从块设备中读入缓冲块时,数据才是变为有效的。

接下来,来看看缓冲头结构buffer_head结构中字段类型为buffer_head的几个字段的用法,下面这个函数是从linux0.11内核代码中摘录下来的,主要是使用了buffer_head这几个字段来进行 *** 作,很容易理解:

函数的功能是:将缓冲块插入空闲链表尾部,同时放入hash队列中。

static inline void insert_info_queues(struct buffer_head * bh)

{

bh->b_next_free=free_list//将bh指向的下一个节点指定为free_list,即空闲表的头指针;

bh->b_prev_free=free_list->b_prev_free//将bh的后指针指向为之前空闲表的最后一个节点;

free_list->b_prev_free->b_next_free=bh

free_list->b_prev_free=bh

bh->b_prev=NULL

bh->b_next=NULL

if(!bh->b_dev)

return

bh->b_next=hash(bh->b_dev,bh->b_blocknr)

hash(bh->b_dev,bh->b_blocknr)=bh

bh->b_next->b_prev=bh

}

以上的代码程序就是对buffer_head中buffer_head字段的使用,这就是这些字段作用之一,有趣吧!

现在来分析缓冲区所使用的两个数据结构:散列表和空闲表。

缓冲区中的所有块是通过散列表进行管理和 *** 作的,对于磁盘而言,如果要使用散列表来进行管理,其散列表是不变的。但是,高速缓冲区中的散列表是变化着的。散列表的控制 *** 作是由对应的散列函数进行实施的。要注意的是,缓冲块所存在的散列表并不是规定的,可以结合实际来安排,当然,系统所追求的是一种均衡的分配方式,这样做只是为了更好地对缓冲块进行管理,同时效率也是很高的!

一个缓冲块可以存在于两个链表中:散列表或者是空闲表。如果我们需要寻找一个特定的缓冲块,我们可以在散列表中寻找,举个例子:在一个 *** 作系统中,有多个进程在执行着,现在进程1在使用一个缓冲块,此时进程2也需要访问相应的块,那么进程2就会在散列表中进行寻找,而不是到空闲表中寻找。

而buffer_head结构的字段:b_next、b_prev、b_prev_free、b_next_free就是用来对散列表和空闲表进行 *** 作的。

这仅仅是对缓冲区头结构进行的一个简单的学习总结,还有相应算法会频繁使用到这些字段,相应的总结将在后面的总结中列出。

如果相对高速缓冲有更直接的认识,了解内存结构是很有好处的,所以,要把内存管理弄明白。呵呵!

帧缓冲(framebuffer)是 Linux 为显示设备提供的一个接口,把显存抽象后的一种设备,他允许上层应用程序在图形模式下直接对显示缓冲区进行读写 *** 作。这种 *** 作是抽象的,统一的。用户不必关心物理显存的位置、换页机制等等具体细节。这些都是由Framebuffer 设备驱动来完成的。帧缓冲驱动的应用广泛,在 linux 的桌面系统中,Xwindow 服务器就是利用帧缓冲进行窗口的绘制。尤其是通过帧缓冲可显示汉字点阵,成为 Linux汉化的唯一可行方案。

帧缓冲设备对应的设备文件为/dev/fb*,如果系统有多个显示卡,Linux 下还可支持多个帧缓冲设备,最多可达 32个,分别为/dev/fb0 到/dev/fb31,而/dev/fb 则为当前缺省的帧缓冲设备,通常指向/dev/fb0。当然在嵌入式系统中支持一个显示设备就够了。帧缓冲设备为标准字符设备,主设备号为29,次设备号则从0到31。分别对应/dev/fb0-/dev/fb31。

通过/dev/fb,应用程序的 *** 作主要有这几种:

1.读/写(read/write)/dev/fb:相当于读/写屏幕缓冲区。例如用 cp /dev/fb0 tmp 命令可将当前屏幕的内容拷贝到一个文件中,而命令 cp tmp >/dev/fb0 则将图形文件tmp显示在屏幕上。

2.映射(map) *** 作:由于 Linux工作在保护模式,每个应用程序都有自己的虚拟地址空间,在应用程序中是不能直接访问物理缓冲区地址的。为此,Linux 在文件 *** 作file_operations 结构中提供了 mmap函数,可将文件的内容映射到用户空间。对于帧缓冲设备,则可通过映射 *** 作,可将屏幕缓冲区的物理地址映射到用户空间的一段虚拟地址中,之后用户就可以通过读写这段虚拟地址访问屏幕缓冲区,在屏幕上绘图了。

3.I/O控制:对于帧缓冲设备,对设备文件的 ioctl *** 作可读取/设置显示设备及屏幕的参数,如分辨率,显示颜色数,屏幕大小等等。ioctl 的 *** 作是由底层的驱动程序来完成的。

在应用程序中, *** 作/dev/fb的一般步骤如下:

1.打开/dev/fb设备文件。

2.用 ioctrl *** 作取得当前显示屏幕的参数,如屏幕分辨率,每个像素点的比特数。根据屏幕参数可计算屏幕缓冲区的大小。

3.将屏幕缓冲区映射到用户空间(mmap)。

4.映射后就可以直接读写屏幕缓冲区,进行绘图和图片显示了。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/8903736.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-22
下一篇 2023-04-22

发表评论

登录后才能评论

评论列表(0条)

保存