Linux 提供了 glibc 库, 它封装了系统调用接口, 对上层更友好的提供服务, 系统调用最终都会通过 DO_CALL 发起, 这是一个宏定义, 其 32 位和 64 位的定义是不同的:
32 位系统调用
用户态
将请求参数保存到寄存器
将系统调用名称转为系统调用号保存到寄存器 eax 中
通过软中断 ENTER_KERNEL 陷入内核态
内核态
内核的软中断陷入门收到系统调用会将用户态的寄存器保存到 pt_regs 结构中
在系统调用函数表 sys_call_table 中根据调用号找到对应的函数
并将寄存器中保存的参数取出来作为参数执行函数, 将返回值写入 pt_regs 结构的 ax 位置
通过iret指令根据 pt_regs 恢复用户态进程
64 位系统调用
用户态
将请求参数保存到寄存器
将系统调用名称转为系统调用号保存到寄存器 rax 中
通过 syscall 指令进入内核态
(注:由int中断指令改为syscall指令,减少了一次查表过程,性能应该有所提高)
内核态
将用户态的寄存器保存到 pt_regs 中
在系统调用函数表 sys_call_table 中根据调用号找到对应的函数
将寄存器中保存的参数取出来作为函数参数执行函数, 将返回值写入 pt_regs 的 ax 位置
由于没写中断处理程序当发送完成后,触发串口中断进入0x0023地址处运行,就相当于复位了一次一样。所以会出现2次的情况。(第二次由于TI已经为1了所以不会触发中断)解决方法
1、关闭串口中断
EA=0
ES=0
2、写一个串口中断处理函数
void UARTInterrupt(void) interrupt 4
{
if(RI)//RI标志位为1代表接收到数据
{
RI = 0 //清零接收标志位
//在这里添加中断处理函数
}
else
TI = 0//如果RI不为1一般是发送完成中断 把TI(发送完成标志位)清零
}
发送完成后清零TI
SBUF = 'i'
while(!TI)//等待发送完成
TI = 0//发送完成后清零TI
这样就可以实现多个字节发送不会造成冲突
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)