XV6

1. 共享内存

由于仅作演示,因此尽量简化功能。要求一个进程只能有一个共享内存区。要求分配共享内存后不允许再用 sbrk 分配空间,共享内存区作为进程最高端的空间。只有解除共享内存映射后才可以继续用 sbrk 释放内存空间。

代码+数据→隔离页帧→堆栈→sbrk 分配空间→共享内存区(不允许 sbrk 操作)

代码+数据→隔离页帧→堆栈→sbrk 分配空间(允许 sbrk 操作)

共享内存区间有全局标识 0~15 共 16 个,每个共享内存区不超过 64 个页(64*4 = 256KB)每个共享内存区有:

struct shm{  
  int allocated;    //是否分配使用的标志 
  Int memsize;      // page 对齐的 
  Void  *pages[64]; //所分配的物理内存地址(内核虚地址)
}shms[16];
  1. 提供系统调用 shm_create(int size) 用于创建共享内存区,返回共享内存的 id 值,超出 256 KB 或者超过 16 个 shm 则返回 -1。

    共享区间物理页帧分配:根据 size 大小分配若干页帧,每个页帧的虚地址填写到 shms[id].pages[i] 中。 设置 shms[id].allocated = 1 标识已分配使用。

  2. 提供系统调用 shm_free(int id)shms[id].pages[] 里的若干页帧逐个用 kfree() 释放,设置 shms[id].allocated=0;

  3. 提供 shm_attch(int id),用于将共享内存映射到用户进程空间,返回用户态的起始地址指针。将进程 proc->sz 先调整到页边界,然后再扩展到 sz+size 空间(类似于 allocuvm() 操作),对于页表映射则逐个页映射到 shms[id].pages[] 中的各个页(pte 地址要通过 V2P 转换)。

  4. 提供 shm_deatt(int id),用于将共享内存空间释放。对于释放的高地址的若干个页帧, 逐个解除页表映射(参考 deallocuvm() 的操作)。

编写应用程序,先运行一个进程创建并映射指定 id 的共享内存,写入指定数据。然后再启动另一个进程映射该 id 的共享内存。

2. 消息队列

参照 Linux 的实现,在进程 proc 中添加一个成员用于记录消息队列。出于简化编程的目的,一个消息不管长度位多少,都用一个页帧大小来管理。另外还需要注意同步关系。