Lec 04 系统调用
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
- 应用只需要记录内核返回的文件标识符
- fd代表该文件,用于之后对文件进行操作

6.7 关闭文件
- 不再需要访问文件
- 内核操作如下
-- 释放在文件打开时创建的数据结构
-- 把文件标识符返回到可用的标识符池 - 进程终止时的默认行为
-- 内核关闭所有打开的文件
-- 内核释放内存资源

6.8 读写文件
- 读操作:
-- 从文件中复制m>0个字节到内存中- 从当前文件的位置k开始,并更新k+=m
-- 如果从k开始到文件末尾的长度小于m,触发条件end-of-file(EOF) - EOF可以被应用检测
- 但是文件末尾实际上不存在EOF字符
- 从当前文件的位置k开始,并更新k+=m


6.9 文件:对所有设备的抽象
- 存储设备
-- File - 网络设备
-- socket - 其他设备
-- 同样是fd

6.10 操作系统设备的示例


Lec 04 系统调用的更多相关文章
- 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 ...
- xv6的作业翻译——作业1 - shell和系统调用
Xv6的lecture LEC 1 Operating systems L1: O/S overview L1:O/S概述 * 6.828 goals 6.828的目标 Understan ...
- [Linux]系统调用理解(2)
本文介绍了Linux下的进程概念,并着重讲解了与Linux进程管理相关的4个重要系统调用getpid,fork,exit和_exit,辅助一些例程说明了它们的特点和使用方法. 关于进程的一些必要知识 ...
- 如何在 Ubuntu 14.04 里面配置 chroot 环境
你可能会有很多理由想要把一个应用.一个用户或者一个环境与你的 Linux 系统隔离开来.不同的操作系统有不同的实现方式,而在 Linux 中,一个典型的方式就是 chroot 环境. 在这份教程中,我 ...
- linux OSlab4 添加自定义系统调用
http://blog.csdn.net/ly01kongjian/article/details/8947285 http://www.cnblogs.com/hoys/archive/2011/0 ...
- Linux系统调用--getrlimit()与setrlimit()函数详解
http://www.cnblogs.com/niocai/archive/2012/04/01/2428128.html 功能描述:获取或设定资源使用限制.每种资源都有相关的软硬限制,软限制是内核强 ...
- (转)详解汇编系统调用过程(以printf为例)
本文以printf为例,详细解析一个简单的printf调用里头,系统究竟做了什么,各寄存器究竟如何变化. 环境: linux + gnu as assembler + ld linker 如何在汇编调 ...
- 入门系列之使用Sysdig监视您的Ubuntu 16.04系统
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由乌鸦 发表于云+社区专栏 介绍 Sysdig是一个全面的开源系统活动监控,捕获和分析应用程序.它具有强大的过滤语言和可自定义的输出,以 ...
- 10-PI开发手册-ERP发布服务供外围系统调用(RFC类型)
一. 文档信息 版本号* 更新日期* 姓名* 更新内容及更新理由* 备注* V1.0 2019/02/19 fanjb 文档创建 以福利接口13589(Z00HRJ_GJJ_REV_FI ...
- 基于Linux-3.9.4内核的GDB跟踪系统调用实验
382 + 原创作品转载请注明出处 + https://github.com/mengning/linuxkernel/ 一.实验环境 win10 -> VMware -> Ubuntu1 ...
随机推荐
- 状态机DP
简介 简单来说就是从一个状态变成另一个状态的路径 感觉还是挺新颖的. 714 https://leetcode-cn.com/problems/best-time-to-buy-and-sell-st ...
- CLTX 笔试题目预览
error: multiple storage classes in declaration of `i' 代理服务器常用以下端口: (1). HTTP协议代理服务器常用端口号:80/8080/312 ...
- ETL知识了解并备份
大数据横行的时代,我们对数据越来越重视,从数据的采集.分析.展示每个过程关注进而针对客户完善数据.数据集成是把不同来源.格式和特点的数据在逻辑上或物理上有机地集中,从而为企业提供全面的数据共享,是企业 ...
- AppLink上的小鹅通能实现什么操作呢?
AppLink实现小鹅通信息同步操作 本篇文章给大家演示下小鹅通可在AppLink平台上快速实现的同步操作,1.用户注册或更换手机号信息同步 2.小鹅通产生新的购买订单,订单信息同步. 以下操作均需获 ...
- 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 高斯分布(正态分布) ...
- POLIR-Society-Organization-Politics: “How”-政治分析+组织建设:资源整合:集成"组织"+"人才"+"资源"+"资本" + 商业运营模式(本质问题:目标客户+问题+风险收益)
POLIR-Society-Organization-Politics: "How"-政治分析+组织建设: 资源整合,集成: 决策层: 大政方针 VS 执行层: 解决问题 决策层: ...
- 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 ...
- 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 ...
- 银河麒麟安装Docker-国产化-九五小庞
银河麒麟高级服务器操作系统 V10 是针对企业级关键业务,适应虚拟化. 云计算.大数据.工业互联网时代对主机系统可靠性.安全性.性能.扩展性和 实时性的需求,依据 CMMI 5 级标准研制的提供内生 ...
- chatgpt 集成飞书实践指南
开个境外服务器 目前OpenAI的API已向161个国家和地区开放,在亚洲范围内,日本.韩国.缅甸.印度.尼泊尔.巴基斯坦均在开放之列.openai对国内网络(包括香港)似乎都有屏蔽,刚好公司就有国际 ...