此为个人笔记存档

week 4 系统调用(上)

一、用户态、内核态和中断处理过程

用户通过库函数与系统调用联系起来。

1.内核态

在高执行级别下,代码可以执行特权指令,访问任意的物理地址

2.用户态:

代码的掌控范围受到限制。

intel x86 CPU有四个权限分级,0-3。Linux只取两种,0是内核态,3是用户态

区分权限级别使得系统更加稳定。

如何区分用户态与内核态?

cs:eip。[代码段选择寄存器:偏移量寄存器]

通过cs寄存器的最低两位,表示当前代码的特权级:

【针对逻辑地址】

0xc0000000以上的空间只能在内核态下访问

0x00000000-0xbfffffff两种状态下都可以访问

如何进行切换?

中断。

3.中断

中断处理是从用户态进入内核态的主要方式。

 - 硬件中断
- 系统调用
  1. 寄存器上下文

    从用户态切换到内核态时,必须保存用户态的寄存器上下文到内核堆栈中,同时会把当前内核态的一些信息加载,例如cs:eip指向中断处理程序入口。

    • 用户态栈顶地址
    • 当时状态字
    • 当时cs:eip
    • ……
  2. 中断发生后的第一件事就是保存现场 - SAVE_ALL

    中断处理结束前最后一件事是恢复现场 - RESTORE_ALL

二、系统调用概述

1. 系统调用的意义:

操作系统为用户态进程与硬件设备进行交互提供了一组接口,就是系统调用。

- 远离底层硬件编程
- 安全性
- 可移植性

2. API - 应用编程接口

与系统调用区别:

- API只是一个函数定义
- 系统调用是通过软中断向内核发出一个明确的请求。

一般每个系统调用对应一个封装例程,库再用这些封装例程定义出用户的API,方便用户使用。

也就是说,API与系统调用不是一一对应的

API可以:
- 直接提供用户态服务
- 一个单独的API可能调用几个系统调用
- 不同的API可能调用了同一个系统调用

返回值:

 - 大部分封装例程返回一个整数
- -1表示失败,不能满足请求
- errno 特定出错码

3.所谓“扒开系统调用的三层皮”

  • API(xyz)
  • 中断向量(system_call)
  • 中断服务程序(sys_xyz)



    1.系统调用的服务例程中,中断向量0x80与system_call绑定起来。(Linux中可以通过执行int $128来执行系统调用。)

    2.system_call是linux中所有系统调用的入口点,每个系统调用至少有一个参数,即系统调用号。

    3.系统调用号将xyz与sys_xyz关联起来。调用号在eax中。

系统调用的参数传递:

  • 函数调用——压栈
  • 用户态到内核态——寄存器传递。

    每个参数长度不能超过32位,个数不能超过6个。

    超过的话?

    使某个寄存器中存储指针,指向内存,内存中存储参数。

三、使用库函数API和C代码中嵌入汇编代码触发同一个系统调用

1.使用库函数API获取系统当前时间

使用time(),代码如下:

