操作系统实验之通过信号量实现复杂PC问题

PC问题

PC问题(producer and consumer,生产者和消费者问题)是操作系统中并发程序设计中的经典同步问题。

semget 函数的作用是创建新的或获得已存在的信号量集。这个函数是以信号量集作为操作单位的,一个信号量集可以包括一个或多个信号量。对于PC问题,有full、empty、mutex1、mutex2等多个信号量。在选取信号量以及对它们进行操作(赋值、P、V)的时候,通过两种变量来识别它们,分别是键值sem_id和信号在信号量集中的序号sem_num。所以可以有两种选择:

  • 声明四个键值,用来创建四个信号量集,每个信号量集包括一个信号量。在操作信号量时,每个信号量的sem_num都是0。是通过键值sem_id来区分信号量的。

  • 只声明一个键值,创建一个信号量集,但里面有四个信号量。所以每个信号量的键值都一样,而是通过sem_id来区分,分别是0、1、2、3。

从运行结果来看,P、C的过程成功受到了信号量的影响。

update: 2017-05-20: 竟然忘了把信号量放到共享存储区中,罪过罪过,在这里多谢浴盆指出我的问题。

代码地址

父子进程、共享存储区

摘抄一段CSAPP中关于进程的内容:

第8章异常控制流:

父进程通过调用fork函数来创建一个新的运行子进程……新创建的子进程几乎但不完全与父进程相同。子进程得到与父进程用户级虚拟地址空间相同(但是独立的)一份拷贝,包括文本、数据和BSS段、堆、栈。子进程还获得与父进程任何打开文件描述符相同的拷贝。这意味着父进程调用fork时,子进程可以读写父进程打开的任何文件。

父进程和子进程是并发运行的独立进程。

相同但是独立的地址空间。如果能在fork函数在父子进程返回后立即暂停,可以看到每个进程的地址空间是相同的(相同的用户栈、堆、本地变量值、全局变量值、相同的代码)。然而,父进程和子进程是独立的进程,它们都有自己私有的地址空间。父进程对于一个变量所做的任何改变都是独立的,不会反映在另一个进程的存储器中。

第9章虚拟存储器:

进程这一抽象能够为每个进程提供私有的虚拟地址空间,免受其他进程的错误读写。……幸运的是,存储器映射给我们提供一种清晰的机制来控制多个进程共享对象。

如果一个进程把一个共享对象映射到它的虚拟地址空间的一个区域内,那么这个进程对这个区域的任何写操作,对于那些也把这个共享对象映射到它们的虚拟存储器的其他进程而言也是可见的。


关于信号量实验API的一些参考链接