7.1-系统调用和 UNIX Shell

2023-11-05

复习

  • 状态机模型 (程序、多线程程序、操作系统)
  • 操作系统是状态机的管理者

本次课回答的问题

  • Q: 我们是操作系统的用户;但操作系统提供的 API 并不是 “我们” 作为人类用户能直接使用的。那 “我们” 到底怎么用操作系统?

本次课主要内容

  • UNIX Shell 的设计和实现

一、Shell

半学期小结:我们都学了什么?

整个计算机系统世界的 “构建”

  • 硬件 (NEMU):从 CPU Reset 开始执行指令 (计算和 I/O)
  • Firmware: 加载操作系统
  • 操作系统:状态机的管理者
    • 初始化第一个进程 (状态机)
    • 执行系统调用

例子:linux-minimal.zip

  • 整个系统里只需要 “一个程序”
    • busybox/toybox/…
  • 这个程序可以再执行各种应用程序
    • vim; dosbox; xeyes; …

为用户封装操作系统 API

我们需要一个 “用户能直接操作” 的程序管理操作系统对象。

这就是 Shell (内核 Kernel 提供系统调用;Shell 提供用户接口)

  • “与人类直接交互的第一个程序”
  • 帮助人类创建/管理进程 (应用程序)、数据文件……

The UNIX Shell

“终端” 时代的伟大设计

  • “Command-line interface” (CLI) 的巅峰

Shell 是一门 “把用户指令翻译成系统调用” 的编程语言

  • man sh (推荐阅读!), bash, …
  • 原来我们一直在编程
    • 直到有了 Graphical Shell (GUI)
    • Windows, Gnome, Symbian, Android

二、复刻经典

脾气有点小古怪的 UNIX 世界

“Unix is user-friendly; it’s just choosy about who its friends are.”

  • 但如果把 shell 理解成编程语言,“不好用” 好像也没什么毛病了
    • 你见过哪个编程语言 “好用” 的?

img

(UNIX 世界有很多历史遗留约定)

A Zero-dependency UNIX Shell (from xv6)

sh-xv6.c

  • 零库函数依赖 (-ffreestanding 编译、ld 链接)
  • 可以作为最小 Linux 的 init 程序
  • 用到文件描述符:一个打开文件的 “指针”

支持的功能

  • 命令执行 ls
  • 重定向 ls > a.txt
  • 管道 ls | wc -l
  • 后台 ls &
  • 命令组合 (echo a ; echo b) | wc -l

gcc -c -ffreestanding sh-xv6.c -g -O2
ld sh-xv6.o -o sh
file sh
# sh: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, with debug_info, not stripped

objdump -d sh | less
# sh:     文件格式 elf64-x86-64
# Disassembly of section .text:
# 0000000000401000 <syscall>:
#   401000:       48 8d 44 24 08          lea    0x8(%rsp),%rax
#   401005:       48 89 74 24 d8          mov    %rsi,-0x28(%rsp)
#   40100a:       4d 89 c2                mov    %r8,%r10
#   40100d:       48 89 44 24 c0          mov    %rax,-0x40(%rsp)
#   401012:       48 8d 44 24 d0          lea    -0x30(%rsp),%rax
#   401017:       48 89 54 24 e0          mov    %rdx,-0x20(%rsp)
#   40101c:       48 89 44 24 c8          mov    %rax,-0x38(%rsp)
#   401021:       48 63 c7                movslq %edi,%rax
#   401024:       48 89 f7                mov    %rsi,%rdi
#   401027:       48 89 d6                mov    %rdx,%rsi
#   40102a:       48 89 4c 24 e8          mov    %rcx,-0x18(%rsp)
#   40102f:       48 89 ca                mov    %rcx,%rdx

/start


gdb sh
starti
layout src
n
n
s
s
n
n
finish
n

A Zero-dependency UNIX Shell (from xv6)

img

我们应该如何阅读 sh-xv6.c 的代码?

  • strace + gdb!
    • set follow-fork-mode, set follow-exec-mode

关键点

  • 命令的执行、重定向、管道和对应的系统调用
  • 这里用到 minimal.S 会简化输出
echo './a.out > /tmp/a.txt' | strace -f ./sh
  • 还可以用管道过滤不想要的系统调用

The Shell Programming Language

基于文本替换的快速工作流搭建

  • 重定向: cmd > file < file 2> /dev/null
  • 顺序结构: cmd1; cmd2, cmd1 && cmd2, cmd1 || cmd2
  • 管道: cmd1 | cmd2
  • 预处理: $(), <()
  • 变量/环境变量、控制流……

