当前位置: 技术问答>linux和unix
我是个新手,请各位大虾多多帮忙,能帮多少帮多少!
来源: 互联网 发布时间:2014-11-27
本文导语: 用户与内核间如何通信?为什么不能直接通信?如何查看内核中各进程状态?进程中有多少种状态,每种状态的意义。 还有,如何实现任务切换,如何处理中断?如何编写自己的中断? | 用...
用户与内核间如何通信?为什么不能直接通信?如何查看内核中各进程状态?进程中有多少种状态,每种状态的意义。
还有,如何实现任务切换,如何处理中断?如何编写自己的中断?
还有,如何实现任务切换,如何处理中断?如何编写自己的中断?
|
用户和内核通信?用户只和shell交互。直接控制内核太麻烦了。而且很可能会出错。
ps aux,top查看进程状态。
进程切换是使用switch_to这个宏来做的,当进入时prev即是现在运行的进程,next是接下来要切换到的进程,
#define switch_to(prev,next,last) do {
asm volatile(
"pushl %%esint"
"pushl %%edint"
"pushl %%ebpnt"
// 首先它切换堆栈指针,prev->tss.esp = %esp;%esp = next->tss.esp,这以后的堆栈已经是next的堆栈了。
"movl %%esp,%0nt" /* save ESP */
"movl %3,%%espnt" /* restore ESP */
// 然后使进程prev的指针保存为标号为1的那一个指针,这样下次进程prev可以运行时,它第一个执行的就是pop指令。
"movl $1f,%1nt" /* save EIP */
// 把进程next保存的指针推进堆栈中,这句作用是,从__switch_to返回时,下一个要执行的指令将会是这个指针所指向的指令了。
"pushl %4nt" /* restore EIP */
// 使用jump跳到__switch_to函数的结果是:调用switch_to函数但不象call那样要压栈,但是ret返回时,仍是要弹出堆栈的,也就是上条指令中推进去的指令指针。这样,堆栈和指令都换了,进程也就被"切换"了。
"jmp __switch_ton"
// 由于上面所说的原因,__switch_to返回后并不会执行下面的语句,要执行到这,只有等进程prev重新被调度了。
"1:t"
"popl %%ebpnt"
"popl %%edint"
"popl %%esint"
:"=m" (prev->tss.esp),"=m" (prev->tss.eip),
"=b" (last)
:"m" (next->tss.esp),"m" (next->tss.eip),
"a" (prev), "d" (next),
"b" (prev));
} while (0)
处理中断比如软盘驱动控制器用的中断口是中断控制器的管脚6,那么当中断处理字系统接收到一个中断信号6时,系统必须将CPU执行地址转到软盘设备驱动程序代码处。Linux使用一系列指针指向含有中断处理例程的数据结构。这些例程分别属于系统中不同的设备驱动程序。每一个设备驱动程序在初始化时负责申请它所需要的中断号。
当一个中断发生时,Linux首先必须通过读取当前的ISR(中断状态寄存器)来决定中断的来源。然后核心把这个中断源映射到irq_action向量一个偏移量上。例如,一个来自软驱的中断6将被映射到向量的第7个入口。如果对于一个发生了的中断没有一个中断处理句柄相对应,Linux核心将记载一个错误。否则,核心将通过查询所有的”挂“这个中断口上irqaction结构并调用相应的中断处理例程。
ps aux,top查看进程状态。
进程切换是使用switch_to这个宏来做的,当进入时prev即是现在运行的进程,next是接下来要切换到的进程,
#define switch_to(prev,next,last) do {
asm volatile(
"pushl %%esint"
"pushl %%edint"
"pushl %%ebpnt"
// 首先它切换堆栈指针,prev->tss.esp = %esp;%esp = next->tss.esp,这以后的堆栈已经是next的堆栈了。
"movl %%esp,%0nt" /* save ESP */
"movl %3,%%espnt" /* restore ESP */
// 然后使进程prev的指针保存为标号为1的那一个指针,这样下次进程prev可以运行时,它第一个执行的就是pop指令。
"movl $1f,%1nt" /* save EIP */
// 把进程next保存的指针推进堆栈中,这句作用是,从__switch_to返回时,下一个要执行的指令将会是这个指针所指向的指令了。
"pushl %4nt" /* restore EIP */
// 使用jump跳到__switch_to函数的结果是:调用switch_to函数但不象call那样要压栈,但是ret返回时,仍是要弹出堆栈的,也就是上条指令中推进去的指令指针。这样,堆栈和指令都换了,进程也就被"切换"了。
"jmp __switch_ton"
// 由于上面所说的原因,__switch_to返回后并不会执行下面的语句,要执行到这,只有等进程prev重新被调度了。
"1:t"
"popl %%ebpnt"
"popl %%edint"
"popl %%esint"
:"=m" (prev->tss.esp),"=m" (prev->tss.eip),
"=b" (last)
:"m" (next->tss.esp),"m" (next->tss.eip),
"a" (prev), "d" (next),
"b" (prev));
} while (0)
处理中断比如软盘驱动控制器用的中断口是中断控制器的管脚6,那么当中断处理字系统接收到一个中断信号6时,系统必须将CPU执行地址转到软盘设备驱动程序代码处。Linux使用一系列指针指向含有中断处理例程的数据结构。这些例程分别属于系统中不同的设备驱动程序。每一个设备驱动程序在初始化时负责申请它所需要的中断号。
当一个中断发生时,Linux首先必须通过读取当前的ISR(中断状态寄存器)来决定中断的来源。然后核心把这个中断源映射到irq_action向量一个偏移量上。例如,一个来自软驱的中断6将被映射到向量的第7个入口。如果对于一个发生了的中断没有一个中断处理句柄相对应,Linux核心将记载一个错误。否则,核心将通过查询所有的”挂“这个中断口上irqaction结构并调用相应的中断处理例程。
|
看看《unix操作系统设计》机工版吧,看了就会茅塞顿开的。