服务接口的结构:
(相关资料图)
Cosmos的API结构:文件类、进程类、内存类、时间类的API;
进入内核:
设备向 CPU 发送一个中断信号,CPU 接受到这个电子信号后,在允许响应中断的情况下,就会中断当前正在运行的程序,自动切换到相应的 CPU R0 特权级,并跳转到中断门描述符中相应的地址上运行中断处理代码。
除了设备可以发送中断信号、应用软件也可以向CPU发送中断;软中断指令,如 int 255,这个常数表示CPU从中断描述符表中取得第几个中断描述符进入内核;
传递参数:
int 指令提供了应用程序,进入了操作系统的内核函数的机制;还需要传递参数,告诉操作系统做什么;
参数传递的方式有两种:寄存器传递 或 保存在用户栈;RBX、RCX、RDX、RDI、RSI 这 5 个寄存器来传递参数,事实上一个系统服务接口函数不会超过五个参数;
RAX寄存器中保存着一个 系统服务号;在系统服务分发器中,会根据这个系统服务号调用相应的函数;
需要用c语言嵌入汇编的方式实现;用来解决参数传递和触发中断问题。并且还需要处理系统返回结果;API_ENTRY_PARE1 、API_ENTRY_PARE4等宏;
系统服务分发器:
中断数量有限,但是系统服务会随着系统功能的增加而增加,不能为每个系统服务都提供一个中断描述符;
系统服务分发器的作用:我们可以只使用一个中断描述符,通过系统服务号区分是哪个服务;
实现系统服务分发器:
其实系统服务分发器就是一个函数,由中端处理代码调用;系统中断处理的第一层汇编代码调用hal_syscl_allocator中断处理框架函数,汇编主要是保存用户态CPU寄存器到内核栈中;
hal_syscl_allocator 中断处理框架函数调用krlservice函数;
krlservice 函数:判断是否大于最大服务号;判断是否有服务接口函数;检查通过之后,调用相应的服务接口;
系统服务表:
服务入口函数指针保存在系统服务表中;
stkparame_t 结构保存的是内核栈中的参数;这个正是之前CPU寄存器压入内核栈中的参数;
hal_syscal_allocator 函数的第二个参数,正是RSP寄存器的值;转成stkparame_t 结构地址,就能提取参数;
osservicetab数组中存放的是服务接口函数;
系统服务实例:
应用程序开发者往往不是直接调用系统API,经常调用某个库达到目的;
时间库:
time库调用 api_time 系统api;
时间API接口:
因为库和API接口函数不同层次,应用程序可以直接调用api 接口函数;
api_time 函数:调用 API_ENTRY_PARE1函数,执行int 指令进入内核,开始运行时间服务代码;
内核态时间服务接口:
系统服务分发器会根据服务号从系统服务表中取出相应的函数并调用;
krlsvetable_time 函数:调用真正的时间服务函数 krlsve_time 函数,这个函数要放在系统服务表中 osservicetab 才可以;
实现时间服务:
krlsve_time 函数:把系统的时间读取出来,写入用户应用程序传入缓冲区,由于osktime 这个结构由其他代码自动更新,需要加锁访问;
系统服务函数的执行过程:
应用程序在用户空间中运行,调用库函数,库函数调用 API 函数执行 INT 指令,进入中断门,从而运行内核代码。最后内核代码一步步执行了相关服务功能,返回到用户空间继续运行应用程序。
关键词: