Lec 04 系统调用

目录

(参考来源:上海交通大学并行与分布式系统研究所+操作系统课程ppt)

Creative Commons Attribution 4.0 License

Contents

4.1 系统调用

  • 硬件提供了一对指令svc/eret指令在用户态/内核态间切换
  • 系统调用

    (1) 用户与操作系统之间,类似于过程调用的接口

    (2) 通过受限的方式访问内核提供的服务

4.1.2 AArch64下常见的Linux系统调用

4.1.3 系统调用举例

int main()
{
write(1, "hello, world\n", 13);
_exit(0);
}

转换成汇编语言

  .section .rodata
.LC0:
.string "hello, world\n"
.text
.align 2
.global main
.type main, %function
main:
// First, call write(1, "hello, world\n", 13)!
movq x8, #0x40 // write is system call 64
movq x0, #0x1 // Arg1:stdout has descriptor 1
adrp x3, .LC0
add x1,x3,:lo12:.LC0 // Arg2:Hello world string
movq x2, #0xd // Arg3:string length
svc // Make the system call
// Next, call exit(0)
movq x8, #0x5d // _exit is system call 93
movq x0, #0x0 // Arg1:exit status is 0
svc // Make the system call

4.1.3 系统调用的参数传递(常见软件的约定)

  • 最多允许8个参数

    (1) x0-x7寄存器

    (2) x8用于存放系统调用编号
  • 返回值存放于x0寄存器中

4.1.4 系统调用返回值与errno

  • 系统调用通过寄存器向应用传递返回值

    (1) 一般设置为 -errno

    (2) 库对系统调用的 wrapper code 会将系统调用的返回值转换为库函数形式的返回值

  • 寄存器放不下,只能通过内存传参

    (1) 将参数放在内存中,将指针放在寄存器中传给内核

    (2) 内核通过指针访问相关参数

    (3) 存在安全的隐患(后续课程会进一步介绍)

4.1.4 如何跟踪系统调用

4.1.5 系统调用流程图

4.2 系统调用优化(Virtual Dynamic Shared Object)

内核将一部分数据通过只读的形式共享给应用,允许应用直接读取。

4.2.1 动机

  • 系统调用的时延不可忽略

    (1) 尤其是调用非常频繁的情况

    (2) 系统调用实际执行逻辑很简单
  • 如何降低系统调用的时延?

    (1) 特权级切换造成的时间开销

    (2) 如果没有特权级切换,那么就不需要保存恢复状态

4.2.2 举例:gettimeofday

  • 内核定义

    (1) 在编译时作为内核的一部分
  • 用户态运行

    (2) 将gettimeofday的代码加载到一块与应用共享的内存页

    (3) 这个页称为:vDSO

    -- Virtual Dynamic Shared Object

    (4) Time 的值同样映射到用户态空间(只读)

    -- 只有在内核态才能更新这个值

4.2.3 Linux的vDSO

4.3 系统调用优化:FLEX-SC

4.3.1 动机

  • 如何进一步降低系统调用的时延?

    (1) 不仅仅是 gettimeofday()
  • "时间都去哪儿了?"

    (1) 大部分是用来做状态的切换

    (2) 保存和恢复状态 + 权限的切换

    (3) Cache pollution
  • 是否有可能在不切换状态的情况下实现系统调用?

4.3.2 Flexible System Call

  • 一种新的syscall机制

    (1) 引入 system call page ,由 user & kernel 共享

    (2) 用户进程可以将系统调用的请求 push 到 system call page

    (3) 内核会从system call page poll system call 请求
  • Exception-less syscall

    (1) 将系统调用的调用和执行解耦,可分布到不同的CPU核

4.3.3 exception less system call

举例

Kernel 填充syscall的返回值

4.3.4 单核上的单线程/多线程系统调用

  • 单内核单线程

    (1) 用户应用将多个系统调用推至系统调用页表

    (2) 切换到内核线程,内核线程从系统调用页表拉取系统调用。

    (3) 执行完系统调用后切换到应用态
  • 单内核多线程

    (1) 线程1将系统调用推至系统调用页表,并且切换到下一个线程,直到所有线程推送结束。

    (2) 下陷到内核态。内核拉取页表中的system call。

    (3) 执行完所有系统调用后返回内核态。

4.4 从应用视角看操作系统抽象

4.4.1 进程

1. 分时复用有限的CPU资源

(1) CPU核心数量少于应用程序数量,如何运行?

(2) 单个CPU核心如何运行多个应用程序?

  • 分时复用CPU

    (1) 让多个应用程序轮流使用处理器核心

    (2) 何时切换:操作系统决定

    -- 运行时间片(例如100ms)

    (3) 高频切换:看起来是多个应用“同时”执行

2. 应用程序与进程
  • 通常一个应用程序对应一个进程

    (1) 在shell中输入可执行文件的名称

    -- shell创建新进程,可执行文件在新进程中执行

    (2) 在图形界面双击应用图标
  • 多进程程序:应用程序亦可自行创建新进程

    (1) 创建新进程,在新进程中运行其他应用程序或与自己一样的程序
3. 进程在操作系统中的实现:状态数据
  • 操作系统提供进程的抽象用于管理应用程序

    (1) 进程标识号(Process ID, PID)

    (2) 运行状态

    -- 处理器上下文(CPU Context)

    (3) 地址空间

    (4) 打开的文件
4. 进程展示效果
  • 进程抽象为应用程序提供了“独占CPU”的假象

    (1) 程序开发不用考虑如何与其他程序共享CPU

    (2) 简化编程
  • 进程相关的系统调用

    (1) 创建进程

    (2) 让进程执行指定的程序

    (3) 退出进程

    (4) 进程间通信

4.5 进程切换

4.5.1 处理器上下文(CPU Context)

  • 操作系统为每个进程维护处理器上下文

    (1) 包含恢复进程执行所需要的状态

    (2) 思考:进程A执行到main函数任意一条指令,切换到进程B执行,一段时间后,再切回到进程A执行

    -- 为完成此过程,有哪些状态需要保存?

    (3) 具体包括:

    -- PC寄存器值,栈寄存器值,通用寄存器值,状态寄存器值

4.5.2 进程切换的时机

  • 异常导致的上下文切换

    (1) Timer中断(如基于时间片的多任务调度)

  • 用户执行系统调用并进入内核

    (1) 如:read/sleep等会导致进程阻塞的系统调用

    (2) 即使系统调用不阻塞执行,内核也可以决定执行上下文切换,而不是将控制权返回给调用进程

举例1

举例2

4.6 进程相关接口

4.6.1 获取进程ID

  • 进程 ID

    (1) 每个进程都有唯一的正数PID
  • Getpid()

    (1) 返回调用进程的PID
  • Getppid()

    (1) 返回调用进程父进程的PID

    (2) 父进程:创建该进程的进程

4.6.2 Exit 函数

exit函数终止进程并带上一个status状态

4.6.3 Fork 函数

  • 调用一次

    (1) 在父进程中
  • 返回两次

    (1) 在父进程中,返回子进程的PID

    (2) 在子进程中,返回0
  • 返回值提供了唯一明确地区分父进程和子进程执行的方法

4.6.4 execve 函数



  • 加载和运行

    (1) filename:可执行文件名;argv:参数列表,envp:环境变量列表
  • execve 只调用一次,且永远不会返回

    (1) 仅仅在运行报错的时候,返回调用程序

    (2) 例:找不到filename标识的文件

4.6.5 Linux下的僵尸进程

  • 进程终止后,内核不会立刻销毁该进程

    (1) 不再运行,但仍然占用内存资源
  • 进程以终止态存在,等待父进程回收
  • 当父进程回收终止的子进程

    (2) 内核把子进程的exit状态传递给父进程

    (3) 内核移除子进程,此时子进程才被真正回收
  • 终止状态下还未被回收的进程就是僵尸进程
  • 如果父进程在自己终止前没有回收僵尸子进程

    (4) 内核会安排init进程回收这些子进程
  • init进程

    (5) PID为1

    (6) 在系统初始化时由内核创建

4.6.6 waitpid函数



