提交 014b2460 编写于 作者: chyyuu1972's avatar chyyuu1972

add some comments in ch6/7

上级 7a46d536
......@@ -9,6 +9,8 @@
文件
-------------------------------------------
.. chyyuu 可以简单介绍一下文件的起源???
在类 Unix 操作系统中,”**一切皆文件**“ (Everything is a file) 是一种重要的设计哲学。在这里,所谓的 **文件** (File) 就是指由内核管理并分配给进程让它可以与之交互的部分 I/O 资源,它大致可以分成以下几种:
- **普通文件** (Regular File) 指的是储存在磁盘/硬盘等存储介质上的文件系统中的一般意义上的文件,可以被看成一个固定的字节序列;
......@@ -29,7 +31,7 @@
fn write(&self, buf: UserBuffer) -> usize;
}
其中 ``UserBuffer`` 是我们在 ``mm`` 子模块中定义的应用地址空间中的一段缓冲区的抽象。它本质上其实只是一个 ``&[u8]`` ,但是它位于应用地址空间中,在内核中我们无法直接通过这种方式来访问,因此需要进行封装。然而,在理解抽象接口 ``File`` 的各方法时,我们仍可以将 ``UserBuffer`` 看成一个 ``&[u8]`` ,它同时给出了缓冲区的起始地址及长度
其中 ``UserBuffer`` 是我们在 ``mm`` 子模块中定义的应用地址空间中的一段缓冲区的抽象。它本质上其实只是一个 ``&[u8]`` ,但是它位于应用地址空间中,在内核中我们无法直接通过这种方式来访问,因此需要进行封装。然而,在理解抽象接口 ``File`` 的各方法时,我们仍可以将 ``UserBuffer`` 看成一个 ``&[u8]`` 切片,它是同时给出了缓冲区的起始地址及长度的一个胖指针
``read`` 指的是从文件中读取数据放到缓冲区中,最多将缓冲区填满(即读取缓冲区的长度那么多字节),并返回实际读取的字节数;而 ``write`` 指的是将缓冲区中的数据写入文件,最多将缓冲区中的数据全部写入,并返回直接写入的字节数。至于 ``read`` 和 ``write`` 的实现则与文件具体是哪种类型有关,它决定了数据如何被读取和写入。
......@@ -118,6 +120,8 @@
文件描述符与文件描述符表
--------------------------------------------
.. chyyuu 可以解释一下文件描述符的起因???
每个进程都带有一个线性的 **文件描述符表** (File Descriptor Table) 记录所有它请求内核打开并可以读写的那些文件。而 **文件描述符** (File Descriptor) 则是一个非负整数,表示文件描述符表中一个打开的文件所处的位置。通过文件描述符,进程可以在自身的文件描述符表中找到对应的文件,并进行读写。当打开一个文件的时候,如果顺利,内核会返回给应用刚刚打开的文件的文件描述符;而当应用想关闭一个文件的时候,也需要向内核提供对应的文件描述符。
当一个进程被创建的时候,内核会默认为其打开三个文件:
......
......@@ -11,6 +11,8 @@
首先来介绍什么是 **管道** (Pipe) 。我们可以将管道看成一个有一定缓冲区大小的字节队列,它分为读和写两端,需要通过不同的文件描述符来访问。读端只能用来从管道中读取,而写端只能用来将数据写入管道。由于管道是一个队列,读取的时候会从队头读取并弹出,而写入的时候则会写入到队列的队尾。同时,管道的缓冲区大小是有限的,一旦整个缓冲区都被填满就不能再继续写入,需要等到读端读取并从队列中弹出一些字符之后才能继续写入。当缓冲区为空的时候自然也不能继续从里面读取,需要等到写端写入了一些数据之后才能继续读取。
.. chyyuu 进一步介绍一下pipe的历史???
我们新增一个系统调用来为当前进程打开一个管道:
.. code-block:: rust
......@@ -176,6 +178,8 @@
从内存管理的角度,每个读端或写端中都保存着所属管道自身的强引用计数,且我们确保这些引用计数只会出现在管道端口 ``Pipe`` 结构体中。于是,一旦一个管道所有的读端和写端均被关闭,便会导致它们所属管道的引用计数变为 0 ,循环队列缓冲区所占用的资源被自动回收。虽然 ``PipeRingBuffer`` 中保存了一个指向写端的引用计数,但是它是一个弱引用,也就不会出现循环引用的情况导致内存泄露。
.. chyyuu 介绍弱引用???
管道创建
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
......
......@@ -141,7 +141,7 @@ easy-fs 被从内核中分离出来,它的实现分成两个不同的 crate
- ``addr_of_offset`` 可以得到一个 ``BlockCache`` 内部的缓冲区一个指定偏移量 ``offset`` 的字节地址;
- ``get_ref`` 是一个泛型方法,它可以获取缓冲区中的位于偏移量 ``offset`` 的一个类型为 ``T`` 的磁盘上数据结构的不可变引用。该泛型方法的 Trait Bound 限制类型 ``T`` 必须是一个编译时已知大小的类型,我们通过 ``core::mem::size_of::<T>()`` 在编译时获取类型 ``T`` 的大小并确认该数据结构被整个包含在磁盘块及其缓冲区之内。这里编译器会自动进行生命周期标注,约束返回的引用的生命周期不超过 ``BlockCache`` 自身,在使用的时候我们会保证这一点。
- ``get_mut`` 与 ``get_ref`` 的不同之处在于它会获取磁盘上数据结构的可变引用,由此可以对数据结构进行修改。由于这些数据结构目前位于内存中的缓冲区中,我们需要将 ``BlockCache`` 的 ``modified`` 标记为 true 表示该缓冲区已经被修改,之后需要将数据写回磁盘块才能真正将修改同步到磁盘。
- ``get_mut`` 与 ``get_ref`` 的不同之处在于它会获取磁盘上数据结构的可变引用,由此可以对数据结构进行修改。由于这些数据结构目前位于内存中的缓冲区中,我们需要将 ``BlockCache`` 的 ``modified`` 标记为 true 表示该缓冲区已经被修改,之后需要将数据写回磁盘块才能真正将修改同步到磁盘。
``BlockCache`` 的设计也体现了 RAII 思想, 它管理着一个缓冲区的生命周期。当 ``BlockCache`` 的生命周期结束之后缓冲区也会被从内存中回收,这个时候 ``modified`` 标记将会决定数据是否需要写回磁盘:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册