首页 > 其他分享 >MIT6.S081 - Lecture1: Introduction and Examples

MIT6.S081 - Lecture1: Introduction and Examples

时间:2024-04-15 21:12:57浏览次数:14  
标签:文件 Lecture1 MIT6 描述符 Introduction 管道 调用 内核 进程

课程简介

课程目标

  1. 理解操作系统的设计和实现
  2. 通过 XV6 操作系统动手实验,可以扩展或改进操作系统

操作系统的目标

  1. Abstraction:对硬件进行抽象
  2. Multiplex:在多个应用程序之间共用硬件资源
  3. Isolation:隔离性,程序出现故障时,不同程序之间不能相互干扰
  4. Sharing:实现共享,如数据交互或协同完成任务
  5. Security:想分享的时候可以分享,不想分享的时候可以不分享,可以称为 Access Control System
  6. Performance:操作系统至少需要不阻止应用程序获得高性能,甚至需要帮助应用程序获取高性能
  7. Range of oses:对于大部分操作系统,需要支持大量不同类型的应用程序

操作系统结构

系统调用函数

read/write 系统调用

  • readwrite 函数在执行时,不会关心读写的数据格式,操作系统中(内核)copy 程序会按照 8bit 的字节流处理数据
  • readwrite 函数中第一个参数代表文件位置,shell 会确保默认情况下,当一个程序启动时,文件描述符 0 连接到 console 的输入,文件描述符 1 连接到了 console 的输出。

open 系统调用

  • 字节流就是一段连续的数据按照字节的长度读取
  • open("output.txt", O_WRONLY | O_CREATE); 第二个参数用来告诉 open 系统调用在内核中的实现:我们将要创建写入一个文件
  • 文件描述符本质上对应了内核中的一个表单数据。内核维护了每个运行进程的状态,内核会为每一个运行进程保存一个表单,表单的 key 是文件描述符。这个表单让内核知道,每个文件描述符对应的实际内容是什么。这里比较关键的点是,每个进程都有自己独立的文件描述符空间,所以如果运行了两个不同的程序,对应两个不同的进程,如果它们都打开一个文件,它们或许可以得到相同数字的文件描述符,但是因为内核为每个进程都维护了一个独立的文件描述符空间,这里相同数字的文件描述符可能会对应到不同的文件

fork 系统调用

  • fork 可以创建新的进程,该进程(子进程)与原进程(父进程)的指令、数据、堆栈、文件描述符表单完全相同

  • fork 有两个返回值,但是有独立的地址空间(都认为内存从 0 开始增长)

    • 在父进程中,返回子进程的 PID
    • 在子进程中,返回 0
    • 如果创建失败,返回-1

wait 系统调用

  • wait 表示等待一个子进程退出

    • 如果调用者没有子进程,则 wait 立即返回-1
    • 如果父进程不关注子进程的退出时状态,可以传一个 0 地址(或者 NULL 指针)给 wait
    pid = wait((int *)0);   // 只要一个子进程退出,wait 就结束,返回该退出的子进程的 pid 号
    
    • 如果父进程关注子进程的退出时状态,可以使用如下方式,status将保存子进程结束时的状态(子进程退出时exit里的参数会被保存到status中)
    int status;
    wait(&status);
    

exit 系统调用

  • exit 系统调用退出程序,并释放资源。exit 需要一个整数状态参数,0 表示成功,1 表示失败

exec 系统调用

  • exec 系统调用使用新内存映像来替换内存的进程
    • exec 会保留当前的文件描述符
    • 通常 exec 不会返回,只有出错时才会返回
_char _*argv[3]; 
argv[0] = "echo"; 
argv[1] = "hello"; 
argv[2] = 0;      // 标记了数组的结尾,也可以用NULL指针
exec("/bin/echo", argv);   // 相当于echo hello
printf("exec error\n");    // exec出错时返回,否则不会运行到这里了
  • 一般来说 fork 下的子进程中调用 exec 函数来替换子进程,但这样会造成资源浪费,因此内核通过使用虚拟内存技术来进行优化

pipe 系统调用

管道的概念

  1. 以文件描述符对的形式提供给进程,一个表示读端,一个表示写端
  2. 本质是一个伪文件,实质为内核缓冲区
  3. 管道实际为内核使用环形队列机制,借助内核缓冲区(4K)实现

