操作系统
文章平均质量分 84
庾志辉
这个作者很懒,什么都没留下…
展开
-
x86汇编--保护模式下的冒泡排序
其实这个代码本身(冒泡排序)没有什么意思,而有用的是怎么从实模式下进入保护模式,以及怎么 使用段选择子和段描述符。原创 2014-12-19 15:55:03 · 1984 阅读 · 0 评论 -
Linux上电初始化--BOSI启动和boot环境设置
BIOS:上电启动时,最开始由硬件控制进入BIOS,BIOS代码一般存放在0xfe000~0xfffff最后几kb中; 启动中cs:eip == 0xffff:0x00000 === 0xffff0 这是最开始启动的(BIOS执行的第一条指令)下面是BIOS程序执行的内容:1、在0x00000处开始的1kb内存空间(0x00000~0x003fff)安装中断向量表(256个中断,c原创 2015-01-15 18:08:08 · 1952 阅读 · 0 评论 -
Linux内核源码分析--内存管理(一、分页机制)
最开始的地方是在head汇编中,如果看boot中那三个汇编的应该记得(那三个汇编还是比较重要的)。首先是分页机制,在CR0的第31位(PG位)置1表示开启分页机制,顺便也介绍下其他几个控制寄存器:CR1保留,没用;CR2 用来记录页面异常时线性地址(不懂没关系,后面会介绍);CR3 当前CPU使用的页目录表的地址(有此可见系统中不仅仅只有一个页目录表,但是在某一时刻有效的页目录表只有一个);当然有关页面操作的前提是CR0的第31位必须打开,也就是必须是在分页机制开启的时候那几个控制寄存器才有效。原创 2015-01-22 16:30:52 · 5566 阅读 · 4 评论 -
Linux内核源码分析--系统时间初始化(kernel_mktime()函数)
从boot文件中的几个汇编程序执行后跳转到init文件中的main.c程序开始继续执行,该main.c函数式为系统运行的环境进行初始化的。首先来看系统时间的初始化(因为系统时间的初始化开始程序就在init文件中),其中主要还是由kernel中的mktime.c程序中的kernel_mktime函数计算时间的。 先看下time_init(void)函数及相关结构是怎么实现的:原创 2015-01-19 23:14:24 · 3816 阅读 · 0 评论 -
Linux内核源码分析--文件系统(二、高速缓存区)
从块设备中读取数据是很慢的(I/O操作相对于内存操作来说是比较慢的),所以为了不让CPU浪费宝贵的时间来等待读取块设备上的数据,就在内存中开辟了一段内存地址用来预获取最近使用过的多块设备块上的数据。当CPU需要访问块设备上的数据时,首先会在缓冲区中查找,如果有幸能找到,那么就直接拿过来使用;如果找不到就没办法,需要从块设备上把查找的数据块读取到高速缓存中(一般会多读取几个存放起来),然后CPU再从高速缓存区中读取需要的数据块;所以总结来说CPU只读内存上的数据,如果要读块设备上的数据,必须先放到高速缓存中,原创 2015-02-09 22:14:06 · 4601 阅读 · 0 评论 -
Linux内核源码分析--文件系统(三、buffer.c)
前面已经大概的分析了下高速缓存区相关知识,这里再来分析下几个重要的函数;1、清缓存:把缓存区数据和设备进行同步; 2、缓存块插入到双链表/hash链表中,从双链表/hash链表中删除缓存块; 3、查找缓存块号; 4、从设备上读取数据到缓存中; 5、缓存区初始化函数;原创 2015-02-10 14:52:56 · 3672 阅读 · 0 评论 -
Linux内核源码分析--文件系统(四、Bitmap.c)
总结的来说其实Bitmap.c程序就是操作文件系统中的两个位图:i节点位图和逻辑块位图;拿逻辑块位图来说吧,申请一个新的逻辑块时,首先是在8块逻辑块位图中查找一个空闲的比特位,找到以后转换成逻辑块号,然后就通过逻辑块号找到真正的逻辑块,通过函数把该逻辑块映射到缓存区中,当然最后要对缓存区做些属性设置;释放一个逻辑块时也一样,首先做些检查,然后释放缓存块,最后也是设置下逻辑块位图(当然也是根据逻辑块号转换成8块逻辑块位图中的某个比特位)。原创 2015-02-21 16:17:41 · 3025 阅读 · 0 评论 -
Linux内核源码分析--文件系统(八、Block_dev.c)
由于是块设备的读写操作,所以每一次都是以块为单位(1024)进行操作;pos是文件的位置光标,用pos可以得到文件现在所处在哪块逻辑块上,并且在该逻辑块上偏移了多少。再根据块的大小 可以得到该逻辑块还剩下多少空间。最后跟需要写入的字符数比较,如果该逻辑块剩下的空间足够存放需要写入的字符,则读取该逻辑块到缓存区,然后进行数据的写入;否则,先填满逻辑块剩下的空间,然后再读取下一个逻辑块;原创 2015-03-26 14:27:29 · 2421 阅读 · 0 评论 -
Linux内核源码分析--文件系统(九、File_dev.c)
file_dev.c程序是用于访问文件数据的读写程序;file_read() int file_read(struct m_inode * inode, struct file * filp, char * buf, int count)函数,从i节点为inode的文件中 filp中pos位置处开始读取count个字节数据存放到用户空buf内 功能:从i节点为inode的文件中 filp中pos处开始读取count个字节数据存放到用户空间buf处 参数:in原创 2015-03-26 15:41:46 · 2088 阅读 · 0 评论 -
Linux内核源码分析--文件系统(七、Namei.c)
1、功能和stncmp()函数一样,都是对指定字符串进行比较。比较指定长度len的name和de结构体中的name进行比较,相等返回1,否则返回0; //字符串匹配,参数分别为:比较长度,文件名指针,目录项结构体static int match(int len,const char * name,struct dir_entry * de){ register int same __原创 2015-03-04 15:02:25 · 3729 阅读 · 0 评论 -
Linux内核源码分析--文件系统(六、Super.c)
1、释放指定设备的超级块:首先是对设备块号检查以及检查设备块号对应的超级块的合法性;然后释放8块i节点位图和逻辑块位图,最后释放掉超级块;//释放指定设备的超级块,//释放设备所使用的超级块数组项(s_dev=0),并释放该设备i节点位图和逻辑块所占用的高速缓存块//如果超级块对应的是文件系统根文件系统,或者其i节点上已经安装其他的文件系统,则不能释放该超级块void put_super原创 2015-02-26 17:07:06 · 4439 阅读 · 0 评论 -
Linux内核源码分析--文件系统(五、Inode.c)
//把文件上的数据存放在磁盘上,inode 文件i节点;block 文件中数据块号,create是否创建标志static int _bmap(struct m_inode * inode,int block,int create){ struct buffer_head * bh; int i;//判断文件数据块号block是否超出范围 if (block<0) panic("_原创 2015-02-26 10:54:41 · 5848 阅读 · 1 评论 -
Linux中的函数间跳转:setjmp()和longjmp()
先来看个实例吧,在 用c++写的简易学生通讯录中有那么个实例:删除通讯录中某个人的号码;1、开始是主页面菜单函数,选择删除功能后;2、跳转到删除信息函数中,在这个函数中还要先调用查找函数;3、在查找函数中又要判断以什么方式查找(姓名还是学号);4、选择好查找方式以后,查找到该人信息返回;5、打印信息再次确认是否真的需要删除这些信息;6、删除后返回到主页面菜单函数; 一个删除功能嵌套调用了这么多函数,假如在某个函数中出错了(或者我在第5步取消删除),又要一层层的返回。幸好Linux中提供了se原创 2015-02-28 11:35:21 · 1593 阅读 · 0 评论 -
x86架构中特权级
特权级,可以分为三种;第一、描述符中的特权级DPL,表示这个段的特权;第二、选择子的RPL表示请求方的特权级;第三、当前特权级,表示正在执行的代码段所具有的特权;下面有关特权级知识的总结: 第一、对于数据段来说,特权级DPL表示了可以访问该数据的最低特权。若数据段的DPL为1,那么只有特权级为0或1的程序才能访问他; 第二、特权指令,为了安全和效率有些指令是只能原创 2015-01-04 17:45:22 · 2876 阅读 · 0 评论 -
x86架构下的系统段描述符格式
如果还记得前面的GDT全局描述符表的话,那么一定不会忘记段描述符中有个s字段,若为0,则表示这个描述符是系统段,若为1,则是普通的段描述符;普通的段为ds,es,ss,cs等等,系统的段则有GDT,调用门,TSS,LDT等等。现在来看看几个系统段描述符格式; -------------------------------------------------------------原创 2015-01-04 21:58:47 · 2764 阅读 · 0 评论 -
BCD码转换成二进制和ASCII码
BCD码转换成二进制和ASCII码;用BCD码表示:十位上的十进制数为 2 == BCD码表示为 0010;个位上的十进制数9 === BCD码表示为 1001;所以总的来说 十进制数 29 用BCD码表示为:0010 1001;转换过程:把BCD码 0010(十进制数为十位上的 2)右移4位(其实表示当作一个个位数,或者说单纯的数值),然后乘以10 还原到十进制的权重(因为这个数本来表示的就是十进制数中的十位)。处理完十位上的数,接着处理个位上的数。因为BCD码的权重和二进制的前四位权重是一样(2^n,n原创 2015-01-17 16:32:10 · 34233 阅读 · 3 评论 -
x86汇编--微内核设计
微内核程序:微内核程序就稍微复杂点了,还是按步骤分析下:1、设计一个打印例程,就是把字符串打印到屏幕终端,用来显示一些提示信息;2、后面都是用来加载用户程序了,其实说到底微内核就是为各个用户程序提供环境,和加载执行用户程序,不过这简单的里面却还是比较复杂的;3、首先只加载用户程序的头部程序到内核临时内存中,然后分析整个用户程序的大小,最后把所有的用户程序都加载到指定位置;4、在上一步中还漏了一步,就是当指定用户程序大小后,需要向内核申请一个同样大小的空间用来存放它。其实这就是简单内存管理;5、开始为用户程序原创 2014-12-27 10:03:12 · 1768 阅读 · 0 评论 -
Linux 新内核中主次设备号范围
作者:李强,华清远见嵌入式学院讲师。 设备驱动中,设备号设一个很重要的概念和变量。不论是主设备号,还是次设备号,在设备驱动中都占据了很重要的地位。那么他在Kernel中是如何操作的?这个数据结构都是通过那些函数可以很容易的在我们写Linux设备驱动模块时被我们所使用呢? 在include/linux/type.h文件中我们能看到一个关于dev_转载 2015-01-28 15:58:02 · 1980 阅读 · 0 评论 -
x86汇编--程序加载器
加载器程序就是如何把一个程序从磁盘上加载到内存空间执行:步骤思考(实模式下的加载器): 第一、确定从磁盘哪个扇区中加载,以及加载到内存中的什么地方; 第二、最基本的设置数据段,和堆栈段,代码段一般不用设置(跳转的时候已经设置了); 第三、读取要加载的文件的头文件(大小一般不超过512字节,视情况而定),一般头文件包含:程序大小,入口地址,段的数量,要调整的段基地址; 第四、分析头文件,读取剩余扇区内容; 第五、调整头文件中各个原创 2014-12-05 16:32:44 · 2851 阅读 · 0 评论 -
x86架构保护模式下界限问题
在保护模式下有很多界限问题,下面集中来看下: 若段界限是0xFFFFF,粒度是4KB,那么实际界限值是多少?若粒度G=0,那么段界限就是实际的界限值;但粒度为4KB,那么界限值就是:(描述符段界限 + 1)× 4KB - 1;为什么会这样?因为段界限是段长度减去1,若粒度G=0,那么段界限就是实际的界限值;若为4KB,则段长度是:(描述符界限 + 1)× 4;然后再减去1;所有:原创 2015-01-04 17:13:39 · 1772 阅读 · 1 评论 -
x86架构中的保护模式
在x86架构中所谓保护模式其实就是段的存储方式能够达到一种保护机制。也正因为有了保护模式(段的存储方式)所以才会有特权模式,以及后面的多任务之说; 在实模式下段的存储很简单,就是代表一个段基地址;如:ds(ds=0x7c00),那么数据段的基地址就是0x7c00;再比如:ds:ax(ds=0x0000;ax=0x7c00)那么段基地址就是0x00;物理地址就是:(ds * 16)原创 2015-01-04 09:38:28 · 3339 阅读 · 1 评论 -
as汇编基础程序设计--调用C库和内存访问
as汇编中的内存访问:movl (%ebx), eax(把ebx寄存器指向的地址上的值传送给eax);movl 4(%ebx), eax(把ebx指向的地址的位置往上偏移4字节的地址上的值传送给eax中);movl -4(%ebx),eax(把ebx执行的地址位置往下偏移4个字节的地址上的值传送给eax);movl 4(%ebx, %ecx, 4), eax (把 ebx+4*ecx+4地址上的数据传送给eax);这样一解释,上面的movl $2, 4(%edi),movl (%edi, %ecx, 4),原创 2015-01-09 16:13:16 · 1453 阅读 · 0 评论 -
as汇编基础程序设计--gdb调试汇编
开始命令:gdb test; 设置断点:break *_start + 1(cpu运行到 _start+1 的地址上会停止,break可以简写b) 开始运行:run (会运行到第一个断点位置上,一般和断点一起使用) 单步调试:step (会一行一行执行代码,遇到函数会进入函数中执行,step可以简写s) 单步调试:next (和上面的命令类似但,但遇到函数不会进入,直接跳过函数,next可以简写n) 顺序执行:cont (当原创 2015-01-10 17:08:50 · 2647 阅读 · 0 评论 -
as汇编基础程序设计--基础知识点
1、数据类型,as汇编和C语言类似,也有数据类型之分。数据类型为了区分数据存放所需要的空间(也就是字节数),浮点型操作没怎么了解,浮点型操作时对数据类型应该有特殊的限制。.section .data output: .ascii "xxxxx%d\n" (后面不添加'\0') .asciz "xxxxxx%d\n" (后面添加'\0') .int 2,3,4原创 2015-01-14 10:29:04 · 1163 阅读 · 0 评论 -
C程序代码中内嵌as汇编(四、宏函数)
先来回忆下C语言中宏是怎么定义的,最基本的是定义常量:#define MAX_LEN 1024 这是最简单的常数宏定义,其中宏名按规定是要大写的,宏名在预编译时会由后面的值替代掉(预编译四大步骤:1、用宏名后面的值替换宏名;2、加载包含的头文件内容;3、判断逻辑假,并且去掉逻辑假代码;4、删除注释)。 C语言中宏函数定义格式:#define FUN_NAME(a, b, c)原创 2015-01-16 15:15:36 · 2077 阅读 · 0 评论 -
C程序代码中内嵌as汇编(一、基础知识)
汇编代码是最接近机器码,所以也是执行效率最高的,在操作系统中有将近10%的关键性代码是由汇编编写的,而还有部分代码是由C代码嵌入汇编构成的。C代码中嵌入汇编可以提高程序的执行效率,同时这种程序还既有高级语言的特性,可以灵活的和其他模块进行配合工作; c程序内嵌as汇编有比较多的规则,可以从最简单、最基本的开始学起直到后面学习现在通用的内嵌方式。原创 2015-01-14 14:51:06 · 1777 阅读 · 0 评论 -
AT&T风格的基础汇编程序--Hello word
为了看懂Linux内核源代码,所以不得不重新学习下汇编语言。汇编语言大体可以分为两个风格,官方的intel风格和unix系列的AT&T风格。Intel风格汇编是比较常见的,一般大学时会学习点基础的(至少我大学时学过点基本指令),这一类代表性的有NASM汇编、as86等(我熟悉的就只有NASM汇编,不过这一类汇编都大同小异)。而AT&T风格的汇编是比较少见的,一般只有做Linux开发的才会接触,尤其是做linux c语言开发的,有时候为了追踪代码,迫不得已编译成汇编来检查(如果在Linux下用C语言开发过的,原创 2015-01-08 17:10:30 · 2218 阅读 · 0 评论 -
x86汇编--RTC中断(时间显示器)
可以用前一篇操作系统内核加载器(x86汇编)的加载器来加载这个RTC中断程序,就可以显示时间了。原创 2014-12-11 17:03:51 · 2844 阅读 · 0 评论 -
as汇编基础程序设计--函数设计及函数堆栈传参问题
其实上面的重点是 .type print_fun, @function ,这是定义函数的方式,后面一般接着是函数入口地址标识符;函数传参问题: 在as汇编和C语言中函数调用时传参的标准是使用堆栈来操作的,而有些其他汇编(如:ARM汇编)是通过ax,bx等,当参数超过4个参数时用堆栈进行压栈传入。来模拟下传参问题(假设有三个参数):原创 2015-01-14 10:57:20 · 1806 阅读 · 0 评论 -
C程序代码中内嵌as汇编(二、占位符)
本篇blog只给几个例题来进行快速学习内嵌as汇编。 第一、输入参数中包含输出参数 #include int main(void) { char string1[]={"this is yzh test code!"}; int len = 25; char string2[30]= {'\0'}; //asm volatil原创 2015-01-14 16:59:54 · 2118 阅读 · 0 评论 -
C程序代码中内嵌as汇编(三、跳转)
在内联汇编中使用跳转语句是非常常见的,比如:比较两个数,返回较大数时,就会用到跳转;先看下汇编和运行结果,然后再一步步分析下: 运行结果: 代码分析: #include void fun(int a, int b) { printf("a=%d原创 2015-01-14 18:16:34 · 4680 阅读 · 1 评论 -
ubunte中用ibus-setup安装中文输入法
(process:2553): Gtk-WARNING **: Locale not supported by C library. Using the fallback 'C' locale.Traceback (most recent call last): File "/usr/share/ibus/setup/main.py", line 582, in <module> locale.setlocale(locale.LC_ALL, '') File "/usr/lib/原创 2015-06-09 23:15:43 · 2556 阅读 · 0 评论