返回值:成功返回子进程 PID,出错返回 -1

  • pid>0:等待集合中只有pid子进程
  • pid=-1:等待集合包括所有子进程
  • 如果没有子进程:返回-1,errno = ECHILD
  • 如果等待被中断:返回-1,errno = EINTR
  • options=0

    (1) 挂起调用进程,等待集合中任意子进程终止

    (2) 如果等待集合中有子进程在函数调用前已经终止,立刻返回

    (3) 返回值是导致函数返回的终止子进程pid

    (4) 该终止子进程被内核回收
  • options=WNOHANG

    (1) 如果等待集合中没有终止子进程,立刻返回0
  • options=WUNTRACED

    (2) 除了返回终止子进程的信息外,还返回因信号而停止的子进程信息
  • options=WNOHANG|WUNTRACED

    (1) 带回被回收子线程的exit状态

    (2) status指针不为NULL

    (3) status包含导致子进程进入终止状态的信息

    (4) wait.h文件包含了若干宏定义,用于解释status

4.6.7 小结

4.7 内存



4.7.1 虚拟内存

  • 虚拟地址空间

    (1) 应用进程使用虚拟地址访问内存

    (2) 所有应用进程的虚拟地址空间都是统一的(方便开发)

  • 地址翻译

    (1) CPU按照OS配置的规则把虚拟地址翻译成物理地址

    (2) 翻译对于应用进程是不可见的(无需关心)

4.7.2 虚拟内存和物理内存

虚拟内存具有独立而统一的地址空间

5. ELF 文件格式

5.1 目标文件

  • 可执行目标文件
  • 可重定位目标文件(.o)
  • 共享目标文件(.so)

    (1) 特殊的可重定位目标文件

    (2) 可以加载到内存中

    (3) 支持动态链接:加载时或运行时

5.2 ELF:可执行可链接格式

  • 目标文件的标准二进制格式

    统一格式,又被称为ELF二进制文件
  • 用于BSD Unix和Linux

    最早用于AT&T System

5.3 ELF格式:可重定位目标文件

(1) ELF 头部(ELF Header)

  • ELF文件的第一个部分
  • 通常用于存元数据

    -- Magic number (‘0x7f’ ‘E’ ‘L’ ‘F’)

    -- 类型(.o, .so, 可执行)

    -- 机器架构

    -- 字节顺序(大小端)

    -- 节头部表的位置(文件内偏移)

(2) 节头部表(Section Header Table)

  • 节(section)

    -- ELF文件中除了头部和头部表划分为若干区域

    -- 每一个节在文件中时一块连续的字节(可能为空)

    -- 互不重叠
  • 每一个节都有一个节头部描述

    -- 节头部的一项

  • sh_name

    -- 节名称(在.strtab节中的偏移)
  • sh_addr

    -- 节在加载到内存后,在内存的起始地址
  • sh_offset

    -- 节在文件中的偏移(字节数)
  • sh_size

    -- 节的大小(字节数)
  • sh_addralign

    -- 对齐要求

(3) ELF字符串表(.strtab)

  • 记录一系列C风格字符串

    -- 以'\0’结尾
  • 表示符号名或节名

    -- 使用时记录字符串在表中的偏移(index)

(4) 用以调试的节

  • .debug

    -- 调试符号表,包括变量(全局、局部)、typedef、C源文件

    -- gcc –g生成
  • .line

    -- C源文件的行数与.text节中指令的映射

(5) 代码与数据节

  • .text:代码
  • .rodata:只读数据
  • .data:初始化的全局变量和静态变量
  • .bss:未初始化的全局变量和静态变量

    -- “Block Started by Symbol”,“Better Save Space”

    -- 不占文件空间,但是在节头部表中有记录

    -- 运行时分配内存,默认为0

5.4 可执行目标文件

  • ELF头部(ELF header)

    -- 整体信息

    -- 程序入口 (e_entry)

    -- 程序头部表信息

    • 在文件中的起始位置(e_phoff)
    • 大小(e_ehsize)
    • 每个条目的大小(e_phentsize)
    • 条目数量(e_phnum)

程序头部表

  • Program (Segment) Header Table

    p_type
  • PT_LOAD (1): 可加载段

    p_flags

    -- 运行时权限 (rwx)
  • p_offset

    -- 段在文件中的起始偏移
  • p_filesz

    -- 段在文件中的大小( 段在内存中的大小p_memsz)
  • p_vaddr

    -- 段在内存中的起始(虚拟)地址
  • p_paddr (不常用,x86、ARM 下不用)
  • p_memsz

    -- 段在内存中的大小(p_filesz)
  • p_align

    -- 段起始地址的对齐要求

    通常为2^12 (4K) 或 2^21 (2M)

