- 浏览: 304202 次
- 性别:
- 来自: 大连
文章分类
最新评论
-
syw19901001:
从入门到精通,不错。http://www.ihref.com/ ...
使用git进行版本控制 -
轻指飞扬:
...
一场程序员和老板的对话 -
luogen33:
ttttttttttttttttttttttttttttttt ...
lsmod -
luogen33:
ttttttttttttttttttt
lsmod -
vaqeteart:
嗯那
得到与享受
关于存储管理中的一些概念
前言
在编写程序的时候,在学习操作系统以及编写驱动的时候,尤其是在Linux内核空间中编程的时候,经常会被一些与存储相关的概念所困扰,而这也经常是我们程序出现错误概率很大的一个原因(指针相关的错误)。
我们经常遇到的问题,例如:什么是页?什么是段?什么是扇区?什么是块?什么是簇?什么是磁道?什么是物理地址?什么是线性地址?什么是虚拟地址?什么是逻辑地址?它们之间究竟有什么关系?……这些问题,这里暂时归结为存储管理中涉及到的问题,而存储管理,又可分为内存管理,外存管理。本文通过对外存、内存的管理的简单叙述,尝试达到理清对这些概念以及它们之间的关系的简单理解。更为具体的内容,可以参见列出的参考资料,或者其他更好的资料。
主要内容:
一、非易失存储(例如磁盘)的管理
二、易失性存储(例如内存)的管理
三、其他
一、非易失存储(例如磁盘)的管理
===========================================
1、关于磁盘物理结构与寻址
关键之处在于关于磁盘物理结构,首先理解了磁盘的柱面(磁道),扇区,以及盘面之后,再知道如下信息,就掌握了关于磁盘寻址基本的知识。
传统的大致情况就是,一个盘面上面有多个磁道(每个磁道就是一圈,这些磁道组成盘面上的同心圆),一个磁道上面有多个扇区(就是一个同心圆上面的一个弧线部分,每个扇区实际物理大小和硬件相关,但是内核内部默认和驱动交互时候采用扇区是512字节的逻辑扇区,所以物理扇区一定是512字节的整数倍),而多个盘片上的同一位置的磁道组成的圆柱就是柱面。综上,寻址磁盘,可以通过“(盘片,磁道,扇区)”达到目的,而这样的磁盘的大小为:盘片数*每盘片上的磁道数*每磁道上的扇区数*每扇区的字节数。
另外,磁盘的分区是以磁道为边界的,所以如果只有2个磁道,因此最多只能创建2个分区。
传统的磁盘使用8个位表示盘面数、6个位表示每磁道扇区数、10个位表示磁道数,因此盘面、每磁道扇区、磁道的最大数值分别为255、63和1023。这也是传说中启动操作系统时的1024柱面(磁道)和硬盘容量8G限制的根源。
现代磁盘采用线性寻址方式突破了这一限制,从本质上说,如果你的机器还没生锈,那么你的硬盘无论是内部结构还是访问方式都与常识中的盘面、每磁道扇区、磁道无关。但为了与原先的理解兼容,对于现代磁盘,我们在访问时还是假设它具有传统的结构。目前比较通用的假设是:所有磁盘具有最大数目的(也就是恒定的)盘面和每磁道扇区数,而磁盘大小与磁道数与成正比。
因此,对于一块80G的硬盘,根据假设,这块磁盘的盘面和每磁道扇区数肯定是255和63,磁道数为:80*1024*1024*1024/512(字节每扇区)/255(盘面数)/63(每磁道扇区数)=10043(小数部分看作不完整的磁道被丢弃)。 假设写磁盘驱动程序中我们指定了磁盘大小为16M,共包含16*1024*1024/512=32768个扇区。假设这块磁盘具有最大盘面和每磁道扇区数后,那么它的磁道数就是:32768/255/63=2。
2、关于扇区(sector)、块(block)和簇(cluster)
扇区是硬件的磁盘的最小存储单位,而块是文件系统中数据存储的最小单元。这里,文件系统是用来规范数据文件在磁盘上以什么方式进行存储的,以便操作系统可以通过文件系统中定义好的规范,访问到磁盘上的文件。
一个磁盘扇区一般512个字节(现在有4K的了), 磁盘块应该是类似FAT的簇大小的概念,是操作系统中分配磁盘容量的最小单位了,一般是512B*2^n。扇区是硬件上的单位,块一般是针对上层的,块一般要比扇区大。有些地方的说法,块和扇区都无什么区别了,关心逻辑和物理的就行了。也就是说,设备驱动的相关结构中,有两个地方,一个表示物理的扇区,一个表示逻辑扇区;物理的扇区就是实际物理扇区的大小,为512字节的整数倍;而逻辑扇区,就是512字节,操作系统认为所有扇区就是512字节,使用统一的逻辑扇区大小做为操作单位,和驱动进行交互,简化了写驱动的繁琐;而具体内部是如何转化两者之间关系的,写驱动的时候不用关心,我们只要告诉物理扇区大小,逻辑扇区大小,然后在驱动里面使用逻辑扇区(512字节)就行了。
而对于簇,在fat文件系统中,fat上面簇是多个磁道,当然不同的文件系统有所不同。
二、易失性存储(例如内存)的管理
===========================================
1、关于实模式和保护模式
说到内存管理,就不能不提到实模式和保护模式。处理器的两种工作方式:保护模式和实模式。早期的dos就是运行在实模式下,而现在的windows则运行在保护模式下。实模式使用的逻辑地址直接转换成物理地址,只能访问1M多一点的内存空间,在拥有32根地址线的cpu中访问1M以上的空间则变得很困难。为了满足计算机对资源(存储资源和cpu资源等等)的管理,由此产生了新的管理方式--保护模式。
80386及以上的处理器功能要大大超过其先前的处理器,但只有在保护模式下,处理器才能发挥作用。在保护模式下,全部32根地址线有效,可寻址4G的物理地址空间;扩充的存储分段机制和可选的存储器分页机制,不仅为存储器共享和保护提供了硬件支持,而且为实现虚拟存储器提供了硬件支持;支持多任务;4个特权级和完善的特权级检查机制,实现了数据的安全和保密。计算机启动后首先进入的就是实模式,通过设置相应的寄存器才能进入保护模式。
2、关于页(page)和段(segment)
和扇区和块等一般是针对于非易失存储介质(如磁盘)不同,段和页的概念一般是对于易失性存储而言的。也就是主要体现在内存访问方式上的存储方式。从逻辑地址到线性地址的转换由80386分段机制管理,分页机制是在段机制之后进行的,它进一步将线性地址转换为物理地址。
(1)段是信息的逻辑单位。
分段的作业地址空间是二维的,程序员在标识一个地址时,既需给出段名,又需给出段内地址。细言之:段式 分段由用户设计划分,每段对应一个相应的的程序模块,有完整的逻辑意义。分段的目的是为了能更好的满足用户的需要。
(2)页是信息的物理单位。
分页的作业地址空间是维一的,即单一的线性空间,程序员只须利用一个记忆符,即可表示一地址。分页的目的是为实现离散分配方式,以消减内存的外零头,提高内存的利用率;或者说,分页仅仅是由于系统管理的需要,而不是用户的需要。
(3)页和段的大小。
页的大小固定且由系统确定,把逻辑地址划分为页号和页内地址两部分,是由机器硬件实现的,因而一个系统只能有一种大小的页面。段的长度却不固定,决定于用户所编写的程序,通常由编辑程序在对源程序进行编辑时,根据信息的性质来划分。
3、分页机制和分段机制
处理器在得到逻辑地址后首先通过分段机制转换为线性地址,线性地址再通过分页机制转换为物理地址最后读取数据。分段机制是必须的,分页机制是可选的,当不使用分页的时候线性地址将直接映射为物理地址,设立分页机制的目的主要是为了实现虚拟存储。
4、分段机制和逻辑地址
分段机制中,将逻辑地址转换成线性地址的细节就省略了,总的思想就是首先通过段选择子在描述符表中找到相应段的描述符,根据描述符中的段基址首先确定段的位置,再通过OFFSET加上段基址计算出线性地址。进一步解释,一个任务会涉及多个段(代码段,数据段……),每个段需要一个描述符来描述,为了便于组织管理,80386及以后处理器把描述符组织成表,即描述符表。逻辑地址结构形式一般为:"seg:offset"形式,用描述表中记录的段基址加上逻辑地址“sel:offset“中的“offset“部分,即转换成线性地址。
5、分页机制和线性地址
通过分段机制,将逻辑地址转换成的线性地址,简单的说就是0000000h~ffffffffh(即0~4G)的线性结构,是32个bite位能表示的一段连续的地址,但它是一个概念上的、抽象的地址,并不存在在现实之中。线性地址地址主要是为分页机制而产生的。
分页机制是在段机制之后进行的,它进一步将线性地址转换为物理地址。80386使用4K字节大小的页,且每页的起始地址都被4K整除;因此,80386把4GB字节的“线性地址”空间划分为1M个页面,采用了两级页表结构进行转换。具体转换过程也省略了,大致如下:
(1)第一级表称为页目录,存储在一个4K字节的页中,每个表项为4个字节,线性地址最高的10位(22-31)对第一级表进行索引,索引得到的表项内容定位了二级表中的一个表的地址(即下级页表所在的内存块号)。
(2)第二级表称为页表,存储在一个4K字节页中,包含了1K字节的表项,线性地址的中间10位(12-21)位对二级页表进行索引,索引得到的表项包含了一个页的物理地址。
(3)页物理地址的高20位与线性地址的低12位形成最后的物理地址。
6、Linux内核中的内存管理
在Linux内核中,内存分为内核空间和用户空间。
(1)用户空间
在Linux中,每个用户进程都可以访问4GB的线性虚拟内存空间。其中从0到3GB的虚存地址是用户空间,用户进程可以直接访问。
(2)内核空间
从3GB到4GB的虚存地址为内核态空间,存放供内核访问的代码和数据,用户态进程不能访问。所有进程从3GB到4GB的虚拟空间都是一样的,linux以此方式让内核态进程共享代码段和数据段。
(3)内核虚拟地址,用户空间虚拟地址
这里的虚拟地址,实际上就是分页机制用来转化成物理地址的线性地址。讲述这里的时候,使用下面三个地址描述内存:
(a)物理地址(phyaddr):对应真实的内存.
(b)内核虚拟地址(kervir):内核的虚地址空间(3g-4g),例如_get_free_pages等就是从这里分配。
(c)用户虚拟地址(usrvir):用户的虚拟空间地址(0g-3g).例如malloc等返回的就是这里的地址。
(4)内存地址空间之间的转换:
phyaddr<->kervir:有类似_pa, _va这样的宏。
kervir->usrvir:有类似remap_pfn_range这样的函数,一般在驱动里面调用,返回内核地址给用户空间。
phyaddr->usrvir:知道phyaddr的基地址,与usrvir的基地址,然后计算偏移量即可。
(5)关于分配内存:
(a)内核空间内存分配
_get_free_pages:连续物理地址,且连续最大页为2^PAGE_SHIFT*2^MAXORDER,宏可以配置。
kmalloc:连续物理地址,不过分配的空间太小了,只有128k,也有一个可以配置的宏。
vmalloc:分配的地址空间物理上不连续。
想要知道更具体的信息,内核源代码中的kmalloc.h/c, kmalloc_size.h/c, slab.h/c等文件会有助于了解。
(b)用户空间内存分配
malloc:从用户堆中动态分配内存。
三、其他
===========================================
这里,是一些补充性的内容。
1,块设备的bio
编写块设备驱动,最终用户请求的数据(读或者写)都会通过bio这个结构反应出来,也就是说,bio代表一次请求。这里就用到了page。对于page,一般各种cpu操作page的最小单位是4k,当然有的设成8k等,但是最小是4k。
当块设备请求到来的时候,会为用户请求数据分配一块虚拟地址,存放在请求结构(request)中的bio结构中,而bio结构中的bi_io_vec数组存放实际的数据。数组元素为:
struct bio_vec
{
struct page* bv_page;
unsigned int bv_len;
unsigned int bv_offset;
}
实际上,分配给用户请求数据的虚拟地址不一定以page进行对齐,所以要对其align,如下:
|--###|#####|#####|##---|
这里,分配了4个页给用户请求数据,这四个页都存放在一个bio_vec中的bv_page列表中。而由于需要align,所以'#'中的才是实际>的数据,而'-'的可能是别人的或者没有用的数据等。这里,bv_offset就是第一个bv_page中第一个'#'中的偏移,而bv_len就是从第1个'#'到最后一个'#'的长度。这一点要注意,不要从bv_page开始的页对应的虚拟地址访问page。
获取一个page对应的起始地址方式是使用page_address宏,这样返回page的起始地址,再加上bv_offset就得到整个bio结构中数据的
起始地址了。获取bio数据对应的虚拟地址的函数的实现就是如下:
//include/linux/bio.h
static inline void *bio_data(struct bio *bio)
{
if (bio->bi_vcnt)
return page_address(bio_page(bio)) + bio_offset(bio);
return NULL;
}
可知,通过bio_data就可以获得bio数据的虚拟地址了,通过内核代码发现,这个虚拟地址只是bio数据的当前vec索引地址,而不一>定是整个的。
2,通过io映射将外设映射到内存空间
我们使用ioremap来将外设的空间映射到内存空间,借以访问外设,而这里所映射得到的就是物理地址,物理地址是一个固定的常量>,而不是我们以为的随意的一个地址。
以上,是本人根据理解,综合所参考的资料,书上所学,以及工作时候的时间,所做的总结。尽量只用文字的形式描述,只通过文本文件便可以学习。如其中有不准或者更好的建议,可以联系我,谢谢!
参考资料:
http://bbs.chinaunix.net/thread-2017377-2-1.html
http://bbs.chinaunix.net/thread-2083672-1-1.html#
http://www.cnblogs.com/c1230v/articles/1432525.html
http://hi.baidu.com/jingxshi/blog/item/7056f612fdcead58f919b865.html
作者:QuietHeart
Email:quiet_heart000@126.com
日期:2011年11月17日
前言
在编写程序的时候,在学习操作系统以及编写驱动的时候,尤其是在Linux内核空间中编程的时候,经常会被一些与存储相关的概念所困扰,而这也经常是我们程序出现错误概率很大的一个原因(指针相关的错误)。
我们经常遇到的问题,例如:什么是页?什么是段?什么是扇区?什么是块?什么是簇?什么是磁道?什么是物理地址?什么是线性地址?什么是虚拟地址?什么是逻辑地址?它们之间究竟有什么关系?……这些问题,这里暂时归结为存储管理中涉及到的问题,而存储管理,又可分为内存管理,外存管理。本文通过对外存、内存的管理的简单叙述,尝试达到理清对这些概念以及它们之间的关系的简单理解。更为具体的内容,可以参见列出的参考资料,或者其他更好的资料。
主要内容:
一、非易失存储(例如磁盘)的管理
二、易失性存储(例如内存)的管理
三、其他
一、非易失存储(例如磁盘)的管理
===========================================
1、关于磁盘物理结构与寻址
关键之处在于关于磁盘物理结构,首先理解了磁盘的柱面(磁道),扇区,以及盘面之后,再知道如下信息,就掌握了关于磁盘寻址基本的知识。
传统的大致情况就是,一个盘面上面有多个磁道(每个磁道就是一圈,这些磁道组成盘面上的同心圆),一个磁道上面有多个扇区(就是一个同心圆上面的一个弧线部分,每个扇区实际物理大小和硬件相关,但是内核内部默认和驱动交互时候采用扇区是512字节的逻辑扇区,所以物理扇区一定是512字节的整数倍),而多个盘片上的同一位置的磁道组成的圆柱就是柱面。综上,寻址磁盘,可以通过“(盘片,磁道,扇区)”达到目的,而这样的磁盘的大小为:盘片数*每盘片上的磁道数*每磁道上的扇区数*每扇区的字节数。
另外,磁盘的分区是以磁道为边界的,所以如果只有2个磁道,因此最多只能创建2个分区。
传统的磁盘使用8个位表示盘面数、6个位表示每磁道扇区数、10个位表示磁道数,因此盘面、每磁道扇区、磁道的最大数值分别为255、63和1023。这也是传说中启动操作系统时的1024柱面(磁道)和硬盘容量8G限制的根源。
现代磁盘采用线性寻址方式突破了这一限制,从本质上说,如果你的机器还没生锈,那么你的硬盘无论是内部结构还是访问方式都与常识中的盘面、每磁道扇区、磁道无关。但为了与原先的理解兼容,对于现代磁盘,我们在访问时还是假设它具有传统的结构。目前比较通用的假设是:所有磁盘具有最大数目的(也就是恒定的)盘面和每磁道扇区数,而磁盘大小与磁道数与成正比。
因此,对于一块80G的硬盘,根据假设,这块磁盘的盘面和每磁道扇区数肯定是255和63,磁道数为:80*1024*1024*1024/512(字节每扇区)/255(盘面数)/63(每磁道扇区数)=10043(小数部分看作不完整的磁道被丢弃)。 假设写磁盘驱动程序中我们指定了磁盘大小为16M,共包含16*1024*1024/512=32768个扇区。假设这块磁盘具有最大盘面和每磁道扇区数后,那么它的磁道数就是:32768/255/63=2。
2、关于扇区(sector)、块(block)和簇(cluster)
扇区是硬件的磁盘的最小存储单位,而块是文件系统中数据存储的最小单元。这里,文件系统是用来规范数据文件在磁盘上以什么方式进行存储的,以便操作系统可以通过文件系统中定义好的规范,访问到磁盘上的文件。
一个磁盘扇区一般512个字节(现在有4K的了), 磁盘块应该是类似FAT的簇大小的概念,是操作系统中分配磁盘容量的最小单位了,一般是512B*2^n。扇区是硬件上的单位,块一般是针对上层的,块一般要比扇区大。有些地方的说法,块和扇区都无什么区别了,关心逻辑和物理的就行了。也就是说,设备驱动的相关结构中,有两个地方,一个表示物理的扇区,一个表示逻辑扇区;物理的扇区就是实际物理扇区的大小,为512字节的整数倍;而逻辑扇区,就是512字节,操作系统认为所有扇区就是512字节,使用统一的逻辑扇区大小做为操作单位,和驱动进行交互,简化了写驱动的繁琐;而具体内部是如何转化两者之间关系的,写驱动的时候不用关心,我们只要告诉物理扇区大小,逻辑扇区大小,然后在驱动里面使用逻辑扇区(512字节)就行了。
而对于簇,在fat文件系统中,fat上面簇是多个磁道,当然不同的文件系统有所不同。
二、易失性存储(例如内存)的管理
===========================================
1、关于实模式和保护模式
说到内存管理,就不能不提到实模式和保护模式。处理器的两种工作方式:保护模式和实模式。早期的dos就是运行在实模式下,而现在的windows则运行在保护模式下。实模式使用的逻辑地址直接转换成物理地址,只能访问1M多一点的内存空间,在拥有32根地址线的cpu中访问1M以上的空间则变得很困难。为了满足计算机对资源(存储资源和cpu资源等等)的管理,由此产生了新的管理方式--保护模式。
80386及以上的处理器功能要大大超过其先前的处理器,但只有在保护模式下,处理器才能发挥作用。在保护模式下,全部32根地址线有效,可寻址4G的物理地址空间;扩充的存储分段机制和可选的存储器分页机制,不仅为存储器共享和保护提供了硬件支持,而且为实现虚拟存储器提供了硬件支持;支持多任务;4个特权级和完善的特权级检查机制,实现了数据的安全和保密。计算机启动后首先进入的就是实模式,通过设置相应的寄存器才能进入保护模式。
2、关于页(page)和段(segment)
和扇区和块等一般是针对于非易失存储介质(如磁盘)不同,段和页的概念一般是对于易失性存储而言的。也就是主要体现在内存访问方式上的存储方式。从逻辑地址到线性地址的转换由80386分段机制管理,分页机制是在段机制之后进行的,它进一步将线性地址转换为物理地址。
(1)段是信息的逻辑单位。
分段的作业地址空间是二维的,程序员在标识一个地址时,既需给出段名,又需给出段内地址。细言之:段式 分段由用户设计划分,每段对应一个相应的的程序模块,有完整的逻辑意义。分段的目的是为了能更好的满足用户的需要。
(2)页是信息的物理单位。
分页的作业地址空间是维一的,即单一的线性空间,程序员只须利用一个记忆符,即可表示一地址。分页的目的是为实现离散分配方式,以消减内存的外零头,提高内存的利用率;或者说,分页仅仅是由于系统管理的需要,而不是用户的需要。
(3)页和段的大小。
页的大小固定且由系统确定,把逻辑地址划分为页号和页内地址两部分,是由机器硬件实现的,因而一个系统只能有一种大小的页面。段的长度却不固定,决定于用户所编写的程序,通常由编辑程序在对源程序进行编辑时,根据信息的性质来划分。
3、分页机制和分段机制
处理器在得到逻辑地址后首先通过分段机制转换为线性地址,线性地址再通过分页机制转换为物理地址最后读取数据。分段机制是必须的,分页机制是可选的,当不使用分页的时候线性地址将直接映射为物理地址,设立分页机制的目的主要是为了实现虚拟存储。
4、分段机制和逻辑地址
分段机制中,将逻辑地址转换成线性地址的细节就省略了,总的思想就是首先通过段选择子在描述符表中找到相应段的描述符,根据描述符中的段基址首先确定段的位置,再通过OFFSET加上段基址计算出线性地址。进一步解释,一个任务会涉及多个段(代码段,数据段……),每个段需要一个描述符来描述,为了便于组织管理,80386及以后处理器把描述符组织成表,即描述符表。逻辑地址结构形式一般为:"seg:offset"形式,用描述表中记录的段基址加上逻辑地址“sel:offset“中的“offset“部分,即转换成线性地址。
5、分页机制和线性地址
通过分段机制,将逻辑地址转换成的线性地址,简单的说就是0000000h~ffffffffh(即0~4G)的线性结构,是32个bite位能表示的一段连续的地址,但它是一个概念上的、抽象的地址,并不存在在现实之中。线性地址地址主要是为分页机制而产生的。
分页机制是在段机制之后进行的,它进一步将线性地址转换为物理地址。80386使用4K字节大小的页,且每页的起始地址都被4K整除;因此,80386把4GB字节的“线性地址”空间划分为1M个页面,采用了两级页表结构进行转换。具体转换过程也省略了,大致如下:
(1)第一级表称为页目录,存储在一个4K字节的页中,每个表项为4个字节,线性地址最高的10位(22-31)对第一级表进行索引,索引得到的表项内容定位了二级表中的一个表的地址(即下级页表所在的内存块号)。
(2)第二级表称为页表,存储在一个4K字节页中,包含了1K字节的表项,线性地址的中间10位(12-21)位对二级页表进行索引,索引得到的表项包含了一个页的物理地址。
(3)页物理地址的高20位与线性地址的低12位形成最后的物理地址。
6、Linux内核中的内存管理
在Linux内核中,内存分为内核空间和用户空间。
(1)用户空间
在Linux中,每个用户进程都可以访问4GB的线性虚拟内存空间。其中从0到3GB的虚存地址是用户空间,用户进程可以直接访问。
(2)内核空间
从3GB到4GB的虚存地址为内核态空间,存放供内核访问的代码和数据,用户态进程不能访问。所有进程从3GB到4GB的虚拟空间都是一样的,linux以此方式让内核态进程共享代码段和数据段。
(3)内核虚拟地址,用户空间虚拟地址
这里的虚拟地址,实际上就是分页机制用来转化成物理地址的线性地址。讲述这里的时候,使用下面三个地址描述内存:
(a)物理地址(phyaddr):对应真实的内存.
(b)内核虚拟地址(kervir):内核的虚地址空间(3g-4g),例如_get_free_pages等就是从这里分配。
(c)用户虚拟地址(usrvir):用户的虚拟空间地址(0g-3g).例如malloc等返回的就是这里的地址。
(4)内存地址空间之间的转换:
phyaddr<->kervir:有类似_pa, _va这样的宏。
kervir->usrvir:有类似remap_pfn_range这样的函数,一般在驱动里面调用,返回内核地址给用户空间。
phyaddr->usrvir:知道phyaddr的基地址,与usrvir的基地址,然后计算偏移量即可。
(5)关于分配内存:
(a)内核空间内存分配
_get_free_pages:连续物理地址,且连续最大页为2^PAGE_SHIFT*2^MAXORDER,宏可以配置。
kmalloc:连续物理地址,不过分配的空间太小了,只有128k,也有一个可以配置的宏。
vmalloc:分配的地址空间物理上不连续。
想要知道更具体的信息,内核源代码中的kmalloc.h/c, kmalloc_size.h/c, slab.h/c等文件会有助于了解。
(b)用户空间内存分配
malloc:从用户堆中动态分配内存。
三、其他
===========================================
这里,是一些补充性的内容。
1,块设备的bio
编写块设备驱动,最终用户请求的数据(读或者写)都会通过bio这个结构反应出来,也就是说,bio代表一次请求。这里就用到了page。对于page,一般各种cpu操作page的最小单位是4k,当然有的设成8k等,但是最小是4k。
当块设备请求到来的时候,会为用户请求数据分配一块虚拟地址,存放在请求结构(request)中的bio结构中,而bio结构中的bi_io_vec数组存放实际的数据。数组元素为:
struct bio_vec
{
struct page* bv_page;
unsigned int bv_len;
unsigned int bv_offset;
}
实际上,分配给用户请求数据的虚拟地址不一定以page进行对齐,所以要对其align,如下:
|--###|#####|#####|##---|
这里,分配了4个页给用户请求数据,这四个页都存放在一个bio_vec中的bv_page列表中。而由于需要align,所以'#'中的才是实际>的数据,而'-'的可能是别人的或者没有用的数据等。这里,bv_offset就是第一个bv_page中第一个'#'中的偏移,而bv_len就是从第1个'#'到最后一个'#'的长度。这一点要注意,不要从bv_page开始的页对应的虚拟地址访问page。
获取一个page对应的起始地址方式是使用page_address宏,这样返回page的起始地址,再加上bv_offset就得到整个bio结构中数据的
起始地址了。获取bio数据对应的虚拟地址的函数的实现就是如下:
//include/linux/bio.h
static inline void *bio_data(struct bio *bio)
{
if (bio->bi_vcnt)
return page_address(bio_page(bio)) + bio_offset(bio);
return NULL;
}
可知,通过bio_data就可以获得bio数据的虚拟地址了,通过内核代码发现,这个虚拟地址只是bio数据的当前vec索引地址,而不一>定是整个的。
2,通过io映射将外设映射到内存空间
我们使用ioremap来将外设的空间映射到内存空间,借以访问外设,而这里所映射得到的就是物理地址,物理地址是一个固定的常量>,而不是我们以为的随意的一个地址。
以上,是本人根据理解,综合所参考的资料,书上所学,以及工作时候的时间,所做的总结。尽量只用文字的形式描述,只通过文本文件便可以学习。如其中有不准或者更好的建议,可以联系我,谢谢!
参考资料:
http://bbs.chinaunix.net/thread-2017377-2-1.html
http://bbs.chinaunix.net/thread-2083672-1-1.html#
http://www.cnblogs.com/c1230v/articles/1432525.html
http://hi.baidu.com/jingxshi/blog/item/7056f612fdcead58f919b865.html
作者:QuietHeart
Email:quiet_heart000@126.com
日期:2011年11月17日
发表评论
-
VNC服务配置
2012-08-21 12:30 2406VNC服务配置 VNC (Virtual N ... -
arp
2012-08-13 13:59 1762[功能] 管理系统的arp缓存。 [描述] 用来管理系统的 ... -
tcpdump
2012-08-10 16:26 1699tcpdump [功能] 抓包工具 ... -
使用git进行版本控制
2012-06-14 18:05 19647使用git进行版本控制 ... -
netstat
2012-05-29 16:15 1628netstat [功能] netstat是一 ... -
route
2012-05-18 14:56 1360route [-CFvnee] route [-v] [- ... -
man命令
2011-10-30 09:54 1102man命令 若你想要找尋具 ... -
程序流程图绘制
2011-08-10 17:11 853dia windows http://sourceforge ... -
使用tnef打开*.dat的邮件
2011-08-10 16:06 1760有时,windows上面发送的mail是dat格式的,例如wi ... -
[转]jad反编译java
2011-08-04 11:14 1660jad 的使用方法 JAD本身 ... -
关于sizeof
2011-08-02 15:17 1241关于sizeof sizeof以字节形 ... -
wordpress备份和恢复
2011-07-14 17:42 2404wordpress备份和恢复 本文 ... -
wordpress恢复片段
2011-07-01 18:05 1146如何备份和恢复? 1,备份 假设在wordpress服务器上面 ... -
sorry I'm OoO
2011-07-01 10:41 819OOO(Out of Office)中文意思:在野;不执政; ... -
vim画图插件
2011-06-27 16:13 1294DrawIt:Vim画图插件(可在vim中画基本示意图) 还是 ... -
UML相关工具一览
2011-03-31 10:45 854http://www.umlchina.com/Tools/N ... -
解决“C compiler cannot create executables”的错误
2011-01-31 16:04 14341感觉不错的解决方法,还没有尝试过,先转载下来了。 解决“C ... -
svn 补充技巧
2010-12-03 14:07 3318http://hqlong.com/2009/02/641.h ... -
spinlock sample
2010-11-26 12:33 9042个使用spinlock的字符驱动完整例子 有待回去仔细验证 -
关于动迁
2010-10-15 16:27 976什么是动迁?拆迁?回 ...
相关推荐
模拟分页式虚拟存储管理中硬件的地址转换和缺页中断,以及选择页面调度算法处理缺页中断。 二. 实验目的 在计算机系统中,为了提高主存利用率,往往把辅助存储器(如磁盘)作为主存储器的扩充,使多道运行的作业的...
总结起来,这个实验涵盖了操作系统中的关键概念,包括分页式虚拟存储管理的硬件地址转换、缺页中断的处理以及缺页中断下的FIFO页面调度算法。同时,我们还将通过实现文件系统,实践文件管理的基本操作,从而深化对...
总的来说,这个实验提供了一个实践平台,让学生通过编程体验和分析虚拟存储管理中的核心概念,如页面替换策略和地址转换,从而更好地理解操作系统如何有效地管理有限的物理内存资源,以满足多任务环境下程序的运行...
在本主题中,我们将深入探讨操作系统中的分页式存储管理和硬件地址转换,以及当发生缺页中断时如何利用FIFO(先进先出)页面调度算法进行处理。 一、分页式存储管理 分页式存储管理是现代操作系统中广泛采用的一种...
通过上述文件中的习题解答和测验,学生能够深入理解这些知识点,提升在信息存储与管理领域的专业能力。同时,这些资料还可以作为复习工具,帮助备考相关的认证考试,如CISSP(Certified Information Systems ...
存储器管理ppt 4.1 程序的装入和链接 ...4.3 基本分页存储管理方式 4.4 基本分段存储管理方式 4.5 虚拟存储器的基本概念 4.6 请求分页存储管理方式 4.7 页面置换算法 4.8 请求分段存储管理方式
分页存储管理是一种现代操作系统中常见的内存管理方式,它的核心思想是将进程的虚拟地址空间分割成固定大小的块,称为“页”,同时将物理内存也分割成相同大小的块,称为“页框”。这样的设计使得内存分配变得更加...
在本项目中,我们将学习如何配置和管理基于Windows Server 2012的存储池,并掌握云存储技术的基本概念和技术要点。 知识点1:添加硬盘到存储服务器中,创建存储池 在Windows Server 2012中,可以使用服务器管理器...
**4.2 储存管理** 存储管理是商品从生产到消费之间的保管过程,目标是高效利用空间和资源,随时准备满足客户需求,并保护货物安全。其功能包括降低运输成本、整合产品以满足个性化需求、提升客户满意度以及平衡供需...
【存储管理】是操作系统的核心功能之一,特别是在计算机内存资源有限的情况下,有效的存储管理至关重要。【可变分区管理】是一种动态分配内存的方法,它允许根据进程的实际需求动态地创建和调整分区大小。本实验报告...
并且,重点解释了重定位的概念、页式存储管理和页式虚拟存储管理及其调度算法的理解和应用。 1. 逻辑地址、绝对地址、重定位、程序浮动、存储保护的解释: 逻辑地址是用户程序中使用的从“0”地址开始的连续地址。...
本教学管理系统涉及的核心概念包括ER图(实体关系图)、概念模型、物理模型以及视图。这些元素都是数据库设计的重要组成部分,对于理解和实现教学管理系统的数据存储和访问至关重要。 首先,让我们详细探讨ER图。ER...
操作系统存储管理是计算机科学中的核心概念,它负责管理和优化计算机内存资源,确保多个进程能够高效、安全地共享有限的内存空间。在这个“操作系统存储管理实验”中,我们将使用C语言来实现三种主要的存储管理模式...
《联想DM存储设备 NetApp设备ONTAP概念指南》是一份专为理解联想凌拓存储ThinkSystem DM系列设备和NetApp FAS系列存储设计的概念性参考资料。该指南详细介绍了ONTAP平台,这是一种先进的数据管理和存储解决方案,...
在这两个案例中,采用HDS TagmaStore解决方案均展现出了强大的商业价值,包括在六个月或更短的时间内达到收支平衡、投资回报率超过三位数,以及总体存储成本和存储管理成本减少超过30%。 尽管Hitachi引入的一些概念...
在分区式存储管理中,还有地址重定位的概念。地址重定位是将逻辑地址转换为物理地址的过程。地址重定位可以分为静态重定位和动态重定位。静态重定位是在程序执行之前进行重定位,支持由软件来实现,将要装入的内存...
操作系统实验报告中的主题是“基本分页存储管理”,这是一个核心的操作系统概念,旨在解决内存管理和虚拟地址到物理地址转换的问题。在本次实验中,学生通过编写源代码模拟了一个基本的分页存储管理系统。 分页存储...
首先,我们需要理解段式存储管理和页式存储管理的基本概念。段式存储管理将内存空间划分为逻辑段,每个段代表一个程序模块,如主函数、数据结构或子程序。这种方式有利于程序的组织和共享。而页式存储管理则是将内存...
NAS具有安装管理方便、价格平民化等优点,是中小企业存储的优选方案。 特别是对于部门服务器目、独立的工作组级的客户,他们能充分享受到NAS性能价格比的好处。而SAN可以适用于企业级数据存储、服务器集群、远程灾难...