update analysis of xv6
This commit is contained in:
parent
0c54dc0424
commit
fa75ac970c
|
@ -1,3 +1,77 @@
|
|||
在user/user.h定义了可用的系统调用。
|
||||
#### 从内核态到用户态
|
||||
|
||||
在xv6启动的过程中,0号核在main函数里会执行userinit函数,标记initcode处的数据会复制到第一个用户进程的内存空间。标记initcode的数字是一段代码,它对应的内容在user/initcode.S,是要把文件init的内容放到内存里以用户态去执行。文件init编译自user/init.c。
|
||||
|
||||
user/init.c把文件sh放到内存里执行。文件sh编译自user/sh.c,把用户输入的命令调入内存中执行,它就是xv6的shell。shell就是不断地使用getcmd函数读取命令行的输入,然后使用runcmd函数来执行命令行的输入。
|
||||
|
||||
#### 从用户态到内核态
|
||||
|
||||
系统调用怎么从用户态到的内核态呢?文件user/usys.pl生成user/usys.S,usys.S就是用来完成从用户态到内核态的代码。从代码可见,它是通过ecall产生一个异常来进入内核态。只要把usys.S生成的二进制文件链接进用户程序里,就可以使用系统调用了。
|
||||
|
||||
#### 进程和内存
|
||||
|
||||
相关系统调用的实现请看kernel/sysproc.c。
|
||||
|
||||
##### fork
|
||||
|
||||
文件位置:kernel/proc.c。作用:创建一个进程。
|
||||
|
||||
fork函数一次调用两次返回,这很怪异,因为一般的调用都是只返回一次的。fork从父进程返回很正常,但为什么会从子进程返回呢?这是因为子进程继承了父进程的所有资源,这一句`*(np->tf) = *(p->tf)`相当于子进程复制了父进程运行的“快照”,子进程里也相当于进行了一个fork函数且从下一句开始执行。
|
||||
|
||||
1. p为当前进程,np为子进程。
|
||||
2. uvmcopy把父进程的内存复制给子进程。
|
||||
3. `np->tf->a0 = 0`保证了子进程返回0,因为寄存器a0保存了函数的返回值。
|
||||
4. `return pid`对于子进程来说,在汇编层面应该实际执行的返回寄存器a0的值。
|
||||
|
||||
##### exit
|
||||
|
||||
文件位置:kernel/proc.c。作用:让调用它的进程停止运行。
|
||||
|
||||
##### wait
|
||||
|
||||
文件位置:kernel/proc.c。作用:等待当前进程的某个子进程退出。
|
||||
|
||||
##### exec
|
||||
|
||||
文件位置:kernel/exec.c。作用:把硬盘上的程序加载到内存里并执行之。
|
||||
|
||||
##### sbrk
|
||||
|
||||
文件位置:kernel/sysproc.c。作用:为进程分配内存。
|
||||
|
||||
#### 文件系统
|
||||
|
||||
相关系统调用的实现请看kernel/sysfile.c。
|
||||
|
||||
##### read
|
||||
|
||||
文件位置kernel/file.c。作用:从文件描述符所指向的文件读取n个字节。
|
||||
|
||||
##### write
|
||||
|
||||
文件位置kernel/file.c。作用:从文件描述符所指向的文件写入n个字节。
|
||||
|
||||
##### close
|
||||
|
||||
##### open
|
||||
|
||||
##### pipe
|
||||
|
||||
##### dup
|
||||
|
||||
##### chdir
|
||||
|
||||
##### mkdir
|
||||
|
||||
##### mknod
|
||||
|
||||
##### fstat
|
||||
|
||||
##### link
|
||||
|
||||
##### unlink
|
||||
|
||||
##### I/O重定向
|
||||
|
||||
|
||||
|
||||
在kernel/syscall.h定义系统调用号。
|
|
@ -0,0 +1,23 @@
|
|||
操作系统有三个需求:多路复用、隔离和交互。本章概述了操作系统如何实现如上三个需求,本章还概述了xv6的进程。xv6-riscv在低层的实现很多是特定于riscv的,比如进程。
|
||||
|
||||
#### 抽象物理资源
|
||||
|
||||
把物理资源抽象成系统调用接口,可以简化应用程序的编写,并使应用程序相互隔离,实践证明是个比较好的硬件抽象方法。
|
||||
|
||||
#### 特权模式和系统调用
|
||||
|
||||
应用程序处于用户模式,以被强制隔离。内核处于管理模式,以执行特权指令。CPU从机器模式开始执行,主要是配置计算机。
|
||||
|
||||
应用程序通过ecall指令调用内核的功能。应用程序不应知道调用内核功能的内存地址,因为恶意程序可借此威胁系统安全。
|
||||
|
||||
#### 内核的组织
|
||||
|
||||
操作系统的哪一部分放在管理模式下是设计的一个核心问题,宏内核的设计是把整个操作系统都放在内核里。这样的内核组织方式使得操作系统拥有完整的硬件权限,这有利于操作系统的不同部分间相互协同。但这也使操作系统的不同部分之间的接口变得复杂,从而出容易出现错误。为了减少内核产生错误的风险,仅让少量的操作系统代码运行在管理模式,而让大部分的操作系统都运行在用户模式,这样的内核组织方式叫微内核。
|
||||
|
||||
在微内核里,操作系统的大量功能都以服务的形式运行于用户态,其它程序以进程间通信的方式使用操作系统提供的服务。这样内核接口就仅包含少量的低级别的功能,诸如启动程序、发送消息、访问硬件等。
|
||||
|
||||
#### xv6的组织
|
||||
|
||||
#### 进程概述
|
||||
|
||||
#### 第一个进程
|
Loading…
Reference in New Issue