Linux内核分析实验四:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用...

陈琛+ 原创作品转载请注明出处《Linux内核分析》MOOC课

1.基础知识

用户态、内核态

为保证系统内核安全,cpu执行指令分为用户态和系统态两种,表现在用户态的指令有些特权指令不能执行、某些内存区域不能访问;而内核态可以执行特权指令,可以访问所有内存空间。
Intel x86CPU有四种级别的,分别为0,1,2,3.Linux只使用0,3级其中0表示内核态,3表示用户态。

中断

中断是从用户态进入内核态的主要方式,系统调用知识一种特殊的中断。

中断时上下文切换

从用户态切换到内核态时,必须保存用户态的寄存器上下文。

  • 保存在哪里?

    保存在内核堆栈中
  • 要保存什么?

    用户态栈顶地址(esp), psw , cs:eip

中断处理的完整过程
interrupt(int 0x80) -- save
cs:eip/ss:esp/eflags tp kernel stack then load
cs:eip(entry of a spefic ISR) and ss:esp(point to kernel stack)
SAVE_ALL
//内核代码,完成终端服务,发生进程调度(暂时保存,下一次切换回该进程时执行返回)
RESTORE_ALL
iret  pop cs:eip /ss:esp/eflags from kernel stack to CPU
系统调用
意义:
  • 程序员从硬件编程中解放出来
  • 提高系统安全性
  • 用户应用程序具有更高地可移植性
API和系统调用的不同点:
  • 系统调用通过软件中断向内核发出一个明确地请求
  • API只是一个函数定义,封装了系统调用

2.实验过程

选择63号系统调用,获取当前进程的父进程pid.代码比较简单,必要处已做注释.

  • 使用库函数getppid,获取父进程pid
#include <stdio.h>                                                                                                
#include <unistd.h>

int main()
{
     long ppid;
     ppid = getppid();
    
     printf("the parent pid is:%ld\n",ppid);
     
     return 0;
}
  • 使用C代码中嵌入汇编方式
#include <stdio.h>                                       
/*
*将系统调用号通过eax寄存器传递
*int 0x80触发中断
*返回值放在eax寄存器,写入到内存变量ppid中
*/
int main()
{
     long ppid;
 
     asm volatile(
         "mov $64,%%eax\n\t" 
         "int $0x80\n\t"
         "mov %%eax,%0\n\t"
         :"=m"(ppid)
     );
 
     printf("the parent pid is:%ld\n",ppid);
 
     return 0;
}
  • 运行截图

image

image

  • 总结

通过本周的课程和本次的实验,熟悉了系统调用的本质,以及系统调用和中断的关联。系统调用是用户态和内核态的桥梁,而具体的措施就是中断。实验中采用内嵌汇编编写的代码,在运行时,通过eax准备系统调用号,使用ebx、ecx等传递具体参数,当我们触发0x80中断时,经过中断处理程序,我们就进入了内核态。

转载于:https://www.cnblogs.com/tb1over/p/6582881.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值