ARM—Linux基本数据类型综合应用实例
2011-04-06 22:37
579 查看
本文章将带读者走进Linux内核,亲身感受一下这个优秀的操作系统Linux的具体搭建过程。其实读者可以看到,若将这一高楼大厦分解细分为砖瓦,那么每一部分其实也并不是那么难的。
在Linux内核中,直接使用基本数据类型来构建的关键数据结构微乎其微,一般都是将基本数据类型组合起来,构成构造数据类型(如结构体等),来组成其关键的数据结构。
本文就以Linux中内存管理中的物理页为例进行讲解。
1、内存页管理机制
内存把物理页作为内存管理的基本单位。尽管处理器的最小可寻址单位通常为字,但是,内存管理单元(MMU,管理内存并把虚拟地址转换为物理地址的硬件)通常是以页为单位进行处理的。也正因为如此,MMU以页的大小为单位来管理系统中的页表。因此,从虚拟内存的角度来看,页就是最小分配单位。
不同的体系结构,所支持的页大小也不尽相同,读者可以查看/include/asm../page.h中的定义,如下所示:
/*include/asm-i386/page.h*/
/*PAGE_SHIFT决定页大小,页大小为4KB*/
#define PAGE_SHIFT 12
/*include/asm-alpha/page.h*/
/*页大小为8KB*/
#define PAGE_SHIFT 13
/*include/asm-arm/page.h*/
/*页大小为4KB*/
#define PAGE_SHIFT 12
/*include/asm-arm26/page.h,arm2600*/
/*若定义了页大小为16KB*/
#if defined(CONFIG_PAGESIZE_16)
#define PAGE_SHIFT 14 /*16KB*/
/*其他情况页大小为32KB*/
#else /*default*/
#define PAGE_SHIFT 15 /*32KB*/
#endif
/*include/asm-ppc/page.h*/
/*页大小为4KB*/
#define PAGE_SHIFT 12
这里的PAGE_SHIFT是用于决定页大小的,将它的数值进行以2为底取幂运算,所得到的结果就是页得大小,比如2的12次方为4K。可以看到,不同的体系结构的页大小是不同的,有些体系结构甚至可以支持多种不同的页大小,在ARM中,就可以支持3种页大小,其中S3C2410的页大小为4KB。
2、内核物理页结构
内核的物理页结构定义在<linux/mm.h>中,它是一个构造数据类型—结构体,其结构体定义如下:
struct page{
/*页状态标记*/
page_flags_t flages;
/*页引用标记*/
atomic_t _count;
/*页映射计数,并且限制页反向映射*/
atomic_t _mapcount;
/*私有页标记*/
unsigned long private;
/*指向该物理页相关的结构*/
struct_address_space *mapping;
/*页映射偏移*/
pgoff_t index;
/*页换出队列*/
struct list_head lru;
/*页虚拟地址*/
void *virtual;
};
下面从语法角度介绍这些基本数据类型中的重要参数。
(1)flags
flags域是用于存放页的状态的,它的类型标识符为“page_flags_t”,可以看出,这是一个自定义的标识符,通常是由typedef来定义的。读者可以继续在该文件中查找,可以发现有以下定义:
typedf unsighed long page_flags_t;
可以看到,“page_flags_t"实际上是一个“unsigned long ”型32位的数据类型。那么,为什么在此处要设置一个32位的数据类型呢?原因在于,flag是用于页得状态的,它其中的每一位都单独表示一种状态,所以它可以同时表示出32种不同的状态。这些状态标志定义在<linux/page_flags.h>中,如下所示:
#define PG_locked 0 /*页被锁*/
#define PG_error 1 /*页错误*/
#define PG_referenced 2 /*页被引用*/
#define PG_uptodate 3 /*页被更新*/
#define PG_dirty 4 /*页是脏的*/
#define PG_lru 5 /*页换出*/
#define PG_active 6 /*页激活*/
#define PG_slab 7 /*页缓存*/
#define PG_arch 8 /*页被检查*/
#define PG_reserved 10 /*页保留*/
#define PG_arch_1 9 /*一级页*/
#define PG_private 11 /*私有页*/
#define PG_writeback 12 /*页写回*/
#define PG_nosave 13 /*该页不安全*/
#define PG_compound 14 /*页响应*/
#define PG_swapcache 15 /*页换出在高速缓存中*/
#define PG_mappedtodisk 16 /*在磁盘中有该快*/
#define PG_reclaim 17 /*页声明*/
#define PG_nosave_free 18 /*页空闲*/
#define PG_uncached 19 /*页未在cache中命中*/
这里定义了19个状态,因此,安排一个32位的整数可以给今后的升级留有空间。
(2)_count和_mapcount
_count和_mapcount分别是页引用计数和页映射计数,它们的类型都是“atomic_t",同“atomic_t”,同“page_flags_t”一样,这个类型标识符也是自定义的,定义其的文件在</include/asm-arm/atomic.h>中,如下所示:
typedef struct {volatile int counter;}atomic_t;
可以看到,typedef不仅可以为基本数据类型取新名,也可以为构造数据类型取名。
(3)virtual
virtual是一个空指针,它用于指明页的虚拟地址。可以看到,使用指针来表示地址是非常恰当的。有些情况下,一些内存(即所谓的高端内存)并不永远地映射到内核空间上,这是virtual的值为NULL。
在这时为什么要用空指针呢?由于在此处,virtual用于表明一个地址而不是用于指示任何其他类型的数据,所以是使用空指针这一中立类型的指针是最合适的。
在Linux内核中,直接使用基本数据类型来构建的关键数据结构微乎其微,一般都是将基本数据类型组合起来,构成构造数据类型(如结构体等),来组成其关键的数据结构。
本文就以Linux中内存管理中的物理页为例进行讲解。
1、内存页管理机制
内存把物理页作为内存管理的基本单位。尽管处理器的最小可寻址单位通常为字,但是,内存管理单元(MMU,管理内存并把虚拟地址转换为物理地址的硬件)通常是以页为单位进行处理的。也正因为如此,MMU以页的大小为单位来管理系统中的页表。因此,从虚拟内存的角度来看,页就是最小分配单位。
不同的体系结构,所支持的页大小也不尽相同,读者可以查看/include/asm../page.h中的定义,如下所示:
/*include/asm-i386/page.h*/
/*PAGE_SHIFT决定页大小,页大小为4KB*/
#define PAGE_SHIFT 12
/*include/asm-alpha/page.h*/
/*页大小为8KB*/
#define PAGE_SHIFT 13
/*include/asm-arm/page.h*/
/*页大小为4KB*/
#define PAGE_SHIFT 12
/*include/asm-arm26/page.h,arm2600*/
/*若定义了页大小为16KB*/
#if defined(CONFIG_PAGESIZE_16)
#define PAGE_SHIFT 14 /*16KB*/
/*其他情况页大小为32KB*/
#else /*default*/
#define PAGE_SHIFT 15 /*32KB*/
#endif
/*include/asm-ppc/page.h*/
/*页大小为4KB*/
#define PAGE_SHIFT 12
这里的PAGE_SHIFT是用于决定页大小的,将它的数值进行以2为底取幂运算,所得到的结果就是页得大小,比如2的12次方为4K。可以看到,不同的体系结构的页大小是不同的,有些体系结构甚至可以支持多种不同的页大小,在ARM中,就可以支持3种页大小,其中S3C2410的页大小为4KB。
2、内核物理页结构
内核的物理页结构定义在<linux/mm.h>中,它是一个构造数据类型—结构体,其结构体定义如下:
struct page{
/*页状态标记*/
page_flags_t flages;
/*页引用标记*/
atomic_t _count;
/*页映射计数,并且限制页反向映射*/
atomic_t _mapcount;
/*私有页标记*/
unsigned long private;
/*指向该物理页相关的结构*/
struct_address_space *mapping;
/*页映射偏移*/
pgoff_t index;
/*页换出队列*/
struct list_head lru;
/*页虚拟地址*/
void *virtual;
};
下面从语法角度介绍这些基本数据类型中的重要参数。
(1)flags
flags域是用于存放页的状态的,它的类型标识符为“page_flags_t”,可以看出,这是一个自定义的标识符,通常是由typedef来定义的。读者可以继续在该文件中查找,可以发现有以下定义:
typedf unsighed long page_flags_t;
可以看到,“page_flags_t"实际上是一个“unsigned long ”型32位的数据类型。那么,为什么在此处要设置一个32位的数据类型呢?原因在于,flag是用于页得状态的,它其中的每一位都单独表示一种状态,所以它可以同时表示出32种不同的状态。这些状态标志定义在<linux/page_flags.h>中,如下所示:
#define PG_locked 0 /*页被锁*/
#define PG_error 1 /*页错误*/
#define PG_referenced 2 /*页被引用*/
#define PG_uptodate 3 /*页被更新*/
#define PG_dirty 4 /*页是脏的*/
#define PG_lru 5 /*页换出*/
#define PG_active 6 /*页激活*/
#define PG_slab 7 /*页缓存*/
#define PG_arch 8 /*页被检查*/
#define PG_reserved 10 /*页保留*/
#define PG_arch_1 9 /*一级页*/
#define PG_private 11 /*私有页*/
#define PG_writeback 12 /*页写回*/
#define PG_nosave 13 /*该页不安全*/
#define PG_compound 14 /*页响应*/
#define PG_swapcache 15 /*页换出在高速缓存中*/
#define PG_mappedtodisk 16 /*在磁盘中有该快*/
#define PG_reclaim 17 /*页声明*/
#define PG_nosave_free 18 /*页空闲*/
#define PG_uncached 19 /*页未在cache中命中*/
这里定义了19个状态,因此,安排一个32位的整数可以给今后的升级留有空间。
(2)_count和_mapcount
_count和_mapcount分别是页引用计数和页映射计数,它们的类型都是“atomic_t",同“atomic_t”,同“page_flags_t”一样,这个类型标识符也是自定义的,定义其的文件在</include/asm-arm/atomic.h>中,如下所示:
typedef struct {volatile int counter;}atomic_t;
可以看到,typedef不仅可以为基本数据类型取新名,也可以为构造数据类型取名。
(3)virtual
virtual是一个空指针,它用于指明页的虚拟地址。可以看到,使用指针来表示地址是非常恰当的。有些情况下,一些内存(即所谓的高端内存)并不永远地映射到内核空间上,这是virtual的值为NULL。
在这时为什么要用空指针呢?由于在此处,virtual用于表明一个地址而不是用于指示任何其他类型的数据,所以是使用空指针这一中立类型的指针是最合适的。
相关文章推荐
- 基于Linux的MySQL操作实例(软件安装,mysql基本操作,mysql数据类型,建表、插入数据操作)
- 第二十节,基本数据类型,集合set、综合应用新数据更新老数据
- ARM—Linux基本运算符综合实例
- Unix/Linux C++应用开发-C++变量和基本数据类型
- 《黑马程序员》注解的基本类型及综合应用
- 实验九——基本数据类型存储及应用总结
- Linux C 学习笔记01-基本数据类型
- 我的php学习笔记(二)php基本数据类型、基本语法和基本运算类型及其应用
- 夯实基础——Java基本数据类型、应用类型和转换
- ARM的嵌入式Linux移植体验之应用实例
- Lengths of Primitive Java and C++ Data Types on Linux and Windows 32-bit/64-bit (Linux和Windows上Java和C++基本数据类型的长度对比32位/64位)
- 了解Java中基本数据类型与应用
- Linux/Unix中的基本系统数据类型
- Android JNI和NDK学习(08)--JNI实例一 传递基本类型数据
- Linux 的基本系统数据类型
- Java字节流与基本数据类型的转换实例
- linux下32位机与64位机基本数据类型长度对比
- 实验九——基本数据类型存储及应用总结
- 实验九——基本数据类型存储及应用总结
- ARM的嵌入式Linux移植体验之应用实例