$Linux$ 里面系统调用使用的向量号是 $0x80$,$xv6$ 里面使用的 $64$(不同 $xv6$ 版本可能不同)。...上述说的用户接口就会执行 INT 64 触发一个 $64$ 号中断,这里 $xv6$ 做了简化,按照以前版本的 $Linux$,用户接口是调用一个宏定义 $_SYSCALL$,这个宏再来执行 INT...可是系统调用是有很多的,虽然 $xv6$ 中实现的系统调用没多少,没多少也还是有那么一些的,怎么区别它们呢?...这就涉及了系统调用号概念,每一个系统调用都唯一分配了一个整数来标识,比如说 $xv6$ 里面 $fork$ 系统调用的调用号就为 1。...上述差不多将系统调用的一些理论知识说完了,下面用 $xv6$ 的实例来看看系统调用具体如何实现的。
binutils-riscv64-linux-gnu binutils-riscv64-linux-gnu-dbg binutils-riscv64-unknown-elf 使用 apt install...sudo apt install binutils-riscv64-linux-gnu sudo apt install binutils-riscv64-linux-gnu-dbg sudo apt...sudo apt install gcc-10-riscv64-linux-gnu 安装之后得到 riscv64-linux-gnu-gcc-10 文件,进入 /usr/bin 目录,建立软连接。...sudo ln -s riscv64-linux-gnu-gcc-10 riscv64-unknown-elf-gcc ---- 安装 QEMU 除了 GCC/Binutils 需要安装,xv6 需要...参考 [xv6] xv6 的运行环境搭建 xv6中译教材 Linux云计算底层技术之一文读懂 Qemu 模拟器 MIT 6.S081 2020 操作系统 [中英文字幕]
里面被当作临时栈 $0x7e00-0x9fbff$ 之间的空闲区域 xv6 拿来放置 APs 的启动程序,以及内核 elf 文件,AP 意思是 Application Processor,对应还有个...但其实这些 xv6 里都没使用,唯一使用了的系统段就是 TSS 段,这在进程一块会详细讲述。...这里准备环境就是最后正式的环境,其实在这之前有建立临时的环境,比如 xv6 在 MBR、Bootloader 阶段建立了临时的 GDT 和页表供启动的时候使用。...这里点到为止不细说,也不好叙述,等后面直接看实例 xv6 做了哪些事,怎么做的。...关于多处理器的配置数据结构就先了解到这儿, 具体怎么使用后面的 xv6 实例讲解。
xv6 本文的剩余部分来解决 xv6 中涉及内联汇编的部分,顺带讲述一些相关指令的用法 in, out in 指令用法: in port, %al in port, %ax out %al, port...来看 xv6 字符串函数 memset,就是用 stos 指令实现的: void* memset(void *dst, int c, uint n) //将从地址dst开始的n个字节设置为c {...//否则就是用stosb的封装函数,每次只传送1字节,重复n次 stosb(dst, c, n); return dst; } 回到内联汇编上来,再来看 xv6...然后解决了 xv6 里面一些用内联汇编实现的功能函数,也就是 x86.h 那个文件里面的函数,还有一些函数就没一一拿出来举例了,都类似或者更简单,把本文举出来的弄清楚,其他的应该没什么问题。
$8259A$ 还有其他的寄存器比如初始化命令寄存器,操作命令寄存器,这里我们后面讲述 $xv6$ 并不会使用 $PIC$,所以这里也就不说明了,最后来看看通过 $PIC$ 的中断流程: PIC 中断流程...如果优先级别设置为 15,则不会接受任何中断,如果优先级别设置为 0,表示接受所有中断,这也是 $Linux$ 设置的默认值。...到 0 ,产生时钟中断时,$Current$ $Count$ 就会自动地从 $Intial$ $Count$ 重新加载,接着新一次的倒数,所以其实 $Current$ $Count$ 似乎没什么用,xv6...$LAPIC$ 自己也可以作为中断源,可在 $LVT$ 中配置相关中断,主要留意时钟中断的设置,$xv6$ 就是使用 $LAPIC$ 自带的时钟来周期性产生时钟中断。...以前 $Linux$ 中系统调用就是使用 $int$ 0x80 来实现的。
memory barrier有几种类型:acquire barrier : 不允许将barrier之后的内存读取指令移到barrier之前(linux kernel中的wmb())。...release barrier : 不允许将barrier之前的内存读取指令移到barrier之后 (linux kernel中的rmb())。...full barrier : 以上两种barrier的合集(linux kernel中的mb())。void release(struct spinlock *lk){ if(!...FAQ基本函数说完,来聊聊一些遗留问题:Ⅰ xv6 的竞争条件有哪些?xv6 是个支持多处理器的系统,各个 CPU 之间可以并行执行,所以可能会出现同时访问公共资源的情况。...下面代码由 xv6 文档给出:for(;;) { if(!
启动代码部分 本文来说码,实打实地来看看计算机到底是如何启动的,先来看看 $xv6$ 启动的整体流程图,好有个大概认识: 不要被这么一大坨吓到,$xv6$ 的启动过程算简单的,在启动方面做了很多简化,应该说整个操作系统都做了简化...虽说 $xv6$ 的启动过程相对简单,但也是有些复杂的,弯弯绕绕有些多,看代码和看下面文章时可以对照着这张图,免得走掉。...这个 $xv6.img$ 可以看作是磁盘映像。...KERNEL 前面所做的事情都可以看作是引导部分,目的就是将 $xv6$ 的内核加载到内存,然后将权力交给内核。...最后再来看一下 $xv6$ 的启动流程图: 上面的启动流程图是很完整的一个图,将各种初始化也画出来了,但是本文只讲述了一小部分,其他部分留待相应章节讲述。
反观 $Linux\ 0.11$ 这一块的处理,它是为管道文件分配了 $inode$ 的,各个层次分明,所以文件读写函数只需要判断 $inode$ 的类型字段去调用不同的读写函数就行了,使得整个代码看起来特别的漂亮...->i_mode)) //普通文件 return file_write(inode,file,buf,count); /***********略***********/ } 这个函数就是 $Linux...实际上在 $Linux$ 的 $bash$ 中,$List$ 不止 ;还有 && || 等符号,详见 man bash struct cmd* listcmd(struct cmd *left, struct...平时在 $Linux$ 下使用命令没有指定命令路径是因为环境变量 $PATH$ 已经帮我们做了这个工作。...总而言之 $xv6$ 机制少,使用方面也要符合习惯于规范。关于文件系统和进程资源的回收详见前文,这里不赘述。
我觉得那里面对内存管理层次抽象分的很清楚,每个操作系统都有相通性,这里拿出来说说: 物理内存管理,主要就是物理页的分配与回收 虚拟内存管理,主要就是虚拟页的分配与回收 物理内存与虚拟内存建立映射,那就是页表了 xv6...分配某页/块就是将相应的位置 1,回收就是将相应的位置 0 空闲链表法 xv6 对于物理内存的组织管理使用的是空闲链表法。...页表内核部分 映射关系 要了解其他几个参数还需要先来了解 xv6 的虚拟地址空间和实际的物理地址空间的映射关系,这也有相应的结构体表示: #define EXTMEM 0x100000...再者也可以看出 xv6 并没有使用全部的 4G 地址空间,有很大一部分都没有使用,内核的为映射部分和物理地址空间的未映射部分两者大小是不一样的,可能图画得有些迷惑,拿出来说一下。...的设计思路,当然只是看和内存相关比较紧密的部分: 最开始内核加载到物理地址 0x10 0000 处,xv6 内核很小,整个内核只有 200 多 K。
日志就是设计来解决因为系统崩溃导致的错误问题,本文就 $xv6$ 来讲解怎么实现一个简单的日志系统。...上面的理论大都来自 $xv6$ 文档,我们能了解到,最为重要的是实现写操作的原子性,那么怎样实现呢?...$xv6$ 在磁盘上分配了一片日志区,假如现在内存中有一个缓存块准备同步到磁盘区域 A,$xv6$ 并不立即将该缓存块的数据写到磁盘区域 A,而是先写到磁盘的日志区(提交)。...$xv6$ 文件系统的总体布局如下: 引导块位于磁盘第零个扇区(LBA),里面存放的就是引导程序。其后就是超级块,接着就是日志区,分为日志头(位于第一个日志块)和日志数据块。...$n$ 来记录当前日志使用的空间大小,日志区的总大小记录在超级块中(大小的单位是块),同时 $xv6$ 也规定每次日志使用的块数也不能超过 $LOGSIZE$。
,这个频率是系统的总线频率再分频,分频系数设置在 $TDCR$ 寄存器,$xv6$ 设置的是 2 分频,根据手册来看这里 $xv6$ 的原本注释应是错了。...$xv6$ 简化了处理,只使用 APIC 模式,所有的 LAPIC 都将两种中断给屏蔽掉了。...关于 Arb,引用 $Interrupt in Linux$ 中的解释: Arb,Arbitration Register,仲裁寄存器。...,$xv6$ 在描述符里面填写的地址就是中断入口程序的地址。...另外 $xv6$ 在这部分也压入了向量号,之后就会跳到入口程序的共同部分保存剩下的上下文。
当然这只是基本原理,还有很多细节要处理,我们在 $xv6$ 创建文件系统的程序中再详细了解。...主机上有个文件叫做 $fs.img$,虚拟机将这个文件当作 $xv6$ 的磁盘,但是对于 $xv6$ 本身来说,它不知道这个 $fs.img$ 就是主机磁盘上的一个普通文件,对于 $xv6$ 来说,$fs.img...相关功能函数 转化为小端模式 我学习的 $xv6$ 实现基于 $intel$ 的 $x86$ 架构,使用小端模式,$xv6$ 一般运行在虚拟机上,虚拟机又可能运行在各个平台,使用的大小端可能就不一样,这里全转化为小端模式...为什么 $qemu$ 里的 $xv6$ 能使用,原因就在此处了。...$xv6$ 里面的块都是有相应的位图标识,所以这里调用 $balloc$ 将第一个空闲块之前的位图全部置 1。因为 $xv6$ 的系统布局就是数据区前面全是不可分配的元数据,需要全部置 1。
简单来说就是this指向的是绑定事件的元素,e.target返回的是所触发事件的元素
该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列。该系列引用了《Android开发艺术探索...
$xv6$ 这是里每个 $CPU$ 一个,所有进程共享。...在 $xv6$ 或者 $Linux$ 里除了第一个 $init$ 进程需要内核来创建之外,其他的所有进程都是使用 $fork$ 来创建,第一个进程的创建放在本文最后一个部分,这一节先来看普通进程的创建方式...$xv6$ 的 $fork$ 实现就很朴实无华,将父进程所有的东西几乎都复制了一份。...$xv6$ 的代码就是有这问题,一些用户接口,内核函数,还有个别文件里面的函数取名一样,但是我们实际看码的时候要区别对待。...此时不该允许中断,因为取锁的时候关中断了,$xv6$ 为了保险,取锁的时候就将中断关闭,避免死锁,这部分详见 锁。
调度是操作系统里面一个很重要的概念,进程中有调度,页面置换有调度,磁盘访问也有调度,本文讲述的是进程之间的调度,以及多处理器之间的调度策略。废话不多时直接来看,...
但实际上述讲述的这些规则 xv6 一个都没用上,想想 xv6 的启动,简化了很多很多,基本不沾边。 FAQ 每个分区最大容量是多少?
MIT_6.S081_xv6.Information 集合 于2023年2月6日2023年2月6日由Sukuna发布 1:Operating System Overview 1 xv6系统的启动过程:...这样的接口设计非常成功,使得包括 BSD,Linux,Mac OS X,Solaris (甚至 Microsoft Windows 在某种程度上)都有类似 Unix 的接口。...内核地址空间 图片 xv6对每个进程都维护了一份页表(每个进程都有一个页表),来表示不同进程的虚拟地址空间.当然xv6也会给内核态地址空间维护一个页表,也就是说xv6的地址空间=若干个用户态进程的地址空间...所有的xv6关于地址的处理全部放在vm.c这个文件中....管道 xv6的管道使用sleep和wakeup的操作来进行复杂的同步通讯.我们在之前已经了解过Linux的管道系统. struct pipe { struct spinlock lock; char
概念始终只会是一个抽象的概念,进程系列文章通过 $xv6$ 的实例来将进程这个概念具象化。...记录管理着文件的信息,当可执行文件被加载到内存当作进程执行后,也有类似的数据结构来记录管理进程的执行情况,这个数据结构就是 $PCB(Process\ Control\ Block)$,进程控制块,$Linux...简要回顾 $xv6$ 的内存管理方式,计算机启动初始化的时候,$xv6$ 将所有的空闲内存分成一页一页的大小然后使用链表头插法的方式将它们给串起来。...所以 $xv6$ 的空闲物理内存就可以看作是一个大链表。...准确点来说应该是下图这样: 图中有鲜明显色的区域都是实际映射到了物理内存的区域,其中蓝色部分才是 $malloc\ free$ 作用的区域,在 $Linux$ 中程序在内存中的映像有个属性叫做 $break
常用命令实现 本节来看看在 $xv6$ 里面一些常见的命令是如何实现的,它们都是用户程序,封装系统调用而成,大多数都很简单一眼过去就能懂那种,来看: echo $echo$ 命令将紧跟其后的参数当作字符串打印出来...来看 $xv6$ 里的实现 首先是两个匹配函数 int matchhere(char* re, char* text); int matchstar(int c, char* re, char* text...printf(2, "rm: %s failed to delete\n", argv[i]); break; } } exit(); //执行完后退出 } $xv6...$ 直接调用 $unlink$ 来"删除"一个文件,但实际上在文件系统调用一文中,我们说过,只有一个文件的链接数,引用数都为 0 的时候才会真正地将一个文件删除,当时还在 $Linux$ 下做了一个实验...上述就是 $xv6$ 中一些命令的实现,很简单,大多数就是调用现成的系统调用就能完成工作,配上详细的注释应该是一眼就能懂什么意思。
领取专属 10元无门槛券
手把手带您无忧上云