#include<stdio.h>
#include<time.h> int main()
{
time_t tt;
struct tm *t;//构造一个结构体,方便读取
tt = time(NULL);//time系统调用
t = localtime(&tt);
printf("time:%d:%d:%d:%d:%d:%d\n", t->tm_year+1900, t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
return 0;
}

执行如下:

2.使用C代码中嵌入汇编代码触发系统调用获取系统当前时间

代码如下:

#include<stdio.h>
#include<time.h> int main()
{
time_t tt;
struct tm *t;
asm volatile(
"mov $0,%%ebx\n\t" # 把ebx清零,相当于传参数
"mov $0xd,%%eax\n\t" # 把0xd放入eax中,即系统调用号13,指time
"int $0x80\n\t"
"mov %%eax,%0\n\t" # 返回值是在eax中,%0指tt,把返回值放到tt中去。
: "=m" (tt)
);
t = localtime(&tt);
printf("time:%d:%d:%d:%d:%d:%d\n", t->tm_year+1900, t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
return 0;
}

可以从中看出用户态向内核态做了什么:

1.传递了一个系统调用号 - eax

2.传递了参数 - ebx

执行如下:

20135202闫佳歆--week4 系统调用(上)--学习笔记的更多相关文章

  1. 20135202闫佳歆--week4 两种方式使用同一个系统调用--实验及总结

    实验四 使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用 在这里我选择的是第20号系统调用,getpid. 1.使用库函数API: 代码如下: /* getpid.c */ #incl ...

  2. 20135202闫佳歆--week5 系统调用(下)--学习笔记

    此为个人笔记存档 week 5 系统调用(下) 一.给MenuOS增加time和time-asm命令 这里老师示范的时候是已经做好的了: rm menu -rf 强制删除 git clone http ...

  3. 20135202闫佳歆--week4 课本第5章学习笔记

    第五章 系统调用 一.与内核通信 系统调用在用户控件进程和硬件设备之间添加了一个中间层,作用如下" 为用户空间提供了一种硬件的抽象接口 系统调用保证了系统的稳定和安全 每个进程都运行在虚拟系 ...

  4. 20135202闫佳歆--week3 跟踪分析Linux内核的启动过程--实验及总结

    实验三:跟踪分析Linux内核的启动过程 一.调试步骤如下: 使用gdb跟踪调试内核 qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd r ...

  5. 20135202闫佳歆--week 7 Linux内核如何装载和启动一个可执行程序--实验及总结

    week 7 实验:Linux内核如何装载和启动一个可执行程序 1.环境搭建: rm menu -rf git clone https://github.com/megnning/menu.git c ...

  6. 20135202闫佳歆--week 9 期中总结

    期中总结 前半学期的主要学习内容是学习mooc课程<Linux内核分析>以及课本<Linux内核设计与实现>. 所涉及知识点总结如下: 1. Linux内核启动的过程--以Me ...

  7. 20135202闫佳歆--week2 一个简单的时间片轮转多道程序内核代码及分析

    一个简单的时间片轮转多道程序内核代码及分析 所用代码为课程配套git库中下载得到的. 一.进程的启动 /*出自mymain.c*/ /* start process 0 by task[0] */ p ...

  8. 20135202闫佳歆--week6 分析Linux内核创建一个新进程的过程——实验及总结

    week 6 实验:分析Linux内核创建一个新进程的过程 1.使用gdb跟踪创建新进程的过程 准备工作: rm menu -rf git clone https://github.com/mengn ...

  9. 20135202闫佳歆--week6 进程的描述与创建--学习笔记

    此为个人学习笔记存档! week 6 进程的描述与创建 一.进程的描述 1.进程控制块task_struct 以下内容来自视频课件,存档在此. 为了管理进程,内核必须对每个进程进行清晰的描述,进程描述 ...

随机推荐

  1. 团队-UML

    UML设计 分工 刘双玉 李佳铭 杜宏庆 肖小强 汪志彬 江郑 符天愉 邓弘立 后台数据库 求购模块 浏览检索商品 即时聊天系统 商品管理 管理员系统 后台商品发布收藏系统 登录注册与个人信息系统 U ...

  2. Python glob.md

    glob 即使glob API非常简单, 但这个模块包含了很多的功能. 在很多情况下, 尤其是你的程序需要寻找出文件系统中, 文件名匹配特定模式的文件时, 是非常有用的. 如果你需要包含一个特定扩展名 ...

  3. python第三十一课--递归(2.遍历某个路径下面的所有内容)

    需求:遍历某个路径下面的所有内容(文件和目录,多层级的) import os #自定义函数(递归函数):遍历目录层级(多级) def printDirs(path): dirs=os.listdir( ...

  4. Spring-IOC XML 配置多个相同 ID 的 bean 加载分析

    我们现在仍以 xml 中配置 bean 的方式来 使用 Spring ,不考虑注解和扫包 配置相同id 的bean 定义一个 bean 类 TransactionManager /** * @auth ...

  5. NOIP模拟赛-2018.11.7

    NOIP模拟赛 如果用命令行编译程序可以发现没加头文件之类的错误. 如果用命令行编译程序可以发现没加头文件之类的错误. 如果用命令行编译程序可以发现没加头文件之类的错误. 编译之前另存一份,听说如果敲 ...

  6. Publisher和Subscriber节点

    一.Publisher节点 /*"ros/ros.h"里面包含了ROS系统内最常用的一些头文件,包含此文件,便可以使用ROS的核心功能.*/#include "ros/r ...

  7. 使用react-navigation时报错:undefined is not an object (evaluating rngesturehandlermodule.direction)

    问题: 使用react-navigation时报错:undefined is not an object (evaluating rngesturehandlermodule.direction). ...

  8. [c.c.a.m.AgentManagerImpl] (AgentConnectTaskPool-39:ctx-c37090c5) Failed to handle host connection: java.lang.IllegalArgumentException: Can't add host: with h

    如果无法添加成功,/etc/redhat-release文件覆盖过去 cat /etc/redhat-release CentOS Linux release 7.1.1503 (Core)Red H ...

  9. C# 含转义符的字符串处理

    如果一个字符串中含有特殊字符,比如"号,如何将一个含有引号"的字符串赋值给一个变量. string a = @"sfsfsf"""; str ...

  10. Xcode添加全局引用文件pch

    Xcode6之前有PrefixHeader.pch文件在写项目的时候,大部分宏定义.头文件都导入在这个pch文件,虽然方便,但会增加Build的时间,所以Xcode6以及之后的版本去除了PrefixH ...