第四章:系统调用的三层机制
一、实验楼实验四:
(一)使用库函数API和C代码中嵌入汇编代码触发同一系统调用
在/LinuxKernel/linux-3.18.6/arch/x86/syscalls目录下选取20号getpid进行调用,
编译并执行如下:
getpid20209302.c源代码如下:
(二)C代码中嵌入汇编代码进行系统调用
修改getpid20209302.c 嵌入汇编代码,编译并执行。
源代码如下:
分析__asm__ __volatile__函数中汇编语言的参数传递方式,首先将EBX置空,然后将系统调用号20传入EAX寄存器,在16进制中,0x14表示十进制的2,然后运行int $0x80指令,产生中断向量为128的编译异常,进入内核后开始执行中断向量128对应的中断服务程序system_call,根据EAX寄存器存储的系统调用号调用getpid(),将返回值传回用户态参数pid。
二、本周知识总结
1.系统调用3层机制:
第一步,系统调用的库函数就是读者使用的操作系统提供的API,调用软中断向内核发出中断请求;
第二步,CPU切换到内核态并开始执行一个system_call和系统调用内核函数,具体通过int $0x80触发系统调用的执行;
第三步,进入内核,通过系统调用号将API函数和系统调用内核函数关联起来进行调用。
参数传递:系统调用中,用户态切换到内核态,两种执行模式使用不同堆栈,参数传递通过特殊寄存器来进行。在x86-32中,EAX用于传递系统调用号,其余参数按顺序赋值给EBX,ECX,EDX,ESI,EDI和EBP,参数个数一般不超过6个。如果超过6个就把一个寄存器作为指针指向内存用于存储参数。
2.内核态和用户态的区别
内核态:处于高的执行级别下,代码可以执行特权指令,访问任意的物理地址,这时的CPU就对应内核态,对所有的指令包括特权指令都可以执行。
用户态:处于低的执行级别下,代码只能在级别允许的特定范围内活动。在日常操作下,执行系统调用的方式是通过库函数,库函数封装系统调用,为用户提供接口以便直接使用。