Job control

  • 类比窗口管理器里的 “叉”、“最小化”
    • jobs, fg, bg, wait
    • (今天的 GUI 并没有比 CLI 多做太多事)

UNIX Shell: Traps and Pitfalls

img

在 “自然语言”、“机器语言” 和 “1970s 的算力” 之间达到优雅的平衡

  • 平衡意味着并不总是完美

  • 操作的 “优先级”?
    • ls > a.txt | cat (bash/zsh)
  • 文本数据 “责任自负”
    • 有空格?后果自负!(PowerShell: 我有 object stream pipe 啊喂)
  • 行为并不总是 intuitive
$ echo hello > /etc/a.txt
bash: /etc/a.txt: Permission denied
$ sudo echo hello > /etc/a.txt
bash: /etc/a.txt: Permission denied

展望未来

Open question: 我们能否从根本上改变命令行的交互模式?

Shell 连接了用户和操作系统

  • 是 “自然语言”、“机器语言” 之间的边缘地带!
  • 非常适合 BERT 这样的语言模型

已经看到的一些方向

三、终端和 Job Control

Shell 还有一些未解之谜

为什么 Ctrl-C 可以退出程序?

为什么有些程序又不能退出?

  • 没有人 read 这个按键,为什么进程能退出?
  • Ctrl-C 到底是杀掉一个,还是杀掉全部?
    • 如果我 fork 了一份计算任务呢?
    • 如果我 fork-execve 了一个 shell 呢?
      • Hmmm……

为什么 fork-printf.c 会在管道时有不同表现?

  • libc 到底是根据什么调整了缓冲区的行为?

为什么 Tmux 可以管理多个窗口?

答案:终端

终端是 UNIX 操作系统中一类非常特别的设备!

  • RTFM: tty, stty, …

观察 Tmux 的实现

img

首先,我们可以 “使用” tmux

  • 在多个窗口中执行 tty,会看到它们是不同的终端设备!

然后,我们也可以把 tmux “打开”

  • strace (-o) 可以看到一些关键的系统调用 (以及 man 7 pty)

终端相关的 API

为什么 fork-printf 能识别 tty 和管道?

  • 当然是观察 strace 了!
    • 找到是哪个系统调用 “识别” 出了终端?

#include <stdio.h>

int main() {
  printf("Hello, World\n");
}

Session, Process Group 和信号

img

参考 signal-handler.c

SIGSEGV 和 SIGFPE

大家熟悉的 Segmentation Fault/Floating point exception (core dumped)

  • #GP, #PF 或 #DIV
    • UNIX 系统会给进程发送一个信号
    • 此时可以生成一个 “core” 文件 (ELF 格式),能用 gdb 调试

UNIX (System V) 信号其实是有一些 dark corners 的

  • 如果 SIGSEGV 里再次 SIGSEGV?
    • POSIX.1 solved the portability mess by specifying sigaction(2), which provides explicit control of the semantics when a signal handler is invoked; use that interface instead of signal().
      • 支持多线程 (早期的 UNIX 还没有多线程)、信号屏蔽、……

Job Control 背后的机制

RTFM: setpgid/getpgid(2),它解释了 process group, session, controlling terminal 之间的关系

——你神奇地发现,读手册不再是障碍了!

  • The PGID (process-group ID) is preserved across an execve(2) and inherited in fork(2)…
  • Each process group is a member of a session

img

Job Control: RTFM (cont’d)

  • A session can have a controlling terminal.
    • At any time, one (and only one) of the process groups in the session can be the foreground process group for the terminal; the remaining process groups are in the background.
      • ./a.out & 创建新的进程组 (使用 setpgid)
    • If a signal is generated from the terminal (e.g., typing the interrupt key to generate SIGINT), that signal is sent to the foreground process group.
      • Ctrl-C 是终端 (设备) 发的信号,发给 foreground 进程组
      • 所有 fork 出的进程 (默认同一个 PGID) 都会收到信号
      • 可以修改 signal-handler.c 观察到这个行为

Job Control: RTFM (cont’d)

  • Only the foreground process group may read(2) from the terminal; if a background process group tries to read(2) from the terminal, then the group is sent a SIGTTIN signal, which suspends it.
    • 这解释了 cat & 时你看到的 “suspended (tty input)”
    • 同一个进程组的进程 read tty 会竞争
    • signal-handler.c 同样可以观察到这个行为

  • The setpgid() and getpgrp() calls are used by programs such as bash(1) to create process groups in order to implement shell job control.
    • 如果希望从进程组里 detach, 使用 setpgid
    • ps -eo pid,pgid,cmd 可以查看进程的 pgid

