linux内核设计与实现 LINUX内核源代码情景分析( 五 )

imgSpider 采集中…

  • 系统调用内部,函数声明中要添加asmlinkage,通知编译期仅从栈中提取函数参数
  • 系统调用在内核中均以sys_作为前缀
  • linux中每个系统调用都和一个独一无二的系统调用号关联
  • 内核记录系统调用表所有已注册过的系统调用列表,存储在sys_call——table中,以体系结构有关
  • linux内核设计优化简洁,上下文切换时间极快,操作系统执行效率高
2. 系统调用处理程序
  • 用户程序不能直接调用内核函数,以防止内核空间安全失控 。而是通过中断通知内核,让内核代表程序去执行
  • 触发软中断前,将调用号装入eax寄存器
imgSpider 采集中…
  • 参数传递:在x86系统上,ebx、ecx、edx、esi、edi按照顺序存放前五个参数 。返回值通过eax寄存器返回
  • 内核空间和用户空间数据拷贝函数:copy_to_user,copy_from_user
3. 系统调用上下文
  • current指针指向引发当前调用的进程
  • 执行系统调用时处于进程上下文
  • 进程上下文中,内核可以休眠(调用阻塞或schedule)并可以被抢占
4. 系统调用的实现
  • linux不提倡多用途的系统调用,每个系统调用都应该有明确的用途
  • 接口应该尽量简洁,参数少 。力求稳定不做改动
  • 尽量为将来做考虑,尽量通用,不要做限制 。“提供机制而不是策略”
  • 编写完后要注册到内核,成为真正可用的系统调用 在系统调用最好加入一个表项 。大部分位于entry.s文件中 。所有支持系统调用的硬件体系都要做 定义系统调用号到include/asm/unist.h文件中 函数放入kernel文件下某个位置,使之编译进内核映像(不能被编译称模块)
  • 用户空间如何访问注册的系统调用 通常情况下,用户通过包含标准头文件,并和底层系统调用具体的c实现链接,就可以使用系统调用 自定义系统调用在标志头文件中不存在,可以通过linux提供的宏来调用:_syscalln,n代表需要传递的参数 。该宏有2+2n个参数,第一个代表返回值类型,第二个代表函数名称,后续的是n个参数类型和参数名称 比如:open函数的系统调用,系统调用号为_NR_open,定义在中,内部被_syscall3宏实现,调用open时,内部把宏直接放入应用程序代码中
五. 中断和中断处理程序1. 中断
  • 中断用于解决计算机处理器与硬件设备处理速度不匹配的问题,硬件处理好任务后主动发送信号给处理器
  • 中断本质是电信号,由硬件设备产生,送入中断处理器的输入引脚上 。再由中断控制器向处理器发送信号 。处理器收到信号就中断工作去处理中断
  • 每个中断都有唯一都数字标识,称为中断请求(IRQ)线 。比如:IRQ0是时钟中断,IRQ1是键盘中断
2. 中断处理程序
  • 响应特定中断时,会执行的函数为中断处理程序或中断服务例程
  • 中断处理程序是设备驱动程序的一部分,设备驱动程序是用于对设备进行管理的内核代码
  • 与内核函数的区别:中断处理程序是被内核调用来响应中断的,运行与中断上下文中
  • 中断处理程序必须能快速执行,同时,我们要靠它完成大量的其他工作 。这两个目的是矛盾的 。
  • 为了解决上述矛盾,将中断处理程序切分为两个半部 上半部:接收到请求就立即执行,但执行少部分工作 。中断应答和硬件复位 下半部:中断处理程序返回时立即执行
3. 注册中断处理程序imgSpider 采集中…
  • irq:要分配的中断号
  • handler:实际中断处理程序 。接受三个参数,返回irqreturn_t类型参数
  • irqflags:可以为0,或以下标识的位掩码 SA_INTERRUPT:表明是快速中断程序 。主要用于时钟中断程序 SA_SAMPLE_RANDOM SA_SHIRQ:共享中断线
  • devname:中断相关设备的Ascii文本名称,如键盘中段为“keyboard”
  • dev_id:用于共享中断线
  • 该函数可能会休眠,不能在中断上下文或不允许阻塞的代码中调用
4. 中断处理机制imgSpider 采集中…
  • 设备产生中断,把电信号发送给中断控制器
  • 中断控制器把信号发给处理器
  • 处理器中断程序,跳到内存中预定义的位置执行 。就是中断程序入口点
  • 内核调用do_IRQ,对中断进行应答
  • 相关函数位于arch/i386/kernel/entry.s,arch/i386/kernel/irq.c
5 中断控制