自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 启动shell环境

6.3 启动shell环境<br />init_post函数来自同一个文件的814行:<br /> <br />811/* This is a non __init function. Force it to be noinline otherwise gcc<br /> 812 * makes it inline to init() and it becomes part of init.text section<br /> 813 */<br /> 814static noinline int init

2011-02-01 02:52:00 2141

原创 子系统的初始化

6.2 子系统的初始化<br />所以接下来说do_basic_setup函数,任然是来自init/main.c:<br /> <br />778/*<br /> 779 * Ok, the machine is now initialized. None of the devices<br /> 780 * have been touched yet, but the CPU subsystem is up and<br /> 781 * running, and memory and process m

2011-02-01 02:49:00 3206

原创 创建1号进程

6 后start_kernel时代<br />至此,start_kernel()函数完成了Linux内核的初始化工作。几乎每天内核部件都是由这个函数进行初始化的,下面让我们再来回顾一下其中最重要的部分:<br /> <br />●  调用setup_arch()函数,根据处理器硬件平台设置系统;解析linux命令行参数;设置0号进程的内存描述结构init_mm;系统内存管理初始化;统计并注册系统各种资源;以及其它项目的初始化等。<br />●  调用sched_init()函数来初始化调度程序。<br />

2011-02-01 02:42:00 2864 5

原创 安装根文件系统

5.12 安装根文件系统<br />start_kernel下步是另一个重要的函数,678行的vfs_caches_init,用于初始化VFS那些数据结构的slab缓存,来自fs/dcache.c:<br /> <br />2355void __init vfs_caches_init(unsigned long mempages)<br />2356{<br />2357        unsigned long reserve;<br />2358<br />2359        /* Base ha

2011-02-01 02:40:00 3027

原创 走进start_kernel尾声

5.11 走进start_kernel尾声<br />中断体系建立起来后,虽然后面还有很多行代码,但是都是些比较好理解的初始化函数了,也就是说start_kernel进入尾声了。5.11.1 初始化slab的后续工作<br />继续分析start_kenel的下一个函数,613行,profile_init函数,用于对系统剖析做相关初始化,系统剖析用于系统调用:<br /> <br />int __ref profile_init(void)<br />{<br />       int buffer_byt

2011-02-01 02:36:00 3365

原创 初始化定时器中断

5.10.4 初始化定时器中断<br />回到start_kernel,612行time_init函数:<br />void __init time_init(void)<br />{<br />       late_time_init = x86_late_time_init;<br />}<br /> <br />函数x86_late_time_init实际上是初始化tsc时钟源。在time_init中只是把该函数的地址赋给全局变量late_time_init,以后某个时刻肯定会调用它的,这里先提前详

2011-02-01 02:34:00 3239

原创 软中断初始化

5.10.3软中断初始化<br />open_softirq结束后,init_timers就结束了,整个内核就可以享受时钟服务了,接下来start_kernel的609行调用hrtimers_init。由于我们没有配置CONFIG_HIGH_RES_TIMERS,所以这个函数仅仅是把全局notifier_block变量hrtimer_cpu_notify加入通知链,供将来的内核各模块使用。<br /> <br />然后,start_kernel的610行调用softirq_init来初始化整个软中断系统:<

2011-02-01 02:33:00 2463

原创 初始化本地软时钟

5.10.2 初始化本地软时钟<br />native_init_IRQ结束后,init_IRQ也就结束了,回到start_kernel中,607行,prio_tree_init函数很简单:<br /> <br />void __init prio_tree_init(void)<br />{<br />       unsigned int i;<br /> <br />       for (i = 0; i < ARRAY_SIZE(index_bits_to_maxindex) - 1; i++)<

2011-02-01 02:32:00 2527

原创 设置APIC中断服务

5.10 初始化中断处理系统<br />start_kernel接下来要做的事是初始化中断处理系统。整个内核的中断系统的核心就是我们在“初始化中断描述符表”里面设置的那个中断描述符表。而这个表的前19个表项我们已经在“初始化异常服务”中设置为了一些中断和异常的服务。内核接下来会如何设置其余的表项呢?<br /> <br />前面提到过高级可编程中断控制器APIC,这里简单地提一下它的体系结构,简单地说就是由两部分组成:本地高级中断控制器(Local APIC,LAPIC),位于每个CPU中,主要负责传递中断

2011-02-01 02:30:00 4692

原创 初始化调度程序

5.9 初始化调度程序<br />回到start_kernel函数中,mm_init()执行后,所有的绝大多数内存管理的初始化都完毕,后面的代码可以开开心心的使用Linux复杂、庞大而又高效的内存管理器了。来看下一个函数,超级重点的进程调度初始化函数sched_init()。不过自从Linux 2.6.23(2007年5月),内核引入了一种所谓的完全公平调度程序(Completely Fair Scheduler,CFS),试图按照对 CPU 时间的“最大需求(gravest need)”运行任务;这有助于

2011-02-01 02:28:00 2884

原创 初始化非连续内存区

5.8.3 初始化非连续内存区<br />回到mm_init()函数,继续走,下一个函数pgtable_cache_init (),不知道咋的,是个空函数,也许是保留着以后开发吧。最后一个函数是vmalloc_init(),来自mm/vmalloc.c:<br /> <br />1088void __init vmalloc_init(void)<br />1089{<br />1090        struct vmap_area *va;<br />1091        struct vm_stru

2011-02-01 02:27:00 2227 1

原创 初始化slab分配器

5.8.2 初始化slab分配器<br />回到mm_init()函数,继续走,下一个函数kmem_cache_init(),也是重点函数,用于初始化内核slab分配体系。这个函数来自文件mm/slab.c<br /> <br />1375void __init kmem_cache_init(void)<br />1376{<br />1377        size_t left_over;<br />1378        struct cache_sizes *sizes;<br />1379   

2011-02-01 02:25:00 2027

原创 启用伙伴算法

5.8 初始化内存管理<br />回到start_kernel,下一个函数执行mm_init()。这个函数很重要了,来自同一个文件。<br /> <br />static void __init mm_init(void)<br />{<br />       /*<br />        * page_cgroup requires countinous pages as memmap<br />        * and it's bigger than MAX_ORDER unless SPARSE

2011-02-01 02:22:00 3660 1

原创 初始化异常服务

5.7 初始化异常服务<br />继续走,start_kernel的583行,sort_main_extable,把编译期间,kbuild设置的异常表,也就是__start___ex_table和__stop___ex_table之中的所有元素进行排序。<br /> <br />584行,调用trap_init函数,重要的函数,初始化中断向量表。该函数来自arch/x86/kernel/traps.c<br /> <br />882void __init trap_init(void)<br /> 883{

2011-02-01 02:20:00 2896

原创 触碰虚拟文件系统

5.6 触碰虚拟文件系统<br />回到start_kernel中,下面我们该第一次接触文件系统了,582行执行vfs_caches_init_early:<br /> <br />void __init vfs_caches_init_early(void)<br />{<br />       dcache_init_early();<br />       inode_init_early();<br />}<br /> <br />vfs_caches_init_early调用两个函数dcache_

2011-02-01 02:19:00 2484

原创 利用early_res分配内存

5.5 利用early_res分配内存<br />回到start_kernel中,570行,page_alloc_init()函数:<br />void __init page_alloc_init(void)<br />{<br />       hotcpu_notifier(page_alloc_cpu_notify, 0);<br />}<br /> <br />这个函数会调用hotcpu_notifier函数。当然,在编译选项CONFIG_HOTPLUG_CPU起作用时,这个函数才有效。这个编译选

2011-02-01 02:13:00 2502

原创 初始化内存管理区列表

5.4 初始化内存管理区列表<br />回到start_kernel函数,569行的build_all_zonelists()函数,来自mm/page_alloc.c:<br /> <br />2815void build_all_zonelists(void)<br />2816{<br />2817        set_zonelist_order();<br />2818<br />2819        if (system_state == SYSTEM_BOOTING) {<br />2820

2011-02-01 02:11:00 3437

原创 设置每CPU环境

5.3 设置每CPU环境<br />回到start_kernel,563行调用mm_init_owner函数,将init_mm的owner字段指回init_task。这个函数可以说进入start_kernel以来最简单的函数了。继续走,setup_command_line也很简单:<br /> <br />static void __init setup_command_line(char *command_line)<br />{<br />       saved_command_line = allo

2011-02-01 02:09:00 6254

原创 scsi命令的第二次转变

1.6.6 scsi命令的第二次转变<br />一旦这种关系建立好了以后,就可以开始执行请求了。来看blk_execute_rq(),来自block/ll_rw_blk.c:<br /> <br />   2616 int blk_execute_rq(request_queue_t *q, struct gendisk *bd_disk,<br />   2617                    struct request *rq, int at_head)<br />   2618 {<br /

2011-02-01 02:02:00 3089

原创 scsi命令的第一次转变

1.6.5 scsi命令的第一次转变<br />前面介绍了读写文件时,是通过sd_init_command设置的scsi_cmnd命令结构,其实我们也可以通过scsi_execute_req函数直接发送scsi命令,不过需要两次转变。<br /> <br />仍然以scsi磁盘举例,最初scsi这边发送的是scsi命令,可是从block走就得变成request,然而走到磁盘那边又得变回scsi命令,换言之,这整个过程scsi命令要变两次身。<br /> <br />比如,我们想获得磁盘的容量,就可以直接调用

2011-02-01 01:59:00 5613

原创 scsi命令的执行

1.6.4 scsi命令的执行<br />负责执行具体scsi命令的函数是scsi_dispatch_cmd,来自drivers/scsi/scsi.c:<br /> <br />    468 int scsi_dispatch_cmd(struct scsi_cmnd *cmd)<br />    469 {<br />    470         struct Scsi_Host *host = cmd->device->host;<br />    471         unsigned lon

2011-02-01 01:56:00 3770

原创 scsi命令的执行

1.6.4 scsi命令的执行<br />负责执行具体scsi命令的函数是scsi_dispatch_cmd,来自drivers/scsi/scsi.c:<br /> <br />    468 int scsi_dispatch_cmd(struct scsi_cmnd *cmd)<br />    469 {<br />    470         struct Scsi_Host *host = cmd->device->host;<br />    471         unsigned lon

2011-02-01 01:24:00 4238

原创 scsi块设备驱动层处理

1.6.3 scsi块设备驱动层处理<br />好了,了解完必要的scsi设备驱动知识以后,我们就可以安心分析scsi_request_fn函数了。大家回忆一下对,这个函数指针通过几次传递并最终在blk_init_queue_node()中被赋予了q->request_fn。所以这一层的重点就是这个scsi_request_fn函数。<br /> <br />在看scsi_request_fn之前,注意回忆一下scsi_alloc_queue函数的1598行至1560行还赋了三个函数指针:<br /> <b

2011-02-01 01:01:00 10450 3

原创 scsi设备驱动体系架构

1.6.2 scsi设备驱动体系架构<br />从这一层开始,整个文件读写的中心将由request转向scsi的命令结构scsi_cmnd。那么这个命令结构到底是怎么一回事呢,这还得从SCSI架构谈起。SCSI 实现了一种客户机/服务器风格的通信架构,发起者向目标设备发送命令请求。该目标处理此请求并向发起者返回响应。发起者可以是托管计算机中的一个 SCSI 设备,而 SCSI 目标则可以是一个磁盘、光盘和磁带设备或特殊设备(比如箱体设备)。<br /> <br />这里要提到一个概念——Lower Leve

2011-02-01 00:37:00 11827 1

原创 scsi总线驱动的初始化

1.6.1 scsi总线驱动的初始化<br />块设备底层驱动的核心是scsi总线层驱动,在总线层驱动之上为各种不同的scsi设备驱动,在总线层驱动之下为scsi host驱动。其在内核中的位置如下图所示:<br /><br /> <br /><br /><br />前面我们已经知道了上三层的工作,接下来大部分知识来自底下三层。<br /> <br />在Linux中scsi驱动基本分为三大层:top level,middle level以及lower level。top level为具体的scsi设备驱动

2011-02-01 00:30:00 17452 5

原创 真实的I/O调度层处理

1.5.6 真实的I/O调度层处理<br />现在我们块设备也有了,队列也有了,要提交请求也就可以开始提交了。那就让我们回到generic_make_request来研究一下如何提交请求如何处理请求吧。我们看到,函数最后调用q->make_request_fn(q, bio)。对 make_request_fn 函数的调用可以认为是 IO调度层的入口,该函数用于向请求队列中添加请求。该函数是在创建请求队列时指定的,代码如下(blk_init_queue 函数中):<br />q->request_fn =

2011-02-01 00:22:00 7130

原创 块设备I/O调度程序

1.5.5 块设备I/O调度程序<br />我们建立请求队列建的目录是,当向请求队列增加一条新的请求,即产生一个request数据结构时,通用块层会调用I/O调度程序来确定该新request将在请求队列中的确切位置。I/O调度程序试图通过扇区将请求队列排序。如果顺序地从链表中提取要处理的请求,那么就会明显减少磁头寻道的次数,因为磁头是按照直线的方式从内磁道移向外磁道(反之亦然),而不是随意地从一个磁道跳跃到另一个磁道。<br /> <br />这就是著名的电梯算法,回想一下,电梯算法处理来自不同层的上下请求

2011-02-01 00:17:00 9147 2

原创 为设备建立请求队列

1.5.4 为设备建立请求队列<br />好啦,磁盘和分区建立好了,block_device数据结构也关联起来了,回到add_disk中,我们需要调用第三个函数了,也就是blk_register_queue(disk),来建立请求队列与bio等数据结构了,让我们来仔细分析。<br /> <br />   4079 int blk_register_queue(struct gendisk *disk)<br />   4080 {<br />   4081         int ret;<br />  

2011-02-01 00:14:00 3302

原创 关联block_device结构

1.5.3 关联block_device结构<br />接下来是register_disk函数,来自fs/partitions/check.c:<br /> <br />    473 /* Not exported, helper to add_disk(). */<br />    474 void register_disk(struct gendisk *disk)<br />    475 {<br />    476         struct block_device *bdev;<br /

2011-02-01 00:11:00 5320

原创 建立块设备驱动环境

1.5.2 建立块设备驱动环境<br />上一节内容反映的是系统上电后,Linux初始化块设备子系统并注册了相应的块设备驱动的内容。而当我们把一块300G的硬盘插入总线的SCSI插槽中时,SCSI设备对应的probe程序就会调用alloc_disk()函数为其分配gendisk结构。<br /> <br />那么SCSI设备对应的probe程序到底是什么呢?设备驱动的研究是有一定套路的,比如说我们这里的scsi吧,必须在drivers/scsi目录下看它的Kconfig和Makefile文件。根据文件中的内

2011-02-01 00:08:00 3638

原创 块设备的初始化

1.5 块设备I/O调度层的处理<br />下面进入块设备I/O调度层,来看看q->make_request_fn方法。不过这个方法的具体函数是什么呢?别着急,要弄清这个问题还需要再补充一下块设备驱动的基础知识,不然就又走不下去了。块设备驱动程序是Linux块子系统中的最底层组件。它们从I/O调度程序中获得请求,然后按要求处理这些请求。<br /> <br />当然,块设备驱动程序是设备驱动程序模型的组成部分(也就是在sysfs中能够看到它)。因此,每个块设备驱动程序对应一个device_driver类型的

2011-02-01 00:03:00 3637 2

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关注的人

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