注意:本系统调用过程基于32位操作系统
中断服务程序的寻址过程
1.用户态程序产生系统调用write();
2.产生中断指令ENTER_KERNEL(int $0x80=128)
,CPU收到中断指令去查询中断向量表,找出中断号0x80
对应的中断服务程序的内存基地址(0x003498
)
3.程序计数器PC
设置为0x003498
,CPU就会执行对应的中断服务程序(entry_INT80_32
)
系统调用用户态发生的事情
1.用户态程序产生系统调用write()
;
2.保存函数参数到CPU寄存器(ebx、ecx、edx....
)
3.通过方法名write()
查看用户态下的文件找到对应的系统调用号(3)
,并将系统调用号存储到CPU的EAX
寄存器中
4.通过中断指令ENTER_KERNEL
进入到内核(见中断服务程序的寻址过程)
系统调用内核态发生的事情
经过上面系统调用用户态发生的事情这一节我们知道,当前CPU通过EAX
寄存器保存了系统调用号,其它寄存器保存了函数参数
1.将用户态寄存器保存到内核pt_regs
缓存中(也就是当前CPU寄存器的值)
2.在系统调用表中(sys_call_table
),根据EAX
寄存器传到内核态的值,找到内核对应的系统调用函数(sys_write
)
3.执行系统函数(函数参数已经通过寄存器传到了内核态)
4.函数执行完毕,返回值写入CPU的Eax
寄存器,通过指令iret
根据pt_regs
缓存恢复用户态程序
整体流程
注意:切换到内核态时,还会在pt_regs缓存中缓存栈指针,程序计数器PC,方便内核态切换回用户态时,恢复系统调用前的上下文信息,CPU可以接着下一条指令执行,函数也可以接着执行