$Linux$ 里面系统调用使用的向量号是 $0x80$,$xv6$ 里面使用的 $64$(不同 $xv6$ 版本可能不同)。...可是系统调用是有很多的,虽然 $xv6$ 中实现的系统调用没多少,没多少也还是有那么一些的,怎么区别它们呢?...这就涉及了系统调用号概念,每一个系统调用都唯一分配了一个整数来标识,比如说 $xv6$ 里面 $fork$ 系统调用的调用号就为 1。...没错,在内核栈中的上下文保存着,从内核栈中取出用户栈的栈顶 $esp$ 值,就可以取到系统调用的参数了,$xv6$ 就是这样实现的。...上述差不多将系统调用的一些理论知识说完了,下面用 $xv6$ 的实例来看看系统调用具体如何实现的。
XV6源码拉取 获取实验室的xv6源代码并切换到util分支 $ git clone git://g.csail.mit.edu/xv6-labs-2020 Cloning into 'xv6-labs...sudo cp qemu-system-riscv64 /usr/bin/ ---- 小结 xv6 需要依赖两个工具,一个是 GCC/Binutils,一个是 QEMU。...需要注意的是,这两个工具都需要是 RISC-V 版本的,因为 xv6 是依赖 RISC-V 指令集架构的。...---- 启动XV6 进入xv6-labs-2020安装目录 构建并运行xv6 $ make qemu riscv64-unknown-elf-gcc -c -o kernel/entry.o kernel...参考 [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 中断流程...到 0 ,产生时钟中断时,$Current$ $Count$ 就会自动地从 $Intial$ $Count$ 重新加载,接着新一次的倒数,所以其实 $Current$ $Count$ 似乎没什么用,xv6...$LAPIC$ 自己也可以作为中断源,可在 $LVT$ 中配置相关中断,主要留意时钟中断的设置,$xv6$ 就是使用 $LAPIC$ 自带的时钟来周期性产生时钟中断。...另外通常这部分也把向量号 $vector$ 也压进去,比如 $xv6$ 里就是保存完上下文之后就是这样: 执行中断处理程序 这部分其实没啥说的,就是 $CPU$ 来执行一个程序来处理中断,不同的中断处理程序肯定是不同的
本文以 $xv6$ 为例来讲解锁本身是怎么实现的,废话不多说先来看一些需要了解的概念:一些概念公共资源:顾名思义就是被多个任务共享的资源,可以是公共内存,也可以是公共文件等等临界区: 要访问使用公共资源...根据上面两种大的解决方案,xv6 实现了两种锁,自旋锁和休眠锁,下面来仔细看看:自旋锁结构定义struct spinlock { uint locked; // Is the lock held...对此可能是 xv6 的一个小 bug 吧,补上就行。第二个条件 ebp 值不能在内核之下即处于用户态,getcallerpcs 的调用者,调用者的调用者都是运行在内核,所以应不会处于用户态的低地址。...FAQ基本函数说完,来聊聊一些遗留问题:Ⅰ xv6 的竞争条件有哪些?xv6 是个支持多处理器的系统,各个 CPU 之间可以并行执行,所以可能会出现同时访问公共资源的情况。...下面代码由 xv6 文档给出:for(;;) { if(!
启动代码部分 本文来说码,实打实地来看看计算机到底是如何启动的,先来看看 $xv6$ 启动的整体流程图,好有个大概认识: 不要被这么一大坨吓到,$xv6$ 的启动过程算简单的,在启动方面做了很多简化,应该说整个操作系统都做了简化...虽说 $xv6$ 的启动过程相对简单,但也是有些复杂的,弯弯绕绕有些多,看代码和看下面文章时可以对照着这张图,免得走掉。...这个 $xv6.img$ 可以看作是磁盘映像。...KERNEL 前面所做的事情都可以看作是引导部分,目的就是将 $xv6$ 的内核加载到内存,然后将权力交给内核。...最后再来看一下 $xv6$ 的启动流程图: 上面的启动流程图是很完整的一个图,将各种初始化也画出来了,但是本文只讲述了一小部分,其他部分留待相应章节讲述。
本文主要通过 $xv6$ 来看看如何实现一个简单的 $shell$,$shell$ 实现分为两个主要步骤,一解析输入的命令字符串,二执行命令。...$However,$ $xv6$ 里面对管道文件没有分配 $inode$,我不知道这样做有什么好处,省下了 $inode$?...正因为少了 $inode$ 这一层,当时看这一块的源码的时候就感觉不太统一,层次不分明,但 $xv6$ 小也无伤大雅,整个脉络还是很容易理清。...总而言之 $xv6$ 机制少,使用方面也要符合习惯于规范。关于文件系统和进程资源的回收详见前文,这里不赘述。...总结 本文主要通过 $xv6$ 讲述了 $shell$ 这个人机交互程序如何实现,着重把重定向和管道机制拿出来说了说。实现 $shell$ 两个主要步骤,一解析命令,二执行命令。
我觉得那里面对内存管理层次抽象分的很清楚,每个操作系统都有相通性,这里拿出来说说: 物理内存管理,主要就是物理页的分配与回收 虚拟内存管理,主要就是虚拟页的分配与回收 物理内存与虚拟内存建立映射,那就是页表了 xv6...分配某页/块就是将相应的位置 1,回收就是将相应的位置 0 空闲链表法 xv6 对于物理内存的组织管理使用的是空闲链表法。...页表内核部分 映射关系 要了解其他几个参数还需要先来了解 xv6 的虚拟地址空间和实际的物理地址空间的映射关系,这也有相应的结构体表示: #define EXTMEM 0x100000...再者也可以看出 xv6 并没有使用全部的 4G 地址空间,有很大一部分都没有使用,内核的为映射部分和物理地址空间的未映射部分两者大小是不一样的,可能图画得有些迷惑,拿出来说一下。...的设计思路,当然只是看和内存相关比较紧密的部分: 最开始内核加载到物理地址 0x10 0000 处,xv6 内核很小,整个内核只有 200 多 K。
,这个频率是系统的总线频率再分频,分频系数设置在 $TDCR$ 寄存器,$xv6$ 设置的是 2 分频,根据手册来看这里 $xv6$ 的原本注释应是错了。...$xv6$ 简化了处理,只使用 APIC 模式,所有的 LAPIC 都将两种中断给屏蔽掉了。...上述就是 $xv6$ 里面对 LAPIC 的一种简单的初始化方式,其实也不简单,涉及了挺多东西。...,$xv6$ 在描述符里面填写的地址就是中断入口程序的地址。...另外 $xv6$ 在这部分也压入了向量号,之后就会跳到入口程序的共同部分保存剩下的上下文。
日志就是设计来解决因为系统崩溃导致的错误问题,本文就 $xv6$ 来讲解怎么实现一个简单的日志系统。...上面的理论大都来自 $xv6$ 文档,我们能了解到,最为重要的是实现写操作的原子性,那么怎样实现呢?...$xv6$ 在磁盘上分配了一片日志区,假如现在内存中有一个缓存块准备同步到磁盘区域 A,$xv6$ 并不立即将该缓存块的数据写到磁盘区域 A,而是先写到磁盘的日志区(提交)。...$xv6$ 文件系统的总体布局如下: 引导块位于磁盘第零个扇区(LBA),里面存放的就是引导程序。其后就是超级块,接着就是日志区,分为日志头(位于第一个日志块)和日志数据块。...$n$ 来记录当前日志使用的空间大小,日志区的总大小记录在超级块中(大小的单位是块),同时 $xv6$ 也规定每次日志使用的块数也不能超过 $LOGSIZE$。
当然这只是基本原理,还有很多细节要处理,我们在 $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 一个都没用上,想想 xv6 的启动,简化了很多很多,基本不沾边。 FAQ 每个分区最大容量是多少?
$xv6$ 这是里每个 $CPU$ 一个,所有进程共享。...$xv6$ 的 $fork$ 实现就很朴实无华,将父进程所有的东西几乎都复制了一份。...$xv6$ 的代码就是有这问题,一些用户接口,内核函数,还有个别文件里面的函数取名一样,但是我们实际看码的时候要区别对待。...$ 中锁的设计在锁一篇中已经聊过,$xv6$ 的锁设计本身不难,难得是锁的使用,这里就根据进程这一块使用锁的地方来简单聊一聊。...此时不该允许中断,因为取锁的时候关中断了,$xv6$ 为了保险,取锁的时候就将中断关闭,避免死锁,这部分详见 锁。
MIT_6.S081_xv6.Information 集合 于2023年2月6日2023年2月6日由Sukuna发布 1:Operating System Overview 1 xv6系统的启动过程:...理解 xv6 是理解这些操作系统的一个良好起点。 xv6 使用了传统的内核概念 – 一个向其他运行中程序提供服务的特殊程序。每一个运行中程序(称之为进程)都拥有包含指令、数据、栈的内存空间。...内核地址空间 图片 xv6对每个进程都维护了一份页表(每个进程都有一个页表),来表示不同进程的虚拟地址空间.当然xv6也会给内核态地址空间维护一个页表,也就是说xv6的地址空间=若干个用户态进程的地址空间...所有的xv6关于地址的处理全部放在vm.c这个文件中....7:Lock 许多操作系统内核,包括xv6都保持着多线程多进程执行,首先是因为这个xv6有许多个微处理器,这些处理器(CPU)是独立地执行一段代码,共享物理内存,这个时候就会有问题,就是在一个CPU读取数据的时候
概念始终只会是一个抽象的概念,进程系列文章通过 $xv6$ 的实例来将进程这个概念具象化。...$CPU$ 结构体 进程运行在 $CPU$ 上,$xv6$ 虽然小,但也是个支持多处理器的操作系统,$xv6$ 为每个 $CPU$ 维护了一个数据结构记录当前 $CPU$ 的信息: /******proc.h...关于页表前文 $xv6$ 的内存管理讲述了内核部分,这里补齐用户部分。...简要回顾 $xv6$ 的内存管理方式,计算机启动初始化的时候,$xv6$ 将所有的空闲内存分成一页一页的大小然后使用链表头插法的方式将它们给串起来。...所以 $xv6$ 的空闲物理内存就可以看作是一个大链表。
常用命令实现 本节来看看在 $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...上述就是 $xv6$ 中一些命令的实现,很简单,大多数就是调用现成的系统调用就能完成工作,配上详细的注释应该是一眼就能懂什么意思。
领取专属 10元无门槛券
手把手带您无忧上云