Linux下的系统调用
张雨梅 原创作品转载请注明出处
《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-10000
1.linux的的用户态与内核态
Intel x86架构的CPU有0~3四种执行级别,0级最高,3级最低, linux只使用0级和3级,分别表示内核态和用户态。linux中,只有内核态能访问逻辑地址为0xc0000000以上的空间。执行一个程序时,大部分时间是运行在用户态下的,在其需要操作系统帮助完成某些它没有权力和能力完成的工作时就会切换到内核态。程序由用户态进入内核态的方式是中断。
系统调用的核心是使用操作系统为用户特别开放的一个中断,例如linux的int 80h中断,系统中断是由用户态主动切换到内核态。
上图展示的是程序在用户态和内核态切换的大概过程。
(1)xyz()是API,就是一个函数定义。
(2)每个系统调用对应一个封装例程, libc库用这些封装例程定义出用户的API。执行到int 80h时,产生系统调用,是通过软中断向内核发出的明确请求。
(3)system_call是linux所有系统调用的入口点,此时进入内核态,执行系统调用处理程序,执行内核函数sys_xyz。
(4)执行完成后返回到系统调用处理程序中的ret_fromsys_call,通过iret返回到封装例程中,又回到用户态封装例程执行完回到发生系统调用的位置,继续执行下面的程序。
每个系统调用对应一个封装实例,从而产生可给用户使用的API。但是API与系统调用不是一一对应的,有的API可能提供的都是用户态的服务,有的API可能调用多个系统调用,可能多个API调用同一个系统调用。
2.c代码与汇编代码
可以通过c代码和汇编代码的对应关系,观察系统调用的发生过程,这里用geituid函数。
getuid.c
#include<stdio.h>
#include<stdlib.h>
#include <sys/types.h>
#include <pwd.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
uid_t uid;
uid = getuid();
printf("User IDs: uid=%d\n", uid);
exit();
}
getuid-asm.c
int main()
{
uid_t uid;
asm volatile(
"mov $0,%%ebx\n\t"//ebx保存参数,置为null
"mov $0x18,%%eax\n\t"//getuid的系统调用号是24,传给eax
"int $0x80\n\t"//系统调用
"mov %%eax,%0\n\t"//返回值用eax保存
: "=m"(uid)
);
printf("User IDs: uid=%d\n", uid);
return ;
}
getuid-asm.c与getuid.c不同的是,把uid = getuid()变成了汇编语言。汇编语言的执行步骤是:
(1)把参数传递给ebx,这个函数没有参数,这一句去掉以后执行结果是一样的。
(2)把系统调用号传给eax,系统调用号标志具体的系统调用函数。
每个系统调用至少有一个参数,系统调用号,用eax传递。除了系统调用号,参数不能超过6个,分别存入ebx,ecx,edx,esi,edi,ebp。如果参数超过6个,会用一个单独的寄存器指向进程地址空间中这些参数所在的内存区。
(3)int 80h,进入system_call,在内核堆栈中保存现场
push cs
push eip
push EFLAGS
push ss
push esp
push eax
push es
push ds
push eax
push ebp
push edi
push esi
push edx
push ecx
push ebx
然后执行内核函数sys_getuid()。
(4)执行完sys_getuid后,返回到system_call,恢复现场。
pop ebx
pop ecx
pop edx
pop esi
pop edi
pop ebp
pop eax
pop ds
pop es
add $,esp//相当于pop eax
iret//返回到用户堆栈
与一般中断一样,函数返回值传递给eax。
iret执行之后,弹出esp,ss,eflags,cs,eip,进入用户堆栈,程序回到用户态进程。
编译运行结果如图
可以看出c代码与汇编代码的执行结果一样。
Linux下的系统调用的更多相关文章
- 浅析基于ARM的Linux下的系统调用的实现
在Linux下系统调用是用软中断实现的,下面以一个简单的open例子简要分析一下应用层的open是如何调用到内核中的sys_open的. t8.c 1: #include <stdio.h> ...
- (转)linux下的系统调用函数到内核函数的追踪
转载网址:http://blog.csdn.net/maochengtao/article/details/23598433 使用的 glibc : glibc-2.17使用的 linux kerne ...
- linux下的系统调用函数到内核函数的追踪
http://blog.csdn.net/maochengtao/article/details/23598433
- Linux下缓冲区溢出攻击的原理及对策(转载)
前言 从逻辑上讲进程的堆栈是由多个堆栈帧构成的,其中每个堆栈帧都对应一个函数调用.当函数调用发生时,新的堆栈帧被压入堆栈:当函数返回时,相应的堆栈帧从堆栈中弹出.尽管堆栈帧结构的引入为在高级语言中实现 ...
- LINUX下FD_SET介绍
刚刚了解了linux下select系统调用,函数原型是 #include <sys/select.h> #include <sys/time.h> int select(int ...
- Linux下端口复用(SO_REUSEADDR与SO_REUSEPORT)
freebsd与linux下bind系统调用小结: 只考虑AF_INET的情况(同一端口指ip地址与端口号都相同) freebsd支持SO_REUSEPORT和SO_REUSEADDR选项,而l ...
- Linux下函数调用堆栈帧的详细解释【转】
转自:http://blog.chinaunix.net/uid-30339363-id-5116170.html 原文地址:Linux下函数调用堆栈帧的详细解释 作者:cssjtuer http:/ ...
- Linux下缓冲区溢出攻击的原理及对策
前言 从逻辑上讲进程的堆栈是由多个堆栈帧构成的,其中每个堆栈帧都对应一个函数调用.当函数调用发生时,新的堆栈 帧被压入堆栈:当函数返回时,相应的堆栈帧从堆栈中弹出.尽管堆栈帧结构的引入为在高级语言中实 ...
- linux下C++修改文件内容
C fwrite在任意位置写入文件,并可修改文件内容 想实现类似迅雷那样下载时可以从文件半中间写入的功能 #include<stdio.h> int main() { FILE *fp; ...
随机推荐
- echarts 用marlkline画线 同时配置中含有datazoom,怎么设置markline
由于项目需要设置边界值即用markline 画标线,通过echarts文档可以查看到(如下) 1.通过坐标点(xAxis和yAxis的设置) 通过网上搜索许多markline的配置都是通过下面来设置的 ...
- Python Thread related
1.Thread.join([timeout]) Wait until the thread terminates. This blocks the calling thread until the ...
- android 图片压缩
引用:http://104zz.iteye.com/blog/1694762 第一:我们先看下质量压缩方法: private Bitmap compressImage(Bitmap image) { ...
- 【Ngui 学习系列之一:简单组件的操作】
一.Buttonunity edit: Sprite作为父对象和背景 -- Collider -- Button script Label 作为子对象和显示文字代码: private UIButton ...
- Android 中如何计算 App 的启动时间?
(转载) 已知的两种方法貌似可以获取,但是感觉结果不准确:一种是,adb shell am start -w packagename/activity,这个可以得到两个值,ThisTime和Total ...
- 微信 回调模式 echostr校验失败,请您检查是否正确解密并输出明文echostr
- (一)sql入门 导读
从转行做软件始,就开始接触sql,但还是不怎么深入,回忆3月份找工作的时候,左关联都没有写出来,真是丢脸,以此博客做个认真的开始. 以后的日子,遇到了圆柱体的空心物体,我就应该联想到一样东西,那就是数 ...
- 关于获取web应用的文件路径的注意事项
今天在把数据写入文件时遇到了一个问题,指定的文件获取不到.一开始是这样的 URL url = XXX.class.getClassLoader().getResource(fileName);File ...
- C# 中的委托和事件(转载)
引言 委托 和 事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易.它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去 ...
- Autumn is a second spring when every leaf is a flower.
Autumn is a second spring when every leaf is a flower. 秋天即是第二个春天,每片叶子都是花朵.——阿尔贝·加缪