练习#

课后练习#

编程题#

  1. * 分别编写基于UNIX System V IPC的管道、共享内存、信号量和消息队列的Linux应用程序,实现进程间的数据交换。

  2. ** 分别编写基于UNIX的signal机制的Linux应用程序,实现进程间异步通知。

  3. ** 参考rCore Tutorial 中的shell应用程序,在Linux环境下,编写一个简单的shell应用程序,通过管道相关的系统调用,能够支持管道功能。

  4. ** 扩展内核,实现共享内存机制。

  5. *** 扩展内核,实现signal机制。

问答题#

  1. * 直接通信和间接通信的本质区别是什么?分别举一个例子。

  2. ** 试说明基于UNIX的signal机制,如果在本章内核中实现,请描述其大致设计思路和运行过程。

  3. ** 比较在Linux中的无名管道(普通管道)与有名管道(FIFO)的异同。

  4. ** 请描述Linux中的无名管道机制的特征和适用场景。

  5. ** 请描述Linux中的消息队列机制的特征和适用场景。

  6. ** 请描述Linux中的共享内存机制的特征和适用场景。

  7. ** 请描述Linux的bash shell中执行与一个程序时,用户敲击 Ctrl+C 后,会产生什么信号(signal),导致什么情况出现。

  8. ** 请描述Linux的bash shell中执行与一个程序时,用户敲击 Ctrl+Zombie 后,会产生什么信号(signal),导致什么情况出现。

  9. ** 请描述Linux的bash shell中执行 kill -9 2022 这个命令的含义是什么?导致什么情况出现。

  10. ** 请指出一种跨计算机的主机间的进程间通信机制。

实验练习#

实验练习包括实践作业和问答作业两部分。

本次难度也就和lab3一样吧

编程作业#

进程通信:邮箱#

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

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

mailread:

  • syscall ID:401

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

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

  • 参数:
    • buf: 缓冲区头。

    • len:缓冲区长度。

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

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

  • 可能的错误:
    • 邮箱空。

    • buf 无效。

mailwrite:

  • syscall ID:402

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

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

  • 参数:
    • pid: 目标进程id。

    • buf: 缓冲区头。

    • len:缓冲区长度。

  • 说明:
    • len > 256 按 256 处理,

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

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

  • 可能的错误:
    • 邮箱满。

    • buf 无效。

实验要求#

  • 实现分支:ch6-lab

  • 实验目录要求不变

  • 通过所有测例

    在 os 目录下 make run TEST=1 加载所有测例, test_usertest 打包了所有你需要通过的测例,你也可以通过修改这个文件调整本地测试的内容。

    你的内核必须前向兼容,能通过前一章的所有测例。

challenge: 支持多核。

问答作业#

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

  2. 共享内存的测例中有如下片段(伪代码):

    int main()
    {
        uint64 *A = (void *)0x10000000;
        uint64 *B = (void *)(0x10000000 + 0x1000);
        uint64 len = 0x1000;
        make_shmem(A, B, len); // 将 [A, A + len) [B, B + len) 这两段虚存映射到同一段物理内存
        *A = 0xabab;
        __sync_synchronize();  // 这是什么?
        if(*B != 0xabab) {
            return ERROR;
        }
        printf("OK!");
        return 0;
    }
    

    请查阅相关资料,回答 __sync_synchronize 这行代码的作用,如果去掉它可能会导致什么错误?为什么?

实验练习的提交报告要求#

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

  • 完成问答问题

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