6. 文件

6.1 UNIX 文件

  • Unix 文件是一串字节序列。

    -- \(B_0,B_1,\ldots,B_k,\ldots,B_m\)
  • 所有的IO设备都被抽象成文件

    -- 如:网络设备,硬盘,终端

    -- Unix提供一个基于文件的底层应用接口,即UNIX I/O
  • 所有输入,输出都是通过读,写文件完成

    -- 所有的输入输出都具有统一的表现形式

6.2 文件类型1

  • 普通文件(regular file):包含任意数据

    -- 从应用程序的角度来看有两种

    • 文本文件:仅包含ASCII和UNICODE字符
    • 二进制文件:除了文本文件以外的所有

      -- 从内核的角度来看没有区别

6.3 文件类型2

  • 目录(directory)也是一个文件

    -- 由有链接(links)构成

    -- 每个链接将一个文件名映射到一个文件(或目录)

    -- 每个目录至少有两个链接:

    • . (dot):到文件夹本身的链接
    • . . (dot-dot):到上一层文件夹的链接

      -- 目录相关指令:mkdir、ls、rmdir等

6.4 目录层级

  • Linux内核使用层次化目录来组织所有文件

    -- /:代表根目录

    -- 每个文件都是根目录直接或间接的后代

6.5 文件类型3

  • 套接字(Socket)也是文件,用于跨网络进程交互
  • 其他文件类型包括:

    -- 命名管道(named pipes)

    -- 符号连接(symbolic links)

    -- 字符/块设备(character/block devices)

    ...

6.6 打开文件

  • 应用准备访问一个IO设备

    -- 内核打开相关文件,并返回一个非负整数,作为文件标识符(file descriptor, fd)

    • fd代表该文件,用于之后对文件进行操作

      -- 内核跟踪记录每个进程的所有打开文件的信息
    • 对于每个打开文件,维护一个文件内偏移k
    • 应用可以通过seek函数,显式改变当前文件内偏移k
    • 应用只需要记录内核返回的文件标识符

6.7 关闭文件

  • 不再需要访问文件
  • 内核操作如下

    -- 释放在文件打开时创建的数据结构

    -- 把文件标识符返回到可用的标识符池
  • 进程终止时的默认行为

    -- 内核关闭所有打开的文件

    -- 内核释放内存资源

6.8 读写文件

  • 读操作:

    -- 从文件中复制m>0个字节到内存中

    • 从当前文件的位置k开始,并更新k+=m

      -- 如果从k开始到文件末尾的长度小于m,触发条件end-of-file(EOF)
    • EOF可以被应用检测
    • 但是文件末尾实际上不存在EOF字符

6.9 文件:对所有设备的抽象

  • 存储设备

    -- File
  • 网络设备

    -- socket
  • 其他设备

    -- 同样是fd

6.10 操作系统设备的示例

