自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(30)
  • 资源 (14)
  • 收藏
  • 关注

原创 请求队列描述符

1.4.4 请求队列描述符<br />make_request_fn方法属于块设备I/O调度层的内容,要继续往下走,需要介绍一下通用块层的体系架构,这里需要从磁盘和磁盘分区开始说起。磁盘是一个由通用块层处理的逻辑块设备,是块设备驱动中最重要的一个概念。通常一个磁盘对应一个硬件块设备,例如硬盘、软盘或光盘。但是,磁盘也可以是一个虚拟设备,可以建立在几个物理磁盘分区之上或一些RAM专用页中的内存区上。在任何情形中,借助通用块层提供的服务,上层内核组件可以以同样的方式工作在所有的磁盘上。<br /> <br />

2011-01-31 23:59:00 3735 2

原创 提交I/O传输请求

1.4.3 提交I/O传输请求<br />好了,bio这个数据我们建立好了,随后调用generic_make_request 函数。这个函数是通用块层的入口点,该层只有这一个函数处理请求:<br /> <br />3020void generic_make_request(struct bio *bio)<br />3021{<br />3022        request_queue_t *q;<br />3023        sector_t maxsector;<br />3024       

2011-01-31 23:53:00 3447

原创 通用块层相关数据结构

1.4.2 通用块层相关数据结构<br />好了,通用块层的一些比较重要的基础知识大家都知道了,下面我们着重来看bio这个东西。大家在前面“创建一个bio请求”一节中已经见过这个结构了,但是,由于它太重要了,所以我们这里有必要对它进行进一步的介绍。<br /> <br />每个bio结构都包含一个磁盘存储区标识符(存储区中的起始扇区号和扇区数目)和一个或多个描述与I/O操作相关的内存区的段。bio由bio数据结构描述:<br /> <br />struct bio {<br />       sector_

2011-01-31 23:47:00 4079

原创 块设备的基础知识

1.4 通用块层的处理<br />在前面普通文件和块设备文件的readpage方法中介绍到,对于一个普通文件,要读取相对于文件头的ppos处开始size个连续的字节,就必须计算成对应的页面缓存在内存中;如果存在不连续的情况,如“文件的洞”,就调用块设备的readpage方法建立块设备页高速缓存存放不来连续的块。<br /> <br />不管怎样,最终都将封装一个bio结构,并把请求传递给函数 generic_make_request ,并由 generic_make_request 函数将请求提交给通用块层

2011-01-31 23:43:00 6214 2

原创 文件的预读

1.3.5 文件的预读<br />文件预读的内容我是把ULK-3一书中的内容全盘拷贝下来了。如果大家感兴趣可以根据源代码深入了解一下。<br /> <br />很多磁盘的访问都是顺序的。普通文件以相邻扇区成组存放在磁盘上,因此很少移动磁头就可以快速检索到文件。当程序读或拷贝一个文件时,它通常从第一个字节到最后一个字节顺序地访问文件。因此,在处理进程对同一文件的一系列读请求时,可以从磁盘上很多相邻的扇区读取。<br /> <br />预读(read-ahead)是一种技术,这种技术在于在实际请求前读普通文件或

2011-01-31 23:32:00 3514

原创 文件的readpage方法

1.3.3 普通文件的readpage方法<br />回到do_mpage_readpage中,从mpage_readpage传进来的buffer_head类型的map_bh参数的b_bdev、b_blocknr和b_size字段就被赋上值了,然后245~271行对这个map_bh进行一系列的检查,检查可能发生的异常条件。具体有这几种情况:当一些块在磁盘上不相邻时,或某块落如“文件洞”内时,或一个块缓冲区已经由get_block函数写入时。那么跳到confused标号处,用一次读一块的方式读该页。有关“文件

2011-01-31 23:15:00 6138

原创 得到文件的逻辑块号

1.3.2 得到文件的逻辑块号<br />继续走,233行,设置map_bh的b_page字段为当前page。随后进入循环,对于页中的每一块,调用ext2文件系统的get_block函数,作为参数传递page的inode、相对于文件起始位置的块索引block_in_file、map_bh进去,最后返回相对于磁盘分区开始位置的逻辑块号,即相对于磁盘或分区开始位置的块索引,存放在结果参数map_bh的b_blocknr字段中。所以这里我们重点关注get_block的原型,ext2_get_block函数,来自f

2011-01-31 22:08:00 7382 2

原创 创建一个bio请求

1.3 页高速缓存层的处理<br />从上文得知:ext2_readpage 函数是该层的入口点,传给它的参数是文件的file,以及需要读入页高速缓存的页面。这个页面不是别的,正是刚才page_cache_alloc_cold分配的那个空白页面,其现在位于文件的基树中,基树中索引为index:<br /> <br />static int ext2_readpage(struct file *file, struct page *page)<br />{<br />       return mpage_r

2011-01-31 21:58:00 5274

原创 Ext2层读文件入口函数

1.2.5 Ext2层读文件入口函数<br />好了,我们知道了Ext2文件系统的磁盘布局,以及始终缓存的磁盘超级拷贝块结构ext2_super_block和动态缓存的已分配磁盘索引节点结构ext2_inode这些预备知识。接下来就假设一个文件的inode已经分配好,并且包含该文件所有块号的对应宿主ext2_inode_info结构也在内存中初始化好了。那么如何读这个文件?<br /> <br />前面讲了,ext2层,也就是第二扩展文件系统的入口函数 generic_file_read,下面我们就从它开始

2011-01-31 21:54:00 3074

原创 Ext2索引节点对象的读取

1.2.4 Ext2索引节点对象的读取<br />上一节我们提到了当open("file", O_CREAT)创建一个文件时,其对应的Ext2磁盘索引节点是如何建立的,又是如何与系统中的其他数据结构联系的。现在还是从一个普通文件的角度来分析,当我门在根目录下调用fd = open("file", O_RDONLY)打开一个已经存在文件时,同样也会启动do_sys_open系统调用,并根据路径“file”去触发do_filp_open函数返回一个file结构。<br /> <br />而这个时候,do_fil

2011-01-31 21:48:00 3539

原创 Ext2索引节点对象的创建

1.2.3 Ext2索引节点对象的创建<br />现在还是从一个普通文件的角度来分析上面的过程,比如说,当我门在根目录下调用fd = open("file", O_CREAT)打开(创建)一个文件时,会启动do_sys_open系统调用,并根据路径“file”去触发do_filp_open函数返回一个file结构。do_filp_open主要调用的两个函数(详细的过程请参考博客“VFS系统调用的实现”<br />http://blog.csdn.net/yunsongice/archive/2010/06/

2011-01-31 21:42:00 3673

原创 Ext2的超级块对象

1.2.2 Ext2的超级块对象<br />当安装Ext2文件系统时(执行诸如mount -t ext2 /dev/sda2 /mnt/test的命令),存放在Ext2分区的磁盘数据结构中的大部分信息将被拷贝到RAM中,从而使内核避免了后来的很多读操作。那么一些数据结构如何经常更新呢?因为所有的Ext2磁盘数据结构都存放在Ext2磁盘分区的块中,因此,内核利用页高速缓存来保持它们最新。<br /> <br />前面谈到,安装ext2文件系统时,最终会调用ext2_fill_super()函数来为数据结构分配

2011-01-31 21:37:00 4371 1

原创 块设备驱动应用之文件读写

1 读文件<br />其实Linux驱动程序最重要,也是难点就是那个块设备驱动程序。要全面研究这个问题不是那么容易,从本博开始,我们独辟蹊径,从一个文件读写的角度把这个问题阐述干净。<br /><br />大部分程序员可能会有这样的疑问:当我们在应用程序中调用库函数 read 时,这个请求是经过哪些处理最终到达磁盘的呢,数据又是怎么被拷贝到用户缓存区的呢?我们就从 read 系统调用发出到结束处理的全过程,来解密整个内核块设备驱动的内幕。<br /> 1.1 系统调用VFS层的处理<br />用户要读写文件

2011-01-31 21:32:00 4283

原创 设备驱动程序共性

<br />设备驱动程序是一组内核例程的集合,它使得硬件设备响应控制设备的编程接口,最关键的是该接口是一组规范的VFS函数集(open, read, lseek, ioctl等等)。这些函数的实际实现由设备驱动程序全权负责。由于每个设备都有一个唯一的I/O控制器,因此就有唯一的命令和唯一的状态信息,所以大部分I/O设备都有自己的驱动程序。<br /> <br />设备驱动程序的种类有很多。它们在对用户态应用程序提供支持的级别上有很大的不同,也对来自硬件设备的数据采集有不同的缓冲策略。这些选择极大地影响了设备

2011-01-31 16:39:00 3679

转载 linux设备模型 —— sysfs

1 sysfs初探<br />"sysfs is a ram-based filesystem initially based on ramfs. It provides a means to export kernel data structures, their attributes, and the linkages between them to userspace.” --- documentation/filesystems/sysfs.txt<br />可以先把documentation/fi

2011-01-31 16:34:00 3467 1

原创 添砖加瓦

5.2.6 添砖加瓦<br />回到setup_arch,来到1007,调用paging_init()进行页面初始化。<br /> <br />825void __init paging_init(void)<br /> 826{<br /> 827        pagetable_init();<br /> 828<br /> 829        __flush_tlb_all();<br /> 830<br /> 831        kmap_init();<br /> 832<br /> 833

2011-01-12 00:23:00 3558

原创 建立内存管理架构

5.2.5 建立内存管理架构回到setup_arch函数的中,第995行调用initmem_init来启用初始化期间的内存管理器early。这个函数在两个文件中有定义,arch/x86/mm/init_32.c和arch/x86/mm/numa_32.c,取决于是否启动了编译选项CONFIG_NEED_MULTIPLE_NODES。这个编译选项是什么意思?这得从NUMA说起。NUMA翻译成中文就叫“非对称内存访问体系”,其目的是为多CPU,或大型计算机集群提供一个分布式内存访问环境,而每一个分布式节点就叫做

2011-01-11 23:13:00 3038

原创 第二次启动分页管理

5.2.4 第二次启动分页管理<br />回到init_memory_mapping()函数,之后nr_range次调用kernel_physical_mapping_init(),nr_range为map_range数组的总的元素数,前面总共执行了两次save_mr,所以nr_range为2,分别是0~1<<9和2MB~end>>12的map_range结构,代表4k和2MB两种形式的内存页表。不过为了方便起见,我们暂时忽略2MB页面大小的体系,只分析传统4k页面体系。<br /> <br />238un

2011-01-11 23:09:00 2724 1

原创 着手建立内核永久页表

5.2.3 着手建立内核永久页表<br />得到了总的页面数max_pfn和高端页面数highmem_pages之后,来到setup_arch的947行,调用init_memory_mapping()函数来建立系统初始化阶段的临时分页体系,传入的参数意义代表从0~max_low_pfn对应的32位物理地址(低12位全为0,也就是页面对齐),在函数init_memory_mapping函数中先后调用下面的几个函数来设置内存相关数据(因为bootmem此时没有初始化):<br />find_early_tabl

2011-01-11 23:07:00 4057 2

原创 获得总页面数

5.2.2 获得总页面数<br />回到setup_arch()中,接下来,继续走,891行调用e820_end_of_ram_pfn()函数根据e820的数据来获得32位可用物理内存地址的最大值并右移PAGE_SHIFT,也就是12位,最后由函数e820_end_pfn返回这个20位的值,保存在内部变量max_pfn中,作为总的页面数量:<br /> <br />855static unsigned long __init e820_end_pfn(unsigned long limit_pfn, uns

2011-01-11 23:06:00 2242

原创 拷贝可用内存区信息

5.2.1 拷贝可用内存区信息首先setup_arch第一步要做的就是保存arch/x86/kernel/head_32.S初始化的new_cpu_data数据到boot_cpu_data中。new_cpu_data主要是保存CPU的相关信息,在哪儿初始化的?还记得我们在arch/x86/kernel/head_32.S中忽略过的checkCPUtype吗?就在那里,感兴趣的同学可以去探究一下。784行,setup_memory_map()函数,进入start_kernel内核初始化函数中第一个内存管理函数

2011-01-11 23:05:00 2685

原创 执行setup_arch()函数

5.2 执行setup_arch()函数<br />回到start_kernel当中,562行,调用setup_arch函数,传给他的参数是那个未被初始化的内部变量command_line。这个setup_arch()函数是start_kernel阶段最重要的一个函数,每个体系都有自己的setup_arch()函数,是体系结构相关的,具体编译哪个体系的setup_arch()函数,由顶层Makefile中的ARCH变量决定:<br /> <br />724void __init setup_arch(cha

2011-01-11 23:02:00 4060

原创 打印版本信息

5.1.6 打印版本信息<br />我们来简单的看看在内核中,在屏幕上打印一条信息的原理是怎么实现的。由于我们配置了CONFIG_PRINTK编译选项,所以调用位于kernel/printk.c中的printk函数:<br /> <br />584 asmlinkage int printk(const char *fmt, ...)<br />585 {<br />586        va_list args;<br />587        int r;<br />588  <br />589    

2011-01-11 23:01:00 2070

原创 初始化地址散列表

5.1.5 初始化地址散列表<br />560行,page_address_init()函数,来自mm/highmem.c:<br /> <br />409void __init page_address_init(void)<br /> 410{<br /> 411        int i;<br /> 412<br /> 413        INIT_LIST_HEAD(&page_address_pool);<br /> 414        for (i = 0; i < ARRAY_SIZE(

2011-01-11 23:00:00 3551

原创 激活第一个CPU

<br />回到start_kernel,559行,boot_cpu_init函数,跟start_kernel位于同一文件:<br /> <br />494static void __init boot_cpu_init(void)<br /> 495{<br /> 496        int cpu = smp_processor_id();<br /> 497        /* Mark the boot cpu "present", "online" etc for SMP and UP case

2011-01-11 22:57:00 7786 9

原创 注册时钟事件监听器

5.1.3 注册时钟事件监听器<br />由于我们在.config文件中设置了CONFIG_GENERIC_CLOCKEVENTS,所以,start_kernel函数的第558行调用kernel/time/tick-common.c中的tick_init函数,来注册一个时钟事件监听器。tick_init只调用一个clockevents_register_notifier函数:<br /> <br />static struct notifier_block tick_notifier = {<br />  

2011-01-11 22:53:00 2919

原创 启动大内核锁

5.1.2 启动大内核锁<br />回到start_kernel,557行,lock_kernel(),实际的代码来了,大内核锁。我们在.config文件中配置了CONFIG_LOCK_KERNEL的,所以这个函数是start_kernel中继local_irq_disable之后实际执行到的第二个函数。<br /> <br />有关大内核的知识,这里又简单的介绍一下。在早期的Linux内核版本中,大内核锁(big kernel block,也叫全局内核锁或BKL)被广泛使用。在2.0版本中,这个锁是相对粗

2011-01-11 22:52:00 2287

原创 初始化同步与互斥环境

5.1 初始化同步与互斥环境<br />要了解本节的内容,需要补充一下“疯狂内核之同步与互斥”的预备知识。<br /><br /> 5.1.1 屏蔽中断<br /> <br />void lockdep_init(void)<br />{<br />       int i;<br /> <br />       /*<br />        * Some architectures have their own start_kernel()<br />        * code which calls

2011-01-11 22:49:00 5133

原创 走向现代:start_kernel函数

5 走向现代:start_kernel函数<br />这是内核初始化至此,终于跑出arch/x86目录了,它在linux/init/main.c,以后的代码除了少数特例,其余的都在linux/init/目录中。<br /> <br />528asmlinkage void __init start_kernel(void)<br /> 529{<br /> 530        char * command_line;<br /> 531        extern struct kernel_param

2011-01-11 22:40:00 2799

原创 初始化0号进程

<br />arch/x86/kernel/head_32.S的336行,进入分页后的内核代码段,执行lss stack_start,%esp指令,立即为进程0建立内核态堆栈。stack_start定义在657行:<br />657 ENTRY(stack_start)<br />658        .long init_thread_union+THREAD_SIZE<br />659        .long __BOOT_DS<br /> <br />我们看到内核态堆栈由init_thread_un

2011-01-04 10:41:00 3871

NFS文件系统

NFS文件系统是目前最为成功的网络文件系统,在文件共享领域有着出色的表现,特别是pNFS的出现,使得NFS文件系统在性能和规模上有了大幅提升,为其带了更为广阔的应用空间。同时,NFS之所以备受关注,还在于它在NAS存储领域的关键作用。本文剖析了NFSv3文件系统源代码,使开发工程师,技术支持人员,特别是存储领域从业人员对NFS有更为深刻的认识。

2012-04-08

数据结构与算法——面向对象C++设计模式

数据结构与算法的经典教材,系统全面地介绍了各种传统的数据结构,把它们按照类层次的现代理念予以展开,进而达到抽象结构与实际设计的完美统一。本书后三章通过引入抽象问题求解的概念,集中进述了算法技术和各算法之间的关系。另外,作者运用一定的数学工具及必要的分析技术和分析理论,对每种数据结构及相关算法都进行了时间和空间效率分析。本书作者在每章后面布置了习题和设计项目,并在全书的后面给出了问题参考答案,希望读者能在其中汲取宝贵的知识与经验。

2011-11-27

高性能分布式监控系统Ganglia详解

Ganglia是一个高性能分布式监控系统,用来监控集群和超级计算机。Ganglia是一个基于多点传送的监听/告知协议来监控集群的状态,它使用一个点对点树来访问集群并且可以统计其综合的信息。Ganglia可以广泛地使用像XML这样的技术来表示数据;使用XDR技术来聚合、轻化数据传送;使用RRDTool来存储和显示数据。

2011-07-10

几个比较著名的哈希算法

几个比较著名的哈希算法,还有哈希算法的概念以及如何优化哈希值的分布,在日常软件开发中十分有用

2011-07-07

疯狂内核之——内核初始化

目录 1 引子 2 1.1 上电 2 1.2 BIOS时代 3 1.3 内核引导程序 5 2 内核映像的形成 8 2.1 MakeFile预备知识 9 2.1.1 Makefile书写规则 9 2.1.2 Makefile变量 10 2.1.3 条件判断 14 2.1.4 函数 17 2.1.5 隐含规则 17 2.1.6 定义模式规则 19 2.1 KBuild体系 23 2.1.1 内核目标 24 2.1.2 主机程序 26 2.1.3 编译标志 27 2.2 内核编译分析 28 2.2.1 编译配置 29 2.2.2 寻找第一个目标 32 2.2.3 prepare和scripts目标 38 2.2.4 递归编译各对象 41 2.2.5 链接vmlinux 44 2.2.6 制作bzImage 50 3 实模式下的内核代码 57 3.1 内核映像内存布局 58 3.2 实模式汇编代码header.S 60 3.2.1 无用的bootsect代码 60 3.2.2 初始化头变量hdr 63 3.2.3 准备实模式下C语言环境 64 3.3 实模式代码main函数 69 3.3.1 复制初始化头变量 71 3.3.2 初始化堆 74 3.3.3 确保支持当前运行的CPU 75 3.3.4 设置BIOS的x86模式 76 3.3.5 内存的检测 78 3.3.6 设置键盘属性 81 3.3.7 填充系统环境配置表 82 3.3.8 填充IST信息 83 3.3.9 设置Video模式 83 3.4 实模式代码go_to_proteced_mode函数 91 3.4.1 禁止可屏蔽和不可屏蔽中断 92 3.4.2 打开A20地址线 93 3.4.3 安装临时全局描述符表 99 3.4.4 第一次启动保护模式 101 4 保护模式下的内核代码 107 4.1 32位x86保护模式代码 107 4.1.1 内核解压缩的前期工作 108 4.1.2 解压缩内核 111 4.1.3 第二次启动保护模式 121 4.1.4 第一次启动分页管理 124 4.1.5 初始化0号进程 128 4.2 向start_kernel进发 131 4.2.1 初始化中断描述符表 132 4.2.2 第三次启动保护模式 137 4.2.3 启动x86虚拟机 141 5 走向现代:start_kernel函数 144 5.1 初始化同步与互斥环境 148 5.1.1 屏蔽中断 148 5.1.2 启动大内核锁 152 5.1.3 注册时钟通知链 153 5.1.4 激活第一个CPU 155 5.1.5 初始化地址散列表 160 5.1.6 打印版本信息 161 5.2 执行setup_arch()函数 166 5.2.1 拷贝可用内存区信息 171 5.2.2 获得总页面数 175 5.2.3 着手建立永久内核页表 177 5.2.4 第二次启动分页管理 181 5.2.5 建立内存管理架构 186 5.2.6 添砖加瓦 192 5.3 设置每CPU环境 206 5.4 初始化内存管理区列表 211 5.5 利用early_res分配内存 214 5.6 触碰虚拟文件系统 223 5.7 初始化异常服务 224 5.8 初始化内存管理 230 5.8.1 启用伙伴算法 230 5.8.2 初始化slab分配器 241 5.8.3 初始化非连续内存区 250 5.9 初始化调度程序 251 5.10 初始化中断处理系统 256 5.10.1 设置APIC中断服务 256 5.10.2 初始化本地软时钟 264 5.10.3 软中断初始化 268 5.10.4 初始化定时器中断 271 5.11 走进start_kernel尾声 273 5.11.1 初始化slab的后续工作 273 5.11.2 启动console 275 5.11.3 一些简单的函数 276 5.11.4 校准CPU时钟速度 279 5.11.5 创建一些slab缓存 282 5.12 安装根文件系统 287 5.12.1 创建VFS相关slab缓存 288 5.12.2 安装rootfs 291 5.12.3 安装proc文件系统 296 6 后start_kernel时代 298 6.1 创建1号进程 298 6.2 子系统的初始化 306 6.3 启动shell环境 309

2011-05-30

疯狂内核之——Linux虚拟内存

目录 第一章 Linux底层分段分页机制 5 1.1 基于x86的Linux分段机制 5 1.2 基于x86的Linux分页机制 7 1.2.1 页全局目录和页表 8 1.2.2 线性地址到物理地址 10 1.2.3 线性地址字段处理 13 1.2.4 页表处理 15 1.3 扩展分页与联想存储器 20 1.4 Linux内存布局 21 1.5 内核空间和用户空间 23 1.5.1 初始化临时内核页表 24 1.5.2 永久内核页表的初始化 32 1.5.3 第一次进入用户空间 41 1.5.4 内核映射机制实例 44 1.6 固定映射的线性地址 48 1.7 高端内存内核映射 50 1.8.1 永久内存映射 50 1.8.2 临时内核映射 55 第二章 内核级内存管理系统 58 2.1 Linux页面管理 58 2.1.1 NUMA架构 61 2.1.2 内存管理区 62 2.2 伙伴系统算法 65 2.2.1 数据结构 66 2.2.2 块分配 67 2.2.3 块释放 69 2.3 Linux页面级内存管理 72 2.3.1 分配一组页面 73 2.3.2 释放一组页面 80 2.4 每CPU页面高速缓存 81 2.4.1 数据结构 81 2.4.2 通过每CPU 页高速缓存分配页面 82 2.4.3 释放页面到每CPU 页面高速缓存 83 2.5 slab分配器 85 2.5.1 数据结构 86 2.5.2 分配/释放slab页面 92 2.5.3 增加slab数据结构 93 2.5.4 高速缓存内存布局 94 2.5.5 slab着色 95 2.5.6 分配slab对象 96 2.5.7 释放Slab对象 100 2.5.8 通用对象 102 2.5.9 内存池 103 2.6 非连续内存区 104 2.6.1 高端内存区回顾 105 2.6.2 非连续内存区的描述符 106 2.6.3 分配非连续内存区 109 2.6.4 释放非连续内存区 113 第三章 进程的地址空间 117 3.1 用户态内存分配 117 3.1.1 mm_struct数据结构 118 3.1.2 内核线程的内存描述符 122 3.2 线性区的数据结构 123 3.2.1 线性区数据结构 123 3.2.2 红-黑树算法 126 3.2.3 线性区访问权限 128 3.3 线性区的底层处理 130 3.3.1 查找给定地址的最邻近区 131 3.3.2 查找一个与给定的地址区间相重叠的线性区 135 3.3.3 查找一个空闲的地址区间 135 3.3.4 向内存描述符链表中插入一个线性区 137 3.4 分配线性地址区间 141 3.5 释放线性地址区间 151 3.5.1 do_munmap()函数 151 3.5.2 split_vma()函数 153 3.5.3 unmap_region()函数 155 3.6 创建和删除进程的地址空间 156 3.6.1 创建进程的地址空间 156 3.6.2 删除进程的地址空间 175 3.6.3 内核线程1号的地址空间 176 3.7 堆的管理 178 第四章 磁盘文件内存映射 182 4.1 内存映射的数据结构 182 4.2 内存映射的创建 184 4.3 内存映射的请求调页 194 4.4 刷新内存映射的脏页 203 4.5 非线性内存映射 210 第五章 页面的回收 215 5.1 页框回收概念 215 5.1.1 选择目标页 216 5.1.2 PFRA设计 217 5.2 反向映射技术 218 5.2.1 匿名页的反向映射 220 5.2.2 优先搜索树 226 5.2.3 映射页的反向映射 231 5.3 PFRA实现 235 5.3.1 最近最少使用(LRU)链表 236 5.3.2 内存紧缺回收 242 5.3.3 回收磁盘高速缓存的页 267 5.3.4 周期回收 273 5.3.5 内存不足删除程序 283 第六章 交换机制 289 6.1 交换区数据结构 289 6.1.1 创建交换区 290 6.1.2 交换区描述符 291 6.1.3 换出页标识符 293 6.2 激活和禁用交换区 295 6.2.1 sys_swapon()系统调用 296 6.2.2 sys_swapoff()系统调用 304 6.2.3 try_to_unuse()函数 308 6.3 分配和释放页槽 313 6.3.1 scan_swap_map()函数 313 6.3.2 get_swap_page()函数 316 6.3.3 swap_free()函数 318 6.4 页面的换入换出 320 6.4.1 交换高速缓存 320 6.4.2 换出页 323 6.4.3 换入页 329 第七章 缺页异常处理程序 335 7.1 总体流程 335 7.2 vma以外的错误地址 341 7.3 vma内的错误地址 346 7.3.1 handle_mm_fault()函数 348 7.3.2 请求调页 352 7.3.3 写时复制 358 7.4 处理非连续内存区访问 364

2011-05-30

疯狂内核之——进程管理子系统

目录 1 进程的组织 5 1.1 进程相关数据结构 5 1.1.1 进程的基本信息 6 1.1.2 进程状态 10 1.1.3 TASK_RUNNING状态的进程链表 11 1.1.4 进程间关系 12 1.2 Linux的线程——轻量级进程 15 1.3 进程的创建——do_fork()函数详解 19 1.4 执行进程间切换 33 1.4.1 进程切换之前的工作 33 1.4.2 进程切换实务 —— switch_to宏 37 1.4.3 __switch_to函数 39 1.5 fork与vfock系统调用的区别 42 1.6 内核线程 46 1.7 挂起状态进程的组织 49 1.7.1 等待队列头 49 1.7.2 等待队列的操作 50 1.7.3 进程资源限制 55 1.8 系统调用execve() 56 1.8.1 拷贝用户态参数 57 1.8.2 重要的数据结构 61 1.8.3 search_binary_handler函数 66 1.8.4 目标文件的装载和投入运行 69 1.8.5 库函数 92 2 中断控制 94 2.1 中断的分类 94 2.2 中断的硬件环境 95 2.2.1 外部中断请求IRQ 95 2.2.2 中断描述符表 96 2.2.3 中断和异常的硬件处理 97 2.3 中断描述符表 99 2.3.1 中断门、陷阱门及系统门 99 2.3.2 IDT的初步初始化 100 2.4 异常处理 101 2.5 中断处理 106 2.5.1 中断向量 107 2.5.2 IRQ数据结构 108 2.5.3 do_IRQ()函数 113 2.5.4 中断服务例程 115 2.5.5 IRQ线的动态分配 116 2.6 下半部分 117 2.6.1 软中断 118 2.6.2 tasklet 121 2.6.3 工作队列 122 2.7定时器中断 124 2.7.1 时钟与定时器 124 2.7.2 定时器中断相关的数据结构 127 2.7.3 定时器中断的上半部分 129 3 进程调度 138 3.1 进程调度的概念 138 3.2 进程调度的数据结构和优先级 141 3.2.1 进程的优先级 141 3.2.2 数据结构 145 3.3 调度程序所使用的函数 151 3.3.1 scheduler_tick函数 151 3.3.2 try_to_wake_up函数 156 3.3.3 recalc_task_prio函数 160 3.4 schedule()函数 163 3.4.1 直接调用 163 3.4.2 延迟调用 164 3.4.3 进程切换之前所做的工作 168 3.4.4 完成进程切换时所执行的操作 171 3.4.5 进程切换后所执行的操作 173 3.5 多处理器运行队列的平衡 175 3.5.1 调度域 176 3.5.2 rebalance_tick()函数 178 3.5.3 load_balance()函数 180 3.5.4 move_tasks()函数 183 3.6 进程退出 187 3.6.1 进程终止 187 3.6.2 进程删除 189 4 进程的并发性体现 191 4.1 内核抢占 193 4.1.1 内核抢占概念 193 4.1.2 同步技术总揽 196 4.2 每CPU变量 197 4.3 原子操作 199 4.4 优化屏障和内存壁垒 203 4.4.1 优化屏障 204 4.4.2 内存壁垒 204 4.5 自旋锁 206 4.6 读写自旋锁 211 4.6.1 为读获取和释放一个锁 213 4.6.2 为写获取或释放一个锁 214 4.7 顺序锁 215 4.8 RCU机制 217 4.9 信号量 219 4.9.1 获取和释放信号量 221 4.9.2 读/写信号量 224 4.9.3 补充信号量 225 4.10 禁止本地中断 226 4.10.1 禁止本地中断 227 4.10.2 禁止下半部(可延迟函数) 229 4.11 一些避免竞争条件的实例 231 4.11.1 引用计数器 231 4.11.2 大内核锁 231 4.11.3 内存描述符读/写信号量 232 4.11.4 slab高速缓存链表的信号量 233 4.11.5 索引节点的信号量 233 4.12 内核同步与互斥的总结 233

2011-05-30

疯狂内核之——Linux预备知识.pdf

目录 1.1 体系架构 3 1.1.1 Linux体系结构 4 1.1.2 一般程序的执行 5 1.2用户态向内核态切换 7 1.2.1 Linux的堆栈切换 7 1.2.2 80x86分段的总结 12 1.2.3 Linux的指针 14 1.3 C语言基本功 14 1.3.1 Linux内核中的链表 15 1.3.2 Linux双循环链表综合实例 29 1.4 内核汇编语言规则 30 1.4.1 GNU的x86汇编语言 32 1.4.2 嵌入式汇编语言 33 1.5 必要的硬件知识 37 1.5.1 EU模块 38 1.5.2 SU模块 39 1.5.3 PU模块 43 1.5.4 高速缓存 45 1.6 __attribute__ 机制 46 1.6.1 函数属性 46 1.6.2 变量属性 51 1.6.3 类型属性 52 1.6.4 变量属性与类型属性举例 54 1.7 必要的编译知识 55

2011-05-30

基于C++语言的GoF23种设计模式

懂了设计模式,你就懂了面向对象分析和设计(OOA/D)的精要。反之好像也可能成立。道可道,非常道。道不远人,设计模式亦然如此。 GoF 的 23 种模式研读、总结和探索,对想成为系统架构师的各位来说,意义重大。

2011-05-29

从8086到Pentium Ⅲ微型计算机及接口技术3

内容提要:   本书以Intel处理器为核心的微型计算机为背景,全面、系统、深入地介绍了微型计算机的基本组成、工作原理和实际应用,注重吸取微机发展的最新技术和最新知识,并将其融于全书之中。   全书共分10章,分别介绍微型计算机的基本知识、从8086到PentiumⅢ循序渐进地介绍了微处理器的内部结构及特点、指令系统、汇编语言程序设计、存储器、输入输出基础、中断系统、通信与接口技术、微机总线及其接口标准和微型计算机系统板等。每章后面都有大量思考题与习题。本书可作为高等院校各个专业本、专科教材,也可作为工程技术人员的参考书。   友情提示:虽然本书并未介绍的目前最新的处理器,但书籍是永远跟不上产品的发展速度的,更何况没有掌握基础的技术是绝对谈不上学会最新技术的,因此本书是很有价值的。本资料为PDF电子版,推荐采用Adobe Reader7.0或兼容阅读器在120%的显示比例下阅读! 目录 前言 第1章 概述 1.1 微型计算机的发展概况 1.2 计算机中信息的表示 1.3 微型计算机的硬件结构和基本工作原理 1.4 微型计算机的软件系统 1.5 微型计算机系统及性能指标 思考与习题 第2章 微处理器 2.1 8086/8088微处理器 2.2 80286微处理器 2.3 80386微处理器 2.4 CISC与RISC 2.5 80486微处理器 2.6 Pentium微处理器 2.7 Pentium Pro微处理器 2.8 MMX及MMX Pentium微处理器 2.9 Pentium II和Pentium III微处理器 2.10 新一代64位微处理器Merced 思考与习题 第3章 80X86指令系统 3.1 指令格式与编码 3.2 寻址方式 3.3 8086/8088指令系统 3.4 80286增强和扩充的指令 3.5 80386增强和扩充的指令 3.6 80486和Pentium增强和扩充的指令 思考与习题 第4章 汇编语言程序设计 4.1 概述 4.2 80X86宏汇编语言的数据和表达式 4.3 80X86宏汇编语言的伪指令语句 4.4 汇编语言程序设计方法 思考与习题 第5章 微型计算机中的存储器 5.1 存储器概述 5.2 半导体存储器分类及性能指标 5.3 随机存取存储器 5.4 只读存储器 5.5 存储器的扩展 5.6 微机内存层次结构 5.7 微机系统中的其他存储部件 5.8 微型计算机系统的内存管理 思考与习题 第6章 输入输出基础 6.1 概述 6.2 输入输出控制方式 6.3 I/O接口的基本结构及特点 6.4 I/O接口的读写技术 6.5 DMA控制器 思考与习题 第7章 微型计算机的中断系统 7.1 中断的基本概念 7.2 可编程中断控制器8259A 7.3 中断调用及中断程序设计 思考与习题 第8章 微机通信与接口技术 8.1 并行通信与串行通信 8.2 可编程串行通信接口芯片16550与8250 8.3 可编程并行通信接口芯片8255 8.4 可编程定时/计数器芯片8253与8254 8.5 A/D与D/A转换接口 8.6 打印机接口 8.7 显示适配器接口 8.8 软硬盘接口 8.9 调制解调器 8.10 简单实用的双机通信 思考与习题 第9章 微机总线及其接口标准 9.1 总线概述 9.2 总线层次及信号类型 9.3 ISA总线 9.4 EISA总线 9.5 VESA总线 9.6 PCI总线 9.7 AGP 思考与习题 第10章 微型计算机系统板 10.1 系统板概述 10.2 PC/XT和286系统板 10.3 386和486系统板 10.4 Pentium和PentiumⅡ/Ⅲ系统板 10.5 系统板重要元器件及接口功能介绍 10.6 微机硬件新技术 思考与习题 参考文献

2010-09-24

Linux sysfs 文件系统机制详解

Linux sys文件系统机制是非常难懂的一个机制。文章主要介绍了一些设备驱动相关的sys文件系统,结合ldd3(linux device driver 3)中的示例代码(主要是lddbus 和sculld 文件夹),详细分析虚拟文件系统sysfs,以及如何编写基于sysfs的模块化的驱动程序。使用的内核是2.6.18。

2009-12-14

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除