各位看官们,大家好,上一回中咱们说的是使用信号量进行进程间同步与互斥的例子,这一回咱们继续说该例子。闲话休提,言归正转。让我们一起talk C栗子吧!
看官们,我们在上一回中介绍了信号量相关的函数及其用法,这一回中我们通过具体的例子来说明如使用这些函数来操作信号量。
下面是具体的使用步骤:
- 1.使用semget函数创建一个信号量;
- 2.使用semctl函数初始化信号量;
- 3.使用semop函数对信号量进行P操作,以便进程进入临界区操作临界资源;
- 4.使用semop函数对信号量进行V操作,以便进程离开临界区时唤醒其它进程;
- 5..使用semctl函数删除信号量;
大家还记得我们在前面章回中的伪代码吧,我们将把这些伪代码转换为实际的C语言代码:
nocritical code //非临界区的代码
P(sem); //执行P操作,进入临界区,执行临界区中的代码
{
critical code; //临界区代码
do something
}
V(sem); //执行V操作,离开临界区
nocritical code //非临界区的代码
看官们,正文中就不写代码了,详细的代码放到了我的资源中,大家可以点击这里下载使用。
另外,我说一下代码中的内容(可以下载代码后对比着看):代码开始处自己定义了联合体semun,不然会有编译错误,详细如下:
union semun
{
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO */
};
代码中对信号量的操作都进行了封装,比如把semctl函数封装成了初始化和删除信号量的函数,把semop函数封装成了信号量的P/V操作。此外,我们在代码中对使用参数和不使用参数这两种情况进行了区分,而且在使用参数时对程序进行了延时操作,这样是为了方便大家观察程序运行结果。
下面是程序的运行结果,请大家参考:
(在运行程序时使用-s参数表示对信号量进行初始化和删除操作,不使用参数时只进行P/V操作。)
$./a -s & //在后台运行编译后的程序a,参数-s表示初始化或者删除信号量
[1] 2713 //程序在后台运行,这里启动了后台进程,PID:2713
$ [pid: 2713 ] init semaphore
[pid: 2713 ] running nocritical code
$./a //在前台运行程序,不使用任何参数,这里启动了前台进程,PID:2714
[pid: 2714 ] running nocritical code
[pid: 2713 ] enter critical area
[pid: 2713 ] running critical code //后台进程执行临界区的代码
[pid: 2713 ] leave critical area
[pid: 2714 ] enter critical area
[pid: 2714 ] running critical code //前台进程执行临界区的代码
[pid: 2714 ] leave critical area
[pid: 2714 ] running nocritical code
$ [pid: 2713 ] delete semaphore
[pid: 2713 ] running nocritical code
//需要按下回车键切换到终端窗口中
[1]+ Done ./a -s //后台进程运行结束
大家从上面的运行结果中可以看到,首先是后台进程执行临界区中的代码,然后才是前台进程执行临界区中的代码。也就是说同一段时间内只能有一个进程操作临界区的代码,这便是进程之间的同步与互斥。
各位看官,关于使用信号量进行进程间同步与互斥的例子咱们就说到这里。欲知后面还有什么例子,且听下回分解 。