张雨梅   原创作品转载请注明出处

《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();
}
       uid_t是用宏定义的,是用户ID的专用类型,用来表示用户id。数据类型是unsigned long或者unsigned int。

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下的系统调用的更多相关文章

  1. 浅析基于ARM的Linux下的系统调用的实现

    在Linux下系统调用是用软中断实现的,下面以一个简单的open例子简要分析一下应用层的open是如何调用到内核中的sys_open的. t8.c 1: #include <stdio.h> ...

  2. (转)linux下的系统调用函数到内核函数的追踪

    转载网址:http://blog.csdn.net/maochengtao/article/details/23598433 使用的 glibc : glibc-2.17使用的 linux kerne ...

  3. linux下的系统调用函数到内核函数的追踪

    http://blog.csdn.net/maochengtao/article/details/23598433

  4. Linux下缓冲区溢出攻击的原理及对策(转载)

    前言 从逻辑上讲进程的堆栈是由多个堆栈帧构成的,其中每个堆栈帧都对应一个函数调用.当函数调用发生时,新的堆栈帧被压入堆栈:当函数返回时,相应的堆栈帧从堆栈中弹出.尽管堆栈帧结构的引入为在高级语言中实现 ...

  5. LINUX下FD_SET介绍

    刚刚了解了linux下select系统调用,函数原型是 #include <sys/select.h> #include <sys/time.h> int select(int ...

  6. Linux下端口复用(SO_REUSEADDR与SO_REUSEPORT)

    freebsd与linux下bind系统调用小结:    只考虑AF_INET的情况(同一端口指ip地址与端口号都相同) freebsd支持SO_REUSEPORT和SO_REUSEADDR选项,而l ...

  7. Linux下函数调用堆栈帧的详细解释【转】

    转自:http://blog.chinaunix.net/uid-30339363-id-5116170.html 原文地址:Linux下函数调用堆栈帧的详细解释 作者:cssjtuer http:/ ...

  8. Linux下缓冲区溢出攻击的原理及对策

    前言 从逻辑上讲进程的堆栈是由多个堆栈帧构成的,其中每个堆栈帧都对应一个函数调用.当函数调用发生时,新的堆栈 帧被压入堆栈:当函数返回时,相应的堆栈帧从堆栈中弹出.尽管堆栈帧结构的引入为在高级语言中实 ...

  9. linux下C++修改文件内容

    C fwrite在任意位置写入文件,并可修改文件内容 想实现类似迅雷那样下载时可以从文件半中间写入的功能 #include<stdio.h> int main() { FILE *fp; ...

随机推荐

  1. JavaScript基本操作

    一.如何编写? 1.JavaScript代码存在形式 <!-- 方式一 --> <script type="text/javascript" src=" ...

  2. Flex 布局

    Flex 布局     网页布局(layout)是CSS的一个重点应用. 布局的传统解决方案,基于盒状模型,依赖 display属性 + position属性 + float属性.它对于那些特殊布局非 ...

  3. Cassandra 键空间(keyspace),表(table)

    查看用户下信息: describe cluster; desc cluster;   查看所有keyspace: describe keyspaces; desc keyspaces;   查看key ...

  4. 关于成为Java高级工程师之路

    简单说明一下现状,个人目前学习使用java已经一年半,很迷茫,高不成低不就,在此列一个目标,为期18个月,再来个一年半,这样软件生涯三年后,我必须成为高级工程师! 这里涉及Java各个方面的知识,有的 ...

  5. Linux下man手册使用

    在 linux 环境下,为了查看一下 free 函数的原型,执行 man free 命令,发现显示结果为系统的 free 命令帮助,而不是库文件中的 free 函数帮助.查阅了一下,发现 man 的使 ...

  6. EntityFramework 使用经验

    1.Nuget控制台常用命令 1.获取EntityFramework命令帮助:get-help EntityFramework  2.在项目中启动数据迁移:Enable-Migrations 3.添加 ...

  7. 设置Beyond Compare 为 Git 默认的比较工具

    对于Beyond Compare4,Git版本号在2.2.0之后的,请在Git中依次输入以下命令: git config --global diff.tool bc3 git config --glo ...

  8. 用PHP调用Oracle存储过程方法

    //建立一个TEST表CREATE TABLE TEST (  ID        NUMBER(16)        NOT NULL,  NAME      VARCHAR2(30)      N ...

  9. 10 个实用技巧,让 Finder 带你飞

    Finder 是 Mac 电脑的系统程序,有的功能类似 Windows 的资源管理器.它是我们打开 Mac 首先见到的「笑脸」,有了它,我们可以组织和使用 Mac 里的几乎所有东西,包括应用程序.文件 ...

  10. 课程设计 --- 黑白棋中的 AI

    原文链接:https://www.dreamwings.cn/reversi/3013.html 到了考试周了佯,可是偏偏这个时候迎来了很多很多的课程设计,幸好教授把C语言的课程设计提前发出了,不然都 ...