Skip to content

Commit

Permalink
Lab 4:用户程序与系统调用 (#10)
Browse files Browse the repository at this point in the history
Co-authored-by: Zhe Tang <[email protected]>
  • Loading branch information
GZTimeWalker and Tangzh33 authored Feb 24, 2024
1 parent c3a624e commit 2d72091
Show file tree
Hide file tree
Showing 43 changed files with 2,072 additions and 124 deletions.
72 changes: 0 additions & 72 deletions docs/general/coding_convention.md

This file was deleted.

96 changes: 96 additions & 0 deletions docs/general/specification.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
---
no_comments: true
---

# 代码与提交规范

!!! tip "部分内容引用修改自 [代码规范](https://lab.cs.tsinghua.edu.cn/rust/projects/coding_convention/)"

本页面列举了一些常见的代码规范要求。部分要求并不强制,但是建议尽量遵守和学习。

## 代码风格

=== "简洁"

保证代码的简洁:

- 有整齐的缩进,建议用空格缩进而非 tab,两个空格或者四个空格作为一级缩进都可以;
- 每一行不要有太多字符,例如不超过 80 - 100 个字符;

=== "注释"

在代码中编写适当的注释:

- 在比较复杂的代码块前,描述代码的功能;
- 过于简单的代码,一般不写注释;
- 函数一般要编写注释,包括其功能,参数和输出;
- 建议用英文,中文也可以,但是注意要用 UTF-8 编码。
- 遵循 [Rustdoc 的约定](https://doc.rust-lang.org/rustdoc/how-to-write-documentation.html)

=== "空白"

代码中应该有适当的空格和空行:

- 函数中,实现不同功能的代码间需要添加空行;
- 操作符前后应该有空格,例如 `c = a + b`;
- 保持前后一致的风格。

=== "命名"

变量的命名,应该符合一定的规范:

- 符合 Rust 编译器建议的变量命名规范;
- 尽量用英文单词,而不是中文拼音首字母;
- 命名与上下文要相关;
- 不用类似 `a, b, c, d` 的命名方式。

建议使用工具来辅助代码风格的检查:

- 使用 `rustfmt``cargo fmt --all` 命令来格式化代码;
- 使用 `clippy``cargo clippy` 来检查代码风格。
- 使用 [typos](https://github.com/crate-ci/typos) 检查拼写错误,可以使用 `cargo install typos-cli` 安装。

!!! note "请注意,由于项目 target 不尽相同,`clippy` 需要在每一个 `package` 下使用。"

## Git 相关

### 提交历史

- 每个提交都应该有一定的意义,例如实现了新功能,修复了一个问题,定义了新的函数;
- 比较复杂的程序,要边开发边提交,而不是写完了再一次性提交;
- 不强求线性历史,**但是不允许使用 force push**

### 提交消息

- 简单明了地描述这个提交的内容;
- 建议用英文写,用中文写也可以;
- 不要编写的过于详细或过于简略;
- 可以采用一些格式,例如 [**Conventional Commits**](https://www.conventionalcommits.org/en/v1.0.0/#examples)
- 不掺杂个人情绪;
- 可以添加一些 Emoji,[gitmoji](https://gitmoji.dev/) 为提交说明中使用的 Emoji 提出了一些建议,可以参考。

### 代码打包

在进行代码提交时,使用如下命令将代码打包:

```bash
git archive --format zip -o ../lab1.zip v0.1
```

`git` 会遵守 `.gitignore` 文件中的规则,不会将不必要的文件打包。从而无需手动删除不必要的文件,或者频繁使用 `cargo clean` 等命令。

**在期末最后的实验报告提交时,需要提交整个代码仓库**,你可以使用如下命令进行仓库的打包,将 `00000000` 位置替换为你的学号:

```bash
git bundle create ../ysos-00000000.bundle --all
```

??? note "给 TA 的注释"

可以直接使用 `git clone` 查看 `bundle` 文件:

```bash
git clone ysos-00000000.bundle /path/to/repo
```

之后可以直接在 `/path/to/repo` 目录下查看提交记录、开发时间等内容。
2 changes: 1 addition & 1 deletion docs/labs/0x00/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

1. 请各位同学独立完成作业,任何抄袭行为都将使本次作业判为 0 分。

2. 请参考 [代码规范](../../general/coding_convention.md) 进行实验代码编写。
2. 请参考 [代码与提交规范](../../general/specification.md) 进行实验代码编写。

3. 依据 [实验任务](./tasks.md) 完成实验。

Expand Down
2 changes: 1 addition & 1 deletion docs/labs/0x01/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@

1. 请各位同学独立完成作业,任何抄袭行为都将使本次作业判为 0 分。

2. 请参考 [代码规范](../../general/coding_convention.md) 进行实验代码编写。
2. 请参考 [代码与提交规范](../../general/specification.md) 进行实验代码编写。

3. 依据 [实验任务](./tasks.md) 完成实验。

Expand Down
2 changes: 1 addition & 1 deletion docs/labs/0x01/tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
```json
{
"llvm-target": "x86_64-unknown-none",
"data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
"data-layout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128",
"linker-flavor": "ld.lld",
"target-endian": "little",
"target-pointer-width": "64",
Expand Down
2 changes: 1 addition & 1 deletion docs/labs/0x02/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

1. 请各位同学独立完成作业,任何抄袭行为都将使本次作业判为 0 分。

2. 请参考 [代码规范](../../general/coding_convention.md) 进行实验代码编写。
2. 请参考 [代码与提交规范](../../general/specification.md) 进行实验代码编写。

3. 依据 [实验任务](./tasks.md) 完成实验。

Expand Down
58 changes: 33 additions & 25 deletions docs/labs/0x02/tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ x86_64::instructions::interrupts::enable();

遵循 I/O 中断处理的 Top half & Bottom half 原则,在中断发生时,仅仅在中断处理中做尽量少的事:读取串口的输入,并将其放入缓冲区。而在中断处理程序之外,选择合适的时机,从缓冲区中读取数据,并进行处理。

为了开启串口设备的中断,你需要参考如下代码,在 `src/drivers/uart16550.rs``init` 函数末尾为串口设备开启中断:
为了开启串口设备的中断,你需要参考如下 C 语言代码,在 `src/drivers/uart16550.rs``init` 函数末尾为串口设备开启中断:

```c
#define PORT 0x3f8 // COM1
Expand All @@ -511,48 +511,56 @@ static int init_serial() {
}
```

为了承接全部(可能的)用户输入数据,并将它们统一在标准输入,需要为输入准备缓冲区,并将其封装为一个驱动,创建 `src/drivers/input.rs` 文件,并借助 `alloc``crossbeam_queue` 等 crate 实现一个输入缓冲区。

??? note "`crossbeam_queue` 的使用提示"

`crossbeam_queue` 默认依赖于 `std`,可以使用如下方式引用:

```toml
[dependencies]
crossbeam-queue = { version = "0.3", default-features = false, features = ["alloc"] }
```
为了承接全部(可能的)用户输入数据,并将它们统一在标准输入,需要为输入准备缓冲区,并将其封装为一个驱动,创建 `src/drivers/input.rs` 文件,使用 `crossbeam_queue` crate 实现一个无锁输入缓冲区。

!!! tip "在 memory 初始化的过程中,你已经有了内核堆分配的能力,可以动态分配内存。"

按照下列描述,补全 `src/drivers/input.rs` 驱动代码:

1. 使用 `crossbeam_queue::ArrayQueue` 存储用户输入的数据。

借助 `once_mutex!``guard_access_fn!` 宏,构造一个上锁的全局静态变量 `INPUT_BUFFER`
1. 使用你喜欢的数据结构存储用户输入的数据。

此缓冲区大小和存储的数据类型由你自行决定,一个参考的缓冲区大小为 128。

2. 实现并暴露 `init` 函数
推荐使用 `crossbeam_queue::ArrayQueue` 作为缓冲区的实现,它是一个无锁的、固定大小的队列,可以在多线程环境下安全地进行读写操作

初始化 `INPUT_BUFFER`,完成后输出日志:`Input Initialized.` 并在在 `src/lib.rs` 中调用它,在操作系统启动时进行。
??? example "`crossbeam_queue` 的使用提示"

请注意:`ysos_kernel::init` 函数中组件的初始化存在顺序,各种组件间可能存在**依赖关系**。由于输入缓冲区初始化是动态分配内存,因此需要在 `memory` 模块初始化之后,才能进行初始化。
`crossbeam_queue` 默认依赖于 `std`,可以使用如下方式引用:

3. 实现并暴露 `push_key` 函数。
```toml
[dependencies]
crossbeam-queue = { version = "0.3", default-features = false, features = ["alloc"] }
```

按照你所定义的类型,对 `INPUT_BUFFER` 上锁后,将数据放入缓冲区。若缓冲区已满,则丢弃数据,并使用 `warn!` 宏输出相关日志
2. 处理数据结构的初始化,暴露基本功能

4. 实现并暴露 `try_pop_key` 函数。
初始化 `INPUT_BUFFER`,你可以直接使用 `lazy_static` 初始化:

从缓冲区中**非阻塞**取出数据。若缓冲区为空或上锁失败,则返回 `None`
```rust
type Key = /* your input type */;

*Note: 或许需要在这一过程中暂时关闭中断。*
lazy_static! {
static ref INPUT_BUF: ArrayQueue<Key> = ArrayQueue::new(128);
}

#[inline]
pub fn push_key(key: Key) {
if INPUT_BUF.push(key).is_err() {
warn!("Input buffer is full. Dropping key '{:?}'", key);
}
}

#[inline]
pub fn try_get_key() -> Option<Key> {
INPUT_BUF.pop()
}
```

5. 实现并暴露 `pop_key` 函数。
3. 实现并暴露 `pop_key` 函数。

利用 `try_pop_key` 函数,从缓冲区中**阻塞**取出数据循环等待,直到缓冲区中有数据。
利用 `try_pop_key` 函数,从缓冲区中**阻塞**取出数据循环等待,直到缓冲区中有数据,并返回获取到的数据

6. 实现并暴露 `get_line` 函数。
4. 实现并暴露 `get_line` 函数。

从缓冲区中**阻塞**取出数据,并将其实时打印出来。直到遇到换行符 `\n`。将数据转换为 `String` 类型,并返回。

Expand Down
2 changes: 1 addition & 1 deletion docs/labs/0x03/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

1. 请各位同学独立完成作业,任何抄袭行为都将使本次作业判为 0 分。

2. 请参考 [代码规范](../../general/coding_convention.md) 进行实验代码编写。
2. 请参考 [代码与提交规范](../../general/specification.md) 进行实验代码编写。

3. 依据 [实验任务](./tasks.md) 完成实验。

Expand Down
Loading

0 comments on commit 2d72091

Please sign in to comment.