管道的局限性

  1. 必须作用在有血缘关系的进程之间
  2. 数据不能进程自己写,自己读(需要两个进程,一个读,一个写)
  3. 采用半双工通信,数据只能单方向流动
  4. 数据不能反复读取

管道函数

int pipe(int fd[2]) :创建并打开管道

  • 参数:fd[0] 读端fd[1] 写端
  • 返回值:0 成功;-1 失败

管道程序举例

int p[2]; 
char *argv[2]; 
argv[0] = "wc"; 
argv[1] = 0; 
pipe(p);            // 创建并打开管道
if (fork() == 0)   // 子进程
{ 
    close(0);     // 释放文件描述符0(标准输入)
    dup(p[0]);    // 使得文件描述符0引用了管道读端p[0]
    close(p[0]);  // 关闭管道读端
    close(p[1]);  // 关闭管道写端 
    exec("/bin/wc", argv);  // wc相当于从管道读数据(这里其实不太理解,管道不是关上了吗)
} 
else             // 父进程
{ 
    close(p[0]);   // 读写只能有一个,父进程将读端关闭
    write(p[1], "hello world\n", 12);  // 向管道写入数据
    close(p[1]);  // 写完将管道关闭
}

管道的读写行为

  1. 读管道:
  • 管道中有数据,read 返回实际读到的字节数

  • 管道中无数据:

    • 管道写端全部关闭read 返回 0
    • 管道写端没有全部关闭read 阻塞等待
  1. 写管道:
  • 管道读端全部关闭,进程异常终止(SIGPIPE 信号导致的)

  • 管道读端没有全部关闭

    • 管道已满,write 阻塞
    • 管道未满,write 将数据写入,并返回实际写入的字节数

File system

文件系统

  1. xv6 文件系统包含了数据文件(拥有字节数组)和目录(拥有对数据文件和其他目录的命名引用)
  2. / 开头的如 /a/b 表示根目录 /a 目录中名为 b 的文件或目录(绝对路径),不以 / 开头的是相对于当前目录的路径(相对路径)

chdir 系统调用

通过 chdir 系统调用可以改变进程的当前目录,如下两个 open 打开了同一个文件

chdir("/a");
chdir("b");
open("c", O_RDONLY);
open("/a/b/c", O_RDONLY);

创建文件和目录

mkdir 可以创建一个新的目录open 使用 O_CREATE 可以创建新的数据文件mknod 可以创建一个新的设备文件

mkdir("/dir");
fd = open("/dir/file", O_CREATE | O_WRONLY);
close(fd);

mknod("/console", 1, 1);  // 主设备号,次设备号,唯一标识一个内核设备

当一个进程打开设备文件后,内核会将系统的读写调用转移到内核设备实现上,而不是将它们传递给文件系统

文件链接

  • inode 是操作系统用来储存除了文件名和实际数据的数据结构,它是用来连接实际数据和文件名的;每个 inode 保存着文件的元数据,包括文件的类型(文件 or 目录 or 设备)、长度、内容在磁盘的位置以及文件的链接数量
  • fstat 系统调用从文件描述符引用的 inode 中检索信息
// int fstat(int fd, struct stat*),stat为接收inode信息的结构体,如fstat(fd, &st)
#define T_DIR     1   // Directory
#define T_FILE    2   // File
#define T_DEVICE  3   // Device

struct stat {
  int dev;     // File system's disk device
  uint ino;    // Inode number
  short type;  // Type of file
  short nlink; // Number of links to file
  uint64 size; // Size of file in bytes
};
  • link 系统调用创建了一个引用同一个 inode 的文件
open("a", O_CREATE | O_WRONLY);
link("a", "b");  // 创建文件b,且a和b指向同一个inode
  • unlink 系统调用会从文件系统中删除一个文件名,只有当文件链接数为且没有文件描述符引用它时,文件 inode 和存放其内容的磁盘空间才会被释放
unlink("a");   // 删除a,此时只有b引用inode

// 创建临时文件的一种惯用方式,它创建一个无名称的inode,在进程关闭fd或退出时删除文件
fd = open("/tmp/x", O_CREATE | O_WRONLY);
unlink("/tmp/x");

Linux 命令

xargs 命令

  • 作用:将标准输入转为命令行参数;xargs 的作用在于,大多数命令(比如 rmmkdirls)与管道一起使用时,都需要 xargs 将标准输入转为命令行参数。
