一起talk C栗子吧(第一百零二回:C语言实例--使用信号量进行进程间同步与互斥三)
程序员文章站
2022-05-13 16:08:40
各位看官们,大家好,上一回中咱们说的是使用信号量进行进程间同步与互斥的例子,这一回咱们继续说该例子。闲话休提,言归正转。让我们一起talk C栗子吧!
看官们,我们在上一...
各位看官们,大家好,上一回中咱们说的是使用信号量进行进程间同步与互斥的例子,这一回咱们继续说该例子。闲话休提,言归正转。让我们一起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 //后台进程运行结束
大家从上面的运行结果中可以看到,首先是后台进程执行临界区中的代码,然后才是前台进程执行临界区中的代码。也就是说同一段时间内只能有一个进程操作临界区的代码,这便是进程之间的同步与互斥。
各位看官,关于使用信号量进行进程间同步与互斥的例子咱们就说到这里。欲知后面还有什么例子,且听下回分解 。