总结

本次课回答的问题

  • Q: 我们作为用户,到底怎么 “使用” 操作系统?

Take-away messages

  • 一个功能完整的 Shell 使用的操作系统对象和 API

    • session, process group, controlling terminal
    • 文件描述符:open, close, pipe, dup, read, write
    • 状态机管理:fork, execve, exit, wait, signal, kill, setpgid, getpgid, …
  • 随着 “零依赖” 的

    sh-xv6.c

    ,操作系统的神秘感逐渐消失

    • (下次课拆开库函数)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

7.1-系统调用和 UNIX Shell 的相关文章

  • Qt 嵌入式触摸屏 QMouseEvents 在收到 MouseButtonRelease 之前未收到

    我在带有触摸屏的小型 ARM 嵌入式 Linux 设备上使用 Qt 4 8 3 我的触摸屏配置了 tslib 并对其进行了校准 因此 etc 中有一个 pointcal 文件 我的触摸事件的位置工作得很好 但无论如何我都会在鼠标按下或鼠标释
  • 基于 Unix ASCII 的命令行图表/绘图工具

    有没有好的命令行 UNIX 图表 绘图 绘图工具 我正在寻找能够在 ASCII 图表上绘制 xy 点的东西 澄清一下 我正在寻找能够以 ASCII 格式输出图形 如 ascii art 风格 的东西 这样我就可以在交互式 shell 会话中
  • 如何将一个文本文件拆分为多个 *.txt 文件?

    我有一个文本文件file txt 12 MB 包含 something1 something2 something3 something4 有没有办法分开file txt分成 12 个 txt 文件 比方说file2 txt file3 t
  • 对于任何真实数据集,数据压缩比的最小可能值是多少

    我在写信ZLIB类似于嵌入式硬件压缩器的 API 它使用 deflate 算法来压缩给定的输入流 在进一步讨论之前 我想解释一下数据压缩率 数据压缩率定义为未压缩大小与压缩大小之间的比率 压缩比通常大于一 这意味着压缩数据通常比未压缩数据小
  • 使用脚本检查 git 分支是否领先于另一个分支

    I have branch1 and branch2我想要某种 git branch1 isahead branch2 这将显示如果branch1已承诺branch2没有 也可能指定这些提交 我无法检查差异原因branch2 is在之前br
  • 更新Linux中的包含路径

    我的 my path to file 文件夹中有几个头文件 我知道如何将这些文件包含在新的 C 程序中 但每次我都需要在包含它之前输入头文件的完整路径 我可以在linux中设置一些路径变量 以便它自动查找头文件吗 您可以创建一个 makef
  • MySQL 与 PHP 的连接无法正常工作

    这是我的情况 我正在尝试使用 Apache 服务器上的 PHP 文件连接到 MySQL 数据库 现在 当我从终端运行 PHP 时 我的 PHP 可以连接到 MySQL 数据库 使用 php f file php 但是当我从网页执行它时 它只
  • Docker忽略limits.conf(试图解决“打开文件太多”错误)

    我正在运行一个 Web 服务器 该服务器正在处理数千个并发 Web 套接字连接 为了实现这一点 在 Debian linux 我的基本镜像是 google debian wheezy 在 GCE 上运行 上 打开文件的默认数量设置为 100
  • bash while 循环的布尔表达式中的 -lt 意味着什么?

    我猜测它代表小于基于输出 但是我在哪里可以找到有关此语法的文档 bin bash COUNTER 0 while COUNTER lt 10 do echo The counter is COUNTER let COUNTER COUNTE
  • Python glob,操作系统,相对路径,将文件名放入列表中[重复]

    这个问题在这里已经有答案了 我正在尝试创建一个目录中所有文件的列表 其中文件名以 root 结尾 在阅读了论坛中的一些文章后 我尝试使用 glob 和 os listdir 的基本策略 但我都遇到了麻烦 首先 当我使用 import glo
  • LINUX:如何锁定内存中进程的页面

    我有一个 LINUX 服务器 运行一个具有大量内存占用的进程 某种数据库引擎 该进程分配的内存太大 需要将其中一部分换出 换出 我想做的是将所有其他进程 或正在运行的进程的子集 的内存页面锁定在内存中 以便只有数据库进程的页面被换出 例如
  • 来自守护程序的错误响应:加入会话密钥环:创建会话密钥:超出磁盘配额

    我尝试在我的服务器上安装 docker 使用本教程 https docs docker com install linux docker ce ubuntu 我想远程运行 docker 镜像并使用 portainer Web 界面来管理一切
  • 如何才能将 TCP 连接返回到同一端口?

    机器是 RHEL 5 3 内核 2 6 18 有时我在 netstat 中注意到我的应用程序有连接 建立了 TCP 连接本地地址 and 国外地址是一样的 其他人也报告了同样的问题 症状与链接中描述的相同 客户端连接到本地运行的服务器的端口
  • Perl 和 Unix 如何以相同的顺序对 Unicode 字符串进行排序?

    我正在尝试获取 Perl 和 GNU Linuxsort 1 程序就如何对 Unicode 字符串进行排序达成一致 我在跑sort with LANG en US UTF 8 在Perl程序中我尝试了以下方法 use Unicode Col
  • vmsplice() 和 TCP

    在原来的vmsplice 执行 有人建议 http lwn net Articles 181169 如果您的用户态缓冲区是管道中可容纳的最大页面数的 2 倍 则缓冲区后半部分成功的 vmsplice 将保证内核使用缓冲区的前半部分完成 但事
  • 批量删除文件名中包含 BASH 中特殊字符的子字符串

    我的目录中有一个文件列表 opencv calib3d so2410 so opencv contrib so2410 so opencv core so2410 so opencv features2d so2410 so opencv
  • 执行命令而不将其保留在历史记录中[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 在进行软件开发时 经常需要在命令行命令中包含机密信息 典型示例是将项目部署到服务器的凭据设置为环境变量 当我不想将某些命令存储在命令历史记
  • SSH,运行进程然后忽略输出

    我有一个命令可以使用 SSH 并在 SSH 后运行脚本 该脚本运行一个二进制文件 脚本完成后 我可以输入任意键 本地终端将恢复到正常状态 但是 由于该进程仍在我通过 SSH 连接的计算机中运行 因此任何时候它都会登录到stdout我在本地终
  • 相当于Linux中的导入库

    在 Windows C 中 当您想要链接 DLL 时 您必须提供导入库 但是在 GNU 构建系统中 当您想要链接 so 文件 相当于 dll 时 您就不需要链接 为什么是这样 是否有等效的 Windows 导入库 注意 我不会谈论在 Win
  • 如何使用 JSch 将多行命令输出存储到变量中

    所以 我有一段很好的代码 我很难理解 它允许我向我的服务器发送命令 并获得一行响应 该代码有效 但我想从服务器返回多行 主要类是 JSch jSch new JSch MyUserInfo ui new MyUserInfo String

随机推荐

  • 微信小程序钱包支付页面案例

    小程序钱包页面 效果图 WXML代码
  • 数据结构 图 part1

    文章目录 图 定义 形式化定义 ADT 有向图和无向图 有向图 无向图 完全有向图和完全无向图 完全无向图 完全有向图 术语 邻接顶点 子图 权 网 度 顶点的度 路径 路径长度 连通图与连通分量 强连通图与强连通分量 存储结构一 邻接矩阵
  • realme支持鸿蒙系统,realme Q3 Pro:接受不了这四个缺点,请谨慎入手!

    64MP主摄 可能不是你想的那样 realme Q3 Pro的64MP像素后置主摄传感器也是发布会中没有提到的 其实这个主摄并非GT系列的IMX682传感器 而是豪威科技的OV64B传感器 IMX682的底更大 向来有底大一级压死人的说法
  • MySQL错误处理--1146错误

    在MySQL的主从复制过程中 出现了1146错误 提示的错误原因是 在默认的数据中找不到指定的表 show slave status G 现实的同步状态 Slave IO Running YESSlave SQL Running NoLas
  • WebGL(二)——什么是WebGL

    WebGL 二 什么是WebGL 什么是WebGL WebGL 全写Web Graphics Library 字面意义理解就是web图像库 是一种3D绘图协议 也可以说是一个负责图形处理的JavaScript API 可在任何兼容的Web浏
  • 蒙特卡洛方法(入门详解)

    一 定义 蒙特卡洛又称统计试验法 是基于概率论的算法 其实质就是将问题转化为一个概率问题 并用计算机模拟产生一堆随机数 再对随机数进行统计工作 蒙特卡洛模拟方法 建立概率模型 计算机模拟 数理统计 二 原理 大数定理证明 在大样本的情况下
  • 顶刊IJCV 2022!基于深度学习的图像去模糊综述来了!

    点击下方卡片 关注 CVer 公众号 AI CV重磅干货 第一时间送达 点击进入 gt CV 微信技术交流群 转载 机器之心 本文提出了一个图像去模糊方向的综述 来自澳大利亚国立大学 中山大学 美国加州大学 Merced 分校 日本乐天研究
  • 前端不使用 i18n,如何优雅的实现多语言?

    前言 关于ERP管理系统的多语言 或者其他应用的多语言一直是我们比较麻烦的问题 大部分是使用 i18n 在代码里进行配置 如果想要修改语言就要自己去改代码 今天我们分享一下如何不使用 i18n 去实现多语言 用到以下的技术栈 ERP管理系统
  • [Python图像处理] 四十一.Python图像平滑万字详解(均值滤波、方框滤波、高斯滤波、中值滤波、双边滤波)

    该系列文章是讲解Python OpenCV图像处理知识 前期主要讲解图像入门 OpenCV基础用法 中期讲解图像处理的各种算法 包括图像锐化算子 图像增强技术 图像分割等 后期结合深度学习研究图像识别 图像分类应用 希望文章对您有所帮助 如
  • 安卓手机玩游戏卡顿怎么解决_告别卡顿 打造Android手机的“游戏模式”

    如今的手游 除了大型3D单机游戏以外 对硬件的需求其实谈不上太过苛刻 比如 王者荣耀 哪怕是骁龙430级别的处理器也能流畅运行 而之所以游戏过程中偶尔出现卡顿 可能还是一些细节设置没有优化到位 有的手机已经自带游戏模式了 问题是没有这个功能
  • 烂大街的 Spring 循环依赖问题,你真以为自己会了吗?

    什么是循环依赖 所谓的循环依赖是指 A 依赖 B B 又依赖 A 它们之间形成了循环依赖 或者是 A 依赖 B B 依赖 C C 又依赖 A 形成了循环依赖 更或者是自己依赖自己 它们之间的依赖关系如下 这里以两个类直接相互依赖为例 他们的
  • google GMS测试环境搭建详细教程

    1 解压jdk tar xvf jdk 8u172 linux x64 tar gz 2 配置java环境 sudo chmod 777 etc profile sudo vim etc profile 3 测试java java vers
  • 树莓派基础之嵌入式开发概述

    树莓派初见 一 嵌入式概述 二 树莓派开发笔记 三 Linux库引入之分文件编程 四 Linux库引入之动态库和静态库 五 静态库的生成和使用 六 动态库的生成和使用 一 嵌入式概述 1 什么是嵌入式 a 嵌入式即嵌入式系统 IEEE 美国
  • 边缘计算初探:什么是边缘计算,它能做什么?

    边缘计算是指在靠近智能设备或数据源头的一端 提供网络 存储 计算 应用等能力 达到更快的网络服务响应 更安全的本地数据传输 边缘计算可以满足系统在实时业务 智能应用 安全隐私保护等方面的要求 为用户提供本地的智能服务 边缘计算一般由云端管理
  • 比较C#和Java

    本文对比了C 与Java这两种编程语言 这两种语言都具有自动垃圾回收以及运行时编译执行的特点 并且两者的语法都有主要继承自C语言 C 因此二者有很多相似之处 但由于C 是作为C 和Java的混合体而在Java之后所创造的 因此C 相较Jav
  • Java位运算符详解

    按位与运算符 参加运算的两个对象 按二进制位进行 或 运算 运算规则 0 0 0 0 1 1 1 0 1 1 1 1 即 参加运算的两个对象只要有一个为1 其值为1 例如 3 5 即 0000 0011 0000 0101 0000 011
  • SQL_Case When 嵌套

    select psperdno 期数 count case when psperdno 1 then case when date datadate psduedt gt 0 then a custid end else case when
  • 第一次竞赛-E.找饭友

    中国幅员辽阔 来自全国各地的朋友的饮食口味也不尽相同 饮食喜好相同的人会组在一起吃饭 我们称其互为 饭友 而你意外得到了一份食堂的流水账单记录 想从中发现今天来食堂吃饭的人当中每个人究竟有多少名饭友 首先你对账单的记录进行了一番整理 把N个
  • Java 5-12、数据模型与接口规范

    5 12 数据模型与接口规范 一 常用数据模型 VO controller View Object Value Object 视图对象 值对象 最有争议的模型 规范写法只存在于controller层 因为swagger注解只作用于VO中的属
  • 7.1-系统调用和 UNIX Shell

    复习 状态机模型 程序 多线程程序 操作系统 操作系统是状态机的管理者 本次课回答的问题 Q 我们是操作系统的用户 但操作系统提供的 API 并不是 我们 作为人类用户能直接使用的 那 我们 到底怎么用操作系统 本次课主要内容 UNIX S