分类: LINUX
2006-04-05 21:28:40
参考网站及书籍有:
Linux系统使用 int32-int47(0x20-0x2f) 来对应 IBM PC 中的两片级联的 8259A (从片的 INT 接主片的IR2) 发出的中断请求信号 IRQ0-IRQ15。并把系统调用 (system call) 中断设置为 int128 (0x80)。
如果当前进程的时间片值减1后已经为 0,并且 CPL>0, do_timer() 就会调用 schedule() 函数切换到其他进程。但是如果CPL=0,那么 do_timer() 会立即退出,这保证了系统运行在内核态时不可被抢占。
Linux 的进程是抢占式的,被抢占的进程仍然处于 TASK_RUNNING 状态,只是暂时没有被 CPU 运行。
在进行进程调度时,基本按照下面的顺序:
schedule() 扫描进程数组选择剩余时钟滴答数最大的进程 || \/ 若时钟数都用完则重新计算所有进程(包括睡眠进程)的时钟滴答数 || \/ 选不出则运行进程 0,进程 0 调用 pause() 设置自己为可中断的睡眠状态再调用 schedule()
_start: mov ax,#BOOTSEG mov ds,ax mov ax,#INITSEG mov es,ax mov cx,#256 sub si,si sub di,di rep movw jmpi go,INITSEG go: mov ax,cs mov ds,ax mov es,ax ! put stack at 0x9ff00. mov ss,ax mov sp,#0xFF00 ! arbitrary value >>512
上面的代码执行过程是:
load_setup: mov dx,#0x0000 ! drive 0, head 0 mov cx,#0x0002 ! sector 2, track 0 mov bx,#0x0200 ! address = 512, in INITSEG mov ax,#0x0200+SETUPLEN ! service 2, nr of sectors int 0x13 ! read it jnc ok_load_setup ! ok - continue mov dx,#0x0000 mov ax,#0x0000 ! reset the diskette int 0x13 j load_setup
在把 setup.s 文件装入内存时,使用了 13 号中断。在中断时, ah=0x02 表示读磁盘内容到内存, al=SETUPLEN=4 为要读出的扇区数量。
总的说来,就是读 第0号驱动器 (硬盘的话 dx 第7位要为1)第0号磁头第0号磁道第2号扇区,数据缓冲区地址为 es:bx=0x9000:0x0200 。如果这段执行出错则 cf=1 ,复位磁盘后再跳到装入 setup.s 的地方继续尝试装入。
作为一个引导程序,一定要设置 boot_flag 标记:
boot_flag: .word 0xAA55
因为 BIOS 只有在发现了 0xAA55 这个标记后才能确定这个引导程序是正确的。
使我感到奇怪的是,在复制硬盘参数表时。Linux 内核先取得第一块硬盘和第二块硬盘的信息,再检查第二块硬盘是否存在,若不存在则要将第二个参数表清零。那为什么不先检查再进行复制呢?这样如果第二块不存在话,不是能节省一次复制操作吗?
在对中断控制器 8259A 进行初始化部分,对以下代码:
mov al,#0x11 ! initialization sequence out #0x20,al ! send it to 8259A-1
《Linux0.11源代码分析》中说设置主控电路的 ICW1 为电平触发,级联模式。但是据《现代微机原理及接口技术》P155 上面说,D3 为 0 应该是边沿触发方式才对。
在对 ICW2 设置时,
mov al,#0x20 ! start of hardware int's (0x20) out #0x21,al
由于 ICW2 的低 3 位用于 8 位机,所以只要对高 5 位进行设置,而低3位对应 8259A 外部引脚 IR7-IR0 的编码。这里设置的高 5 位为 00010D。因为 IR(i) 的中断类型号 = ICW2 的高 5 位 + i,所以中断类型号是从 0x20 开始的。
代码
.word 0x00eb,0x00eb
的作用与教科书上的
jmp short $+2
差不多,都是因为 I/O 的端口延时。 .word 伪指令表示其后每个数据项占 2 个字节。