Linux/kernel
文章平均质量分 72
剑圣风暴
说法是否速读法啊但是发生
展开
-
再谈分页
Linux0.11最多支持64个任务,而每个进程拥有的线性空间为64M,64*64M=4G,所以这64个任务刚好填满4G的线性空间。对于一个任务所独占的64M空间并不是说它就一定需要64M的物理内存。linux0.11设计的物理内存只有16M,除去内核以及高速缓冲区占用的4M,就只剩12M给用户进程,至于为什么拥有64M线性空间的进程能够在12M的物理内存甚至4M内存中运行,一方面原因在于通常实际原创 2014-12-16 15:37:09 · 742 阅读 · 0 评论 -
linux0.11进程睡眠sleep_on函数和唤醒wake_up函数分析
内核中的这两个函数主要用于访问资源时的同步操作,典型的例子就是高速缓冲区的访问,如果两个进程都要访问同一个缓冲块,那么其中的一个进程就必然睡眠等待,直到该缓冲块被释放才可访问。赵炯博士所著的linux0.11内核完全注释一书中也是对该问题进行详细的讨论,但是我在阅读这段代码的时候还是有些疑问,在此发表下自己的见解。首先将这两个函数贴出来:void sleep_on(struct task_原创 2014-12-26 15:00:26 · 4394 阅读 · 7 评论 -
为什么全局描述符表GDT的第0项总是一个空描述符
为什么全局描述符表GDT的第0项总是一个空描述符,而局部描述符表却不是这样?386的保护模式下: DT=GDT*1+IDT*1+LDT*n;IDT和每个LDT都要到GDT中报一次到.有一个描述符项与一张表对应.什么是描述表呢? 其实很简单。1个段描述表记录记录一个段的特征信息,中断描述符表记录中断的端口和其对应的函数入口地址或门的入口函数地址,全局描述表GDT记录所有表的地址。其转载 2014-12-21 21:26:32 · 1348 阅读 · 1 评论 -
Minix文件系统磁盘结构分析
00000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 引导块 *00000400 40 00 a0 00 01 00 01 00 06 00 00 00 00 1c 08 10 |@...............| 超级块00000410 8f 13 01 00 00 00 00原创 2014-12-21 16:48:14 · 2636 阅读 · 0 评论 -
linux0.11信号处理
linux中的信号处理函数提供了对程序异步处理的功能,比如键盘按下ctrl+c键,该操作将产生一个SIGINT信号,并被发送到当前前台的进程中。内核采用一个无符号长整形变量中(32bit)的每一个比特位来表示不同的信号,因此最多可以定义32种信号。对于一个进程来说,当收到一个信号时,有3种不同的处理方式:1. 忽略该信号。其中SIGKILL和SIGSTOP不能忽略。2. 捕获该信号。调用s原创 2014-12-19 13:09:55 · 1203 阅读 · 1 评论 -
linux0.11进程调度分析
10ms时钟中断 --> 时钟中断函数timer_interrupt,将jiffier加1 --> 调用do_timer函数,将当前进程counter计数减1,如果--counter大于0,则返回继续执行该任务,否则 --> 调用schedule函数,代码如下:void schedule(void){ int i,next,c; struct task_struct ** p;/*原创 2014-12-11 14:12:45 · 1577 阅读 · 0 评论 -
方向位DF对串操作的影响
首先看如下代码:#include struct task_struct{ int a,b,c,d,e;};int main(){ struct task_struct init={1,2,3,4,5}; struct task_struct new_task={0,0,0,0,0}; struct task_struct *task[5]={&init}; struct ta原创 2014-12-09 16:57:12 · 1173 阅读 · 1 评论 -
分段机制
首先谈一下80X86系统中存在的三个地址概念:逻辑地址、线性地址和物理地址。逻辑地址:是指由程序产生的与段相关的偏移地址,也就是在Intel保护模式下程序执行代码段限长内的偏移地址。例如,在C语言指针编程中,读取指针变量本身的值(&操作),实际上这个值就是逻辑地址,它是相对于你当前进程数据段的地址,与绝对物理地址不相关。应用程序员仅需与逻辑地址打交道,而分段和分页机制对他们来说是透明的,仅由系原创 2014-12-03 19:51:35 · 1027 阅读 · 0 评论 -
块设备请求项队列及硬盘驱动
linux0.11在读写块设备的时候,并不直接对块设备进行操作,而是借由低级的ll_rw_block函数通过请求项来与设备进行联系,也即加入了一个中间环节。为什么要这样做呢?当然,你也可以直接对块设备进行操作,但是直接操作会存在一些问题:1. 同一个进程在写的过程中就不能发出读的请求,反之,在读的过程中也不能发出写的请求。2. 当一个进程正在对硬盘进行写或者读的时候,其他进程就不能发出硬盘原创 2014-12-30 15:41:06 · 1403 阅读 · 0 评论 -
bochs神奇的任意断点调试
#=======================================================================# MAGIC_BREAK:# This enables the "magic breakpoint" feature when using the debugger.# The useless cpu instruction XCHG BX,原创 2014-12-11 15:08:14 · 2608 阅读 · 0 评论 -
一个操作系统的实现——进程
在Orange中,对于进程的实现包含以下步骤:1. 首先定义一个任务,如下类似的函数,函数名就是任务到入口地址。void TestA(){ while(1){}}2. 在kernel_main函数中初始化进程结构体,除了初始化进程的name和pid,段寄存器(注意T1位为1,LDT选择子),eip和esp之外,关键需要初始化进程的局部描述符LDT在GDT中的选择子,以便从内核跳入进程原创 2014-12-01 11:23:36 · 840 阅读 · 0 评论 -
linux0.11块设备读写过程分析
Linux将一切设备视为文件,所以对于块设备也一样。块设备常见的有软盘和硬盘两种,虽然当今的硬盘传输速率已经非常快,但还是远不及内存,所以当CPU访问这类块设备的时候需要借助一个缓冲,以求得效率的最大化。因此,在分析块设备数据传输过程前,先了解下高速缓冲区(cache)是如何工作的。Linux0.11划分内存的一部分作为cache,这部分内存从内核末端开始到4M内存处,一共可以划出3千多个逻辑原创 2014-12-23 13:43:38 · 2249 阅读 · 0 评论 -
再谈分段
我们已经知道CPU的分段机制的作用在于将程序逻辑地址映射为线性地址,CPU在启动了保护模式之后,其段寄存器不再作为地址内容的一部分,而是作为一种称为选择子的东西,它作为在全局描述符表或者局部描述符表中寻找目标地址的索引,所以对于程序中每一个地址的寻址就需要指定两个事物,第一个就是选择子,第二个就是描述符表。选择子就是段寄存器,而描述符表就是一个全局数组变量。这个描述符表其实应该是二维的数组,第一维原创 2014-12-15 12:12:23 · 537 阅读 · 0 评论 -
linux0.11内核空间与用户空间数据交换
学习linux到现在对于这个问题一直都没有在意,细看代码时发现这确实是一个大问题,并且感觉很巧妙。当用户进程执行系统调用进入内核空间时,所有段都指向内核段,但是fs却除外,它需要扮演负责内核空间与用户空间数据的交换的重要角色。其中一个典型的例子就是printk函数,在内核空间中如果要打印一串数据,由于ds段指向内核空间,所以无法向用户空间的tty0控制终端输送数据,linux为了实现print原创 2014-12-14 20:52:07 · 675 阅读 · 0 评论 -
linux学习总结1
学习linux系统已有月余,可能是天资问题,到现在才感觉入门,不过还是对自己这段时间能够沉下心坚持学习下来感到欣慰,也该作一个阶段性的总结了。学习linux之前对于这个系统基本上是零基础,总感觉linux博大精深,我一开始不去研究它也是因为平时都是零碎的时间,感觉零碎的去学习它很难有一个比较好的学习效果。趁着找完工作这段时间,可以大量时间投入到上面去,一个月下来自己也感觉颇有收获,算是入门了吧。原创 2014-12-14 12:50:33 · 714 阅读 · 0 评论 -
linux0.11任务切换switch_to
#define switch_to(n) {\struct {long a,b;} __tmp; \__asm__( "cmpl %%ecx,current\n\t" \ "je 1f\n\t" \ "movw %%dx,%1\n\t" \ "xchgl %%ecx,current\n\t" \ "ljmp *%0\n\t" \ "cmpl %%ecx,last_task_used原创 2014-12-13 20:54:37 · 1599 阅读 · 0 评论 -
linux0.11init进程及shell原理分析
static char * argv_rc[] = { "/bin/sh", NULL };static char * envp_rc[] = { "HOME=/", NULL };static char * argv[] = { "-/bin/sh",NULL };static char * envp[] = { "HOME=/usr/root", NULL };void init(原创 2014-12-12 16:34:15 · 2451 阅读 · 2 评论 -
linux0.11字符设备的读写过程分析
首先要知道linux系统/dev目录下的各种设备文件(文件属性c打头)并不占用空间,你可以发现他们的大小为0字节,他们的区别在于文件的i节点的成员i_zone[0]的值不同,该值标识不同的设备号。比如tty0文件的设备号为0x0400,tty1设备号为0x0401,hd0设备号为0x0300,hd1设备号为0x0301等。而这个设备号里面又包含两部分内容:高字节标识不同类设备,比如tty0和hd0原创 2014-12-10 20:48:43 · 1696 阅读 · 0 评论 -
linux0.11 编译遇到的问题
在oldlinux网址下载了linux0.11能够编译通过的代码,在自己ubuntu13.10的机子上确实能够编译成功,gcc版本4.8.1,但是放在boshs上确无法运行,总结有如下问题:1. 反复Loading system... 。一步一步调试,发现当setup完后并没有进入到head中,通过查看Image二进制文件,发现第5扇区(0xa00)开始处的指令并不是head代码。经过一步一步原创 2014-12-09 16:08:33 · 1897 阅读 · 1 评论 -
linux0.11 execve系统调用分析
在Linux平台下,我们一般都是在命令行下键入"./hello"来运行一个当前目录下的hello应用程序("./"指定当前目录)。虽然看似很简单,但这么小小的一个操作其实涉及到了很多的知识。比如:shell是如何将hello调入内存的?hello在运行前shell执行了哪些操作?hello的父进程又是哪个?回答这些问题之前我们先来看下面的一个例子:这个例子包含两个程序,第一个test_hell原创 2015-01-04 18:15:27 · 3156 阅读 · 0 评论