chapter6练习

  • 本节难度: 也就和lab3一样吧

编程作业

进程通信:邮件

这一章我们实现了基于 pipe 的进程间通信,但是看测例就知道了,管道不太自由,我们来实现一套乍一看更靠谱的通信 syscall吧!本节要求实现邮箱机制,以及对应的 syscall。

  • 邮箱说明:每个进程拥有唯一一个邮箱,基于“数据报”收发字节信息,利用环形buffer存储,读写顺序为 FIFO,不记录来源进程。每次读写单位必须为一个报文,如果用于接收的缓冲区长度不够,舍弃超出的部分(截断报文)。为了简单,邮箱中最多拥有16条报文,每条报文最大长度256字节。当邮箱满时,发送邮件(也就是写邮箱会失败)。不考虑读写邮箱的权限,也就是所有进程都能够随意给其他进程的邮箱发报。

mailread:

  • syscall ID:401

  • C接口: int mailread(void* buf, int len)

  • Rust接口: fn mailread(buf: *mut u8, len: usize)

  • 功能:读取一个报文,如果成功返回报文长度.

  • 参数:

    • buf: 缓冲区头。

    • len:缓冲区长度。

  • 说明:

    • len > 256 按 256 处理,len < 队首报文长度且不为0,则截断报文。

    • len = 0,则不进行读取,如果没有报文读取,返回-1,否则返回0,这是用来测试是否有报文可读。

  • 可能的错误:

    • 邮箱空。

    • buf 无效。

mailwrite:

  • syscall ID:402

  • C接口: int mailwrite(int pid, void* buf, int len)

  • Rust接口: fn mailwrite(pid: usize, buf: *mut u8, len: usize)

  • 功能:向对应进程邮箱插入一条报文.

  • 参数:

    • pid: 目标进程id。

    • buf: 缓冲区头。

    • len:缓冲区长度。

  • 说明:

    • len > 256 按 256 处理,

    • len = 0,则不进行写入,如果邮箱满,返回-1,否则返回0,这是用来测试是否可以发报。

    • 可以向自己的邮箱写入报文。

  • 可能的错误:

    • 邮箱满。

    • buf 无效。

实验要求

  • 实现分支:ch6。

  • 完成实验指导书中的内容,实现进程控制,可以基于 pipe 进行进程通信。

  • 实现邮箱机制及系统调用,并通过 Rust测例 中 chapter6 对应的所有测例。

challenge: 支持多核。

实验检查

  • 实验目录要求

    目录要求不变(参考lab1目录或者示例代码目录结构)。同样在 os 目录下 make run 之后可以正确加载用户程序并执行。

    加载的用户测例位置: ../user/build/bin

  • 检查

    可以正确 make run 执行,可以正确执行目标用户测例,并得到预期输出(详见测例注释)。

问答作业

  1. 举出使用 pipe 的一个实际应用的例子。

  2. 假设我们的邮箱现在有了更加强大的功能,容量大幅增加而且记录邮件来源,可以实现“回信”。考虑一个多核场景,有 m 个核为消费者,n 个为生产者,消费者通过邮箱向生产者提出订单,生产者通过邮箱回信给出产品。

  • 假设你的邮箱实现没有使用锁等机制进行保护,在多核情景下可能会发生哪些问题?单核一定不会发生问题吗?为什么?

  • 请结合你在课堂上学到的内容,描述读者写者问题的经典解决方案,必要时提供伪代码。

  • 由于读写是基于报文的,不是随机读写,你有什么点子来优化邮箱的实现吗?

报告要求

  • 简单总结本次实验与上个实验相比你增加的东西。(控制在5行以内,不要贴代码)

  • 完成问答问题

  • (optional) 你对本次实验设计及难度的看法。