$ echo "hello world" | xargs echo
hello world

上面的代码将管道左侧的标准输入,转为命令行参数 hello world,传给第二个 echo 命令

$ echo "one two three" | xargs mkdir

上面的代码等同于 mkdir one two three。如果不加 xargs 就会报错,提示 mkdir 缺少操作参数

  • 命令格式如下:
$ xargs [-options] [command]

真正执行的命令,紧跟在 xargs 后面,接受 xargs 传来的参数

标签:文件,Lecture1,MIT6,描述符,Introduction,管道,调用,内核,进程
From: https://www.cnblogs.com/jll133688/p/18136905

相关文章

  • SystemVerilog -- 2.0 Data Types ~ Introduction
    SystemVerilogDataTypesSystemVerilog是Verilog的扩展,也用作HDL。Verilog具有和数据类型来描述硬件行为。由于硬件验证可能变的更加复杂和苛刻,Verilog中的数据类型不足以开发高效的测试平台和测试用例。因此,SystemVerilog通过添加更多类似C的数据类型和扩展Verilog,以......
  • SystemVerilog -- 1.1 Introduction ~ tb
    我们需要一个称为testbench的环境对设计运行任何类型的仿真。Whatisthepurposeofatestbench?Testbench允许我们通过仿真来验证设计的功能。它是一个容器,其中放置设计并使用不同的输入激励进行驱动。生成不同类型的输入刺激使用生成的激励驱动设计输入允许设计处理输......
  • Verification -- Introduction
    AISC设计流程由几个步骤组成,包括designspecification、designentry、designsynthesis、designverification、physicaldesignanddesignsign-off.Designverification(DV)通常是指使用仿真工具对设计进行功能验证的pre-siliconeffort。Whatisdigitaldesignverific......
  • Operating System Concepts 9th: Chapter 1 Introduction
    Anoperatingsystemisaprogramthatmanagesacomputer’shardware.Italsoprovidesabasisforapplicationprogramsandactsasanintermediarybetweenthecomputeruserandthecomputerhardware.操作系统的定义:一个管理计算机硬件,并作为用户与硬件之间的中......
  • Lecture 10 Geometry 1 (Introduction)
    Lecture10Geometry1(Introduction)Examplesofgeometry几何的例子不同形状的几何光滑的曲面复杂的模型、位置摆放布料水滴城市(复杂在东西多)怎么存储怎么渲染这么大级别的东西离得远的情况下如何简化几何模型如何利用光线之间的连续性毛发微观几何树枝......
  • [Container] Introduction to Kubernetes
    DefineKubernetesAlsoknowasK8S,isanopen-sourcesystemforautomatingdeployment,scaling,andmanagementofcontainerizedapplications.Anopensourcecontainerizationorchestrationpaltform.Easolyportableacrosscloudsandon-premisesIncludes......
  • matlab教程_台大lecture1基本操作和矩阵输入
    matlab教程视频matlabascalculatorcommendline直接用命令行计算部分ans是结果运算法则和平时一样((),^乘除加减)onlinehelpeg:helpsin&直接搜索嵌套式公式sin(cos(pi))==cos(pi)sin(ans)其中,ans是第一个的结果变量可以用who查看变量,whos详细信息一些保留......
  • MIT6.830-Lab5
    simpleDB项目地址概览类概述BTreePage:B+树节点(叶子节点和内部节点)的公共父类,存储了父节点页号protectedintparent,并且使用protectedfinalintkeyField存储在表记录的哪个字段建立索引。BTreeLeafPage:B+树的叶子节点,用来存放具体的表记录。BTreeInternalPage:B+树的内部节......
  • MIT6.830-Lab3
    simpleDB项目地址概览IntHistogram作用估计条件过滤某表的某个Int字段时,结果集记录数和该表记录总数的比例;StringHistogram类似IntHistogramTableStats作用存放某表各个字段对应的直方图对象(IntHistogram或StringHistogram类型);使用静态对象ConcurrentMap<String,Tab......
  • MIT6.830-Lab2
    simpleDB项目地址实验部分实验1Predicate类用来存放对表记录进行条件过滤的信息(要过滤字段的序号,具体的比较规则,用来比较的字段),其内部的枚举类Op就是比较规则类,filter()方法的实现使用Field接口中的compare()即可。JoinPredicate类用来存放两表的记录进行连接的信息(两表......