对信号量的理解

时间:2021-02-21 20:42:42

《UNIX环境高级编程》讲述了两种信号量:XSI信号量和POSIX信号量,而且后一种更好。但实际中好像前一种用的更多。之前一直对信号量一知半解,知道他是一个计数器,用来为多个进程提供对共享数据的访问。每有一个进程访问资源,则计数器减一。直到减到0的时候,需要访问资源的进程就必须等到其他进程释放资源,信号量值大于0才可以继续访问。但是一直没有编程测试过。今天经过一阵尝试折腾才算弄好,对信号量的理解也算多了一些。

测试程序包括两个进程,竞争对一个文件进行写操作。

首先,信号量的资源是什么呢?是一个文件或者一段内存吗?在创建信号量的时候需要把资源和信号量联系在一起吗?我觉得可以这么理解,即使是同一个信号量,他所指的资源也可以是各式各样的,不光是某个文件或者一段内存。可以简单地认为,在每个程序代码的PV操作之间所使用的资源都是信号量的资源,但由于信号量是用来同步的,所以如果代码使用的资源不一样,也就没有了意义。

信号量只是提供了一种一使进程睡眠的方式,如果程序执行到P操作的位置,信号量值为0,那么进程就进入了睡眠,直到信号量为正。既然这样,也就没有必要通过ftok函数把信号量和一个文件或一段内存联系在一起了。一般程序也不是这么写的,一般都是直接写成:

semid = semget((key_t)1234, 3, IPC_CREAT|0600);

每个进程都通过此语句获取键值为1234的信号量,就能够使用同一信号量了。当然需要注意,只能在一个进程里通过semctl()函数的SETVAL参数设置信号量的初值,如果在每个进程中都设置初值,那么信号量就没有了计数器的功能,就不能够提供互斥访问了。 <span style="white-space:pre"> </span>在测试程序中还发现,当进程1进行V操作后,在该进程中打印信号量的值仍然为0,这是因为进程2立即获取了该信号量并进行V操作,当进程1打印信号量值时,进程2已经完成了P操作,所以打印出来仍然是0