使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用

章强 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

前提内容

CPU分用户态和内核态,cpu总共四种执行级别,0和3分别表示内核态和用户态,用户态下只能访问到0xbfffffff,内核态可访问所有地址,逻辑地址经过MMU转化为物理地址。
中断处理是从用户态进入内核态的主要方式
系统调用是一种特殊的中断,发生中断时保存用户态栈顶地址、当前的状态字、当前的cs:eip值。save_all保存现场,iret对应中断信号或者int指令,那边是保存,iret就是恢复
中断完整过程
这里写图片描述
1、保存eip,当前ss堆栈段寄存器esp,eflags标志寄存器至内核堆栈;
2、同时加载了ISR中断服务程序入口至cseip,然后当前esp指向内核堆栈段信息;
3、SAVE_ALL完成后开始中断服务,可能会发生进程调度,
如果发生了进程调度,当前的SAVE_ALL都会暂时保存在系统里边,再切换回来时恢复;
4、RESTORE_ALL,iret

系统调用概述
系统调用意义:防止了用户直接与操作系统打交道,提高安全性与可移植性(用户程序与具体硬件已经解耦和,被抽象接口替代了)。
系统调用封装成了一个函数API,区分是:API只是为了便于系统调用而产生的,通过汇编也可以完成系统调用功能。

这里写图片描述
xyz()是个API,内部封装了系统调用触发了int 0x80,这个中断向量对应着system_call内核代码入口起点。
服务程序sys_xyz执行完后ret_from_sys_call,这个过程中返回后则是进程调度的实际。

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
超过6个就把某一个寄存器做指针指向内存,通过那一块内存来传递eax传递的系统调用号,即int 0xxx的这个号至少为一个参数
(eax传入的0Xd即为系统调用号13,int0x80调用system_call)

实验截图

本次实验使用库函数API和C代码嵌入式汇编代码两种方式使用同一个系统调用getpid,即获取进程的id号,进入实验楼,编写以下代码

getpid.c 使用API
这里写图片描述

getpid-asm.c 使用c代码和嵌入式汇编代码
这里写图片描述

ebx清零表示无参数输入
0x14赋值给eax表示调用号为20 ,调用getpid
int $0x80执行系统调用
返回值保存在eax中,复制给pid变量

两个程序编译执行结果如下
这里写图片描述

总结

系统调用是用户态与内核态的桥梁,通过本次实验,我明白了系统调用的整个工作机制是怎样的:应用程序在用户态调用API函数,该函数将对应的系统调用号及参数保存,触发软中断,然后陷入内核态,system_call根据系统调用号调用对应的内核函数,内核函数执行完毕后将结果存放的eax中并返回给程序,程序返回的用户态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值