随笔分类 -  Linux kernel

摘要:前言 目前linux中包含anticipatory、cfq、deadline和noop这4个I/O调度器。2.6.18之前的linux默认使用anticipatory,而之后的默认使用cfq。我们在前面编写简单的ramdisk(有请求队列)中分配请求队列使用了blk_init_queue函数,该函数会默认该请求队列分配一个调度器,这里我们打算不使用该函数默认分配给请求队列的调度器,而是使用noop调度器。noop顾名思义,是一个基本上不干事的调度器。它基本不对请求进行什么附加的处理,仅仅假惺惺地告诉通用块设备层:我处理完了。但与吃空饷的公仆不同,noop的存在还是有不少进步意义的。至少我们现. 阅读全文
posted @ 2014-02-16 21:39 在于思考 阅读(1312) 评论(0) 推荐(1) 编辑
摘要:前言 前面用无请求队列实现的ramdisk的驱动程序虽然申请了请求队列,但实际上没用上,因为ramdisk不像实际的磁盘访问速度慢需要缓存,ramdisk之间使用内存空间,所以就没用请求队列了。本文将介绍使用请求队列的ramdisk驱动,虽然对于ramdisk使用请求队列用处不大,但对于基于磁盘的块设备驱动来说却是必须要用的。 在LDD3书中,其中的有些块设备操作函数在当前的linux版本中有了很大的变动,需要自己重新根据新定义的一些函数进行适当的移植,以解决编译时报出的各种错误,主要是在请求处理函数中修改。设置请求队列的请求处理函数 在前面用无请求队列实现的ramdisk的驱动程序中直... 阅读全文
posted @ 2014-02-14 21:40 在于思考 阅读(2249) 评论(0) 推荐(1) 编辑
摘要:最近在研究块设备驱动的编写,看了赵磊大牛的《写一个块设备驱动》,受益匪浅,虽然能看懂里面说的,但动手写写代码还是能加深理解的,下面实现的ramdisk写的很简单,如果有错误,欢迎大牛们指正哈!分配一块内存区存放ramdisk数据 为了简单,我直接静态分配了一个大小为16MB的内存区,当然对于编写驱动来说这个空间有点大。不过就是为了简单嘛,可以理解。#define SIMP_BLKDEV_BYTES (16 * 1024 * 1024)unsigned char simp_blkdev_data[SIMP_BLKDEV_BYTES];分配一个请求队列 可以通过函数b... 阅读全文
posted @ 2014-01-11 11:08 在于思考 阅读(2443) 评论(4) 推荐(1) 编辑
摘要:1Linux3.10.21内核系统调用设置 以前看的内核版本时2.6.11的,里面的系统调用设置一目了然啊!在文件entry.S中直接定义了sys_call_table表,并在这个文件中用各个系统调用函数的地址初始化了这个表。今天看了下3.10.21的内核,想自己添加个系统调用到这个内核里面,没想到看了半天还是在云里雾里中,只知道sys_call_table表的定义在文件/usr/src/linux-3.10/arch/x86/kernel/syscall_32.c中,当具体怎么初始化这个表的还是不知道。找了半天都没找到表sys_call_table初始化的地方,后来回到syscall_32. 阅读全文
posted @ 2013-12-24 16:45 在于思考 阅读(3396) 评论(0) 推荐(0) 编辑
摘要:一、为什么要使用模块 由于linux使用的是整体结构,不是模块化的结构,整体结构实现的操作系统可扩展性差。linux为了扩展系统,使用了模块的技术,模块能够从系统中动态装入和卸载,这样使得linux也具有很好的可扩展性。二、linux中哪些代码作为模块实现,哪些直接编译进内核? 当然我们是尽量把代码编译成模块,这样就可以根据需要进行链接,内核的代码量也会少很多。几乎所有的高层组件—文件系统、设备驱动程序、可执行格式、网络层等等—都可以作为模块进行编译。 然而有些代码确必须直接编译进内核。这些代码通常是对数据结构或者函数进行修改。如内核中已经定义好了的数据结构,如果要改变这个数据结构... 阅读全文
posted @ 2013-11-19 20:33 在于思考 阅读(2356) 评论(2) 推荐(1) 编辑
摘要:一、为什么需要异常表? 处于内核态的程序有下面四种情况会产生缺页异常: 1、内核试图访问属于进程地址空间的页,但是,该页对应的页框不存在或者内核试图去访问一个只读的页,分别对应“请求调页”和“写时复制”两种情况。 2、内核寻址到属于内核地址空间的页,但是相应的页表项没有被初始化,这个对应“非连续内存区访问”。 3、内核代码包含编程错误,函数执行产生异常,这是一个内核漏洞。 4、系统调用服务例程试图读写一个内存区,而该内存区的地址是通过系统调用参数传递过来的,但确不属于进程的地址空间。 前面两种情况缺页异常处理程序很容易识别出来,但是后面两种情况却比较难区分。为了识别出后面的两种情况... 阅读全文
posted @ 2013-11-18 10:47 在于思考 阅读(3782) 评论(1) 推荐(2) 编辑
摘要:为什么要使用bootmem分配器,内存管理不是有buddy系统和slab分配器吗?由于在系统初始化的时候需要执行一些内存管理,内存分配的任务,这个时候buddy系统,slab分配器等并没有被初始化好,此时就引入了一种内存管理器bootmem分配器在系统初始化的时候进行内存管理与分配,当buddy系统和slab分配器初始化好后,在mem_init()中对bootmem分配器进行释放,内存管理与分配由buddy系统,slab分配器等进行接管。 bootmem分配器使用一个bitmap来标记物理页是否被占用,分配的时候按照第一适应的原则,从bitmap中进行查找,如果这位为1,表示已经被占用... 阅读全文
posted @ 2013-11-16 20:35 在于思考 阅读(5230) 评论(3) 推荐(1) 编辑
摘要:一、linux中的每cpu变量 看linux内核代码的时候,会发现大量的per_cpu(name, cpu),get_cpu_var(name)等出现cpu字眼的语句。从语句的意思可以看出是要使用与当前cpu相关的一个变量,不过查看这个变量的定义,总是有这样一个宏:DEFINE_PER_CPU(type, name),将这个宏展开成下面的语句: __attribute__((__section__(".data.percpu"))) __typeof__(type) per_cpu__##name,这个语句就是在.data.percpu段中定义type类型的per_cpu# 阅读全文
posted @ 2013-11-03 15:20 在于思考 阅读(3581) 评论(0) 推荐(0) 编辑
摘要:内核模块是Linux内核向外部提供的一个插口,其全称为动态可加载内核模块(Loadable Kernel Module,LKM),我们简称为模块。Linux内核之所以提供模块机制,是因为它本身是一个单内核(monolithic kernel)。单内核的最大优点是效率高,因为所有的内容都集成在一起,但其缺点是可扩展性和可维护性相对较差,模块机制就是为了弥补这一缺陷。很多驱动程序都以模块的形式存在,用户可以有选择的加载需要的驱动程序。一、什么是模块 模块是具有独立功能的程序,它可以被单独编译,但不能独立运行。它在运行时被链接到内核作为内核的一部分在内核空间运行,这与运行在用户空间的进程是不同... 阅读全文
posted @ 2013-10-28 17:21 在于思考 阅读(2371) 评论(0) 推荐(1) 编辑
摘要:看了《深入理解linux内核》的中断与异常,简单总结了下,如果有错误,望指正! 一 什么是中断和异常 异常又叫同步中断,是当指令执行时由cpu控制单元产生的,之所以称之为异常,是因为只有在一条指令结束之后才发出中断(程序执行异常或者系统调用)。 中断又叫异步中断,是由其他硬件设备依照cpu时钟信号随 阅读全文
posted @ 2013-10-21 17:16 在于思考 阅读(4757) 评论(4) 推荐(1) 编辑
摘要:linux2.6.11的内核中,为了方便管理linux的进程,主要建了5种linux链表。每个链表节点之间的互联有两种方式,一种是hash节点之间的互联,通过hlist_node的数据结构来实现;另一种就是list_head类型的数据结构来互联。看linux内核的人对这两种类型的数据结构肯定是不会陌生的,因为它们在linux内核中无处不在。1 进程直接的互连 通过任务描述符结构task_struct结构中的tasks成员来实现各个节点之间的互连,它是list_head类型。这个链表是一个循环的双向链表,开始的时候只有init_task这一个进程,它是内核的第一个进程,它的初始化是通过静态... 阅读全文
posted @ 2013-10-18 19:19 在于思考 阅读(3969) 评论(0) 推荐(0) 编辑
摘要:以下只是个人看了《linux内核完全注释》的一点理解,如果有错误,欢迎指正!1 eip中保存的地址是逻辑地址、线性地址还是物理地址? 这个应该要分情况。eip保存的是下一条要执行的指令地址,也就是说cpu是根据eip到内存中去寻找指定的内容。如果cpu工作在实模式,那么eip保存的就是物理地址;如果cpu工作在保护模式下,那么cpu在去内存寻找指定的内容之前要先将eip加上当前程序代码段的基址(通过当前cs所指向的代码段描述符获得),即获得当前程序的线性地址,如果cpu没有开启分页机制,那么这个线性地址就是实际的物理地址了;如果cpu开启了分页机制,那么就要通过线性地址查找页目录表和页表... 阅读全文
posted @ 2013-10-08 10:59 在于思考 阅读(3725) 评论(6) 推荐(4) 编辑
摘要:今天看了于渊的《自己动手写操作系统》中的第一章,怎样10分钟写个操作系统,这个操作系统其实就是一个启动程序。 当计算机电源被打开后,它会先进行加电自检(POST),然后寻找启动盘,如果是选择从软盘启动,计算机就会查找软盘的0面0磁道1扇区,如果发现它以0xAA55结束,则BIOS认为它是一个引导扇区,然后BIOS就会把引导扇区的前512字节的引导代码拷贝到内存的0000:7c00处并将控制器彻底交给这段引导代码。 简单的引导代码如下所示: 1 org 07c00h ;告诉编译器加载到07c00h处 2 3 mov ax, cs 4 mov ds, a... 阅读全文
posted @ 2013-04-22 19:30 在于思考 阅读(4900) 评论(3) 推荐(0) 编辑
摘要:最近看了本书,突然对于地址空间有些疑惑。在深入理解linux内核中把地址分为三类:逻辑地址(汇编语言中操作数地址或指令的地址,对于80x86的cup,逻辑地址是段+段内偏移地址)、线性地址(也叫虚拟地址)和物理地址。但在Stott Maxwell的《Linux Core Kernel Comment 阅读全文
posted @ 2013-04-17 19:56 在于思考 阅读(11484) 评论(1) 推荐(4) 编辑
摘要:1 红黑树的定义 (1)每个节点或者为黑色,或者为红色。 (2)根必须为黑色。 (3)每个叶子节点(不包含关键字的节点)都是黑色。 (4)如果有一个节点是红色,那么它的两个儿子都是黑色。 (5)对于每个节点,从该节点出发到其子孙节点的所有路径上包含相同数目的黑节点。 满足上面5个条件的树就是一颗红黑树,红黑树有着很好的性质,它类似于平衡二叉树(AVL)。一颗红黑树的高度不会超过2lg(n+1),而且插入和删除操作较AVL更快,由于它分别最多做2次和3次旋转来维护树的性质,所以在linux内核中大量使用了红黑树,如ext3文件系统中使用红黑色来记录目录项,虚拟内存区也是使用它来记录的... 阅读全文
posted @ 2013-04-06 11:05 在于思考 阅读(6239) 评论(0) 推荐(4) 编辑
摘要:1 内存地址 逻辑地址:包括在机器语言指令中指定操作数或者一条指令的地址。每个逻辑地址都由一个段选择符和偏移量组成,偏移量指明了从段开始的地方到实际地址的距离。 线性地址:也称为虚拟地址,32位的无符号整数,程序所能使用空间的大小。 物理地址:它与内存地址总线上的数目相同,主要用于内存单元的寻址。 内存控制单元(MMU)通过分段单元的硬件电路把一个逻辑地址转换为线性地址;接着通过分页单元的硬件电路把线性地址转换为一个物理地址(如图1.1)。图1.1 在多处理器的系统中,由于在RAM芯片上的读或写操作必须是串行地执行,所以内存中有个内存仲裁器,当CPU访问的RAM芯片空闲时,就准予访... 阅读全文
posted @ 2013-04-03 19:20 在于思考 阅读(2379) 评论(0) 推荐(1) 编辑