Lec 04 系统调用的更多相关文章

  1. Ubuntu 14.04 + Linux 3.14.34 系统调用实现文件拷贝

    采用 64位系统, ubuntu 14.04 + 新内核linux-3.14.34 下载地址https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.1 ...

  2. xv6的作业翻译——作业1 - shell和系统调用

    Xv6的lecture LEC 1 Operating systems   L1: O/S overview L1:O/S概述   * 6.828 goals 6.828的目标   Understan ...

  3. [Linux]系统调用理解(2)

    本文介绍了Linux下的进程概念,并着重讲解了与Linux进程管理相关的4个重要系统调用getpid,fork,exit和_exit,辅助一些例程说明了它们的特点和使用方法. 关于进程的一些必要知识 ...

  4. 如何在 Ubuntu 14.04 里面配置 chroot 环境

    你可能会有很多理由想要把一个应用.一个用户或者一个环境与你的 Linux 系统隔离开来.不同的操作系统有不同的实现方式,而在 Linux 中,一个典型的方式就是 chroot 环境. 在这份教程中,我 ...

  5. linux OSlab4 添加自定义系统调用

    http://blog.csdn.net/ly01kongjian/article/details/8947285 http://www.cnblogs.com/hoys/archive/2011/0 ...

  6. Linux系统调用--getrlimit()与setrlimit()函数详解

    http://www.cnblogs.com/niocai/archive/2012/04/01/2428128.html 功能描述:获取或设定资源使用限制.每种资源都有相关的软硬限制,软限制是内核强 ...

  7. (转)详解汇编系统调用过程(以printf为例)

    本文以printf为例,详细解析一个简单的printf调用里头,系统究竟做了什么,各寄存器究竟如何变化. 环境: linux + gnu as assembler + ld linker 如何在汇编调 ...

  8. 入门系列之使用Sysdig监视您的Ubuntu 16.04系统

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由乌鸦 发表于云+社区专栏 介绍 Sysdig是一个全面的开源系统活动监控,捕获和分析应用程序.它具有强大的过滤语言和可自定义的输出,以 ...

  9. 10-PI开发手册-ERP发布服务供外围系统调用(RFC类型)

      一.      文档信息 版本号* 更新日期* 姓名* 更新内容及更新理由* 备注* V1.0 2019/02/19 fanjb 文档创建 以福利接口13589(Z00HRJ_GJJ_REV_FI ...

  10. 基于Linux-3.9.4内核的GDB跟踪系统调用实验

    382 + 原创作品转载请注明出处 + https://github.com/mengning/linuxkernel/ 一.实验环境 win10 -> VMware -> Ubuntu1 ...

随机推荐

  1. 状态机DP

    简介 简单来说就是从一个状态变成另一个状态的路径 感觉还是挺新颖的. 714 https://leetcode-cn.com/problems/best-time-to-buy-and-sell-st ...

  2. CLTX 笔试题目预览

    error: multiple storage classes in declaration of `i' 代理服务器常用以下端口: (1). HTTP协议代理服务器常用端口号:80/8080/312 ...

  3. ETL知识了解并备份

    大数据横行的时代,我们对数据越来越重视,从数据的采集.分析.展示每个过程关注进而针对客户完善数据.数据集成是把不同来源.格式和特点的数据在逻辑上或物理上有机地集中,从而为企业提供全面的数据共享,是企业 ...

  4. AppLink上的小鹅通能实现什么操作呢?

    AppLink实现小鹅通信息同步操作 本篇文章给大家演示下小鹅通可在AppLink平台上快速实现的同步操作,1.用户注册或更换手机号信息同步 2.小鹅通产生新的购买订单,订单信息同步. 以下操作均需获 ...

  5. SciTech-Mathmatics-Proba. & Stats.: $\large y=ax^2 + bx + c$(非常重要的 抛物线函数) + $\large 高斯分布(正态分布)的Bell Curve钟形曲线 的 pdf(概率分密度曲线方程) 与 cdf(累积分布函数:积分面$积)

    SciTech-Mathmatics-Proba. & Stats.: \(\largey=ax^2 + bx + c\)(非常重要的 抛物线函数) + \(\large 高斯分布(正态分布) ...

  6. POLIR-Society-Organization-Politics: “How”-政治分析+组织建设:资源整合:集成"组织"+"人才"+"资源"+"资本" + 商业运营模式(本质问题:目标客户+问题+风险收益)

    POLIR-Society-Organization-Politics: "How"-政治分析+组织建设: 资源整合,集成: 决策层: 大政方针 VS 执行层: 解决问题 决策层: ...

  7. POLIR-Society-Organization-Management:Transform Business Skills with Proven Simulation and Assessment Technology

    Capsim Management Simulations, Inc. Privacy Policy Terms Accessibility Policy Transform Business Ski ...

  8. Linguistics-English-Would, Should, and Could: How to Use Them Correctly

    https://7esl.com/would-should-could/ Compare Can, Could and Would Can: capacity Could: possibility W ...

  9. 银河麒麟安装Docker-国产化-九五小庞

     银河麒麟高级服务器操作系统 V10 是针对企业级关键业务,适应虚拟化. 云计算.大数据.工业互联网时代对主机系统可靠性.安全性.性能.扩展性和 实时性的需求,依据 CMMI 5 级标准研制的提供内生 ...

  10. chatgpt 集成飞书实践指南

    开个境外服务器 目前OpenAI的API已向161个国家和地区开放,在亚洲范围内,日本.韩国.缅甸.印度.尼泊尔.巴基斯坦均在开放之列.openai对国内网络(包括香港)似乎都有屏蔽,刚好公司就有国际 ...