linux网络编程之system v信号量(一)

今天起,学习信号量相关的知识,下面开始:

 关于信号量,在前面已经介绍过了,这里回顾一下:

linux网络编程之system v信号量(一)_第1张图片

通过上面的描述,很容易就能想到信号量的一上数据结构:

linux网络编程之system v信号量(一)_第2张图片

下面再来回顾一下P、V原语:

linux网络编程之system v信号量(一)_第3张图片

linux网络编程之system v信号量(一)_第4张图片

所谓的原语就是指这段代码是原子性的,是不会被其它信号中断的,

 在Linux中,system v 信号量是以信号量集来实现的,跟其它system v IPC对象一样,也有自己的数据结构:

linux网络编程之system v信号量(一)_第5张图片

 同样的,信号量集也提供了一些函数来操作:

linux网络编程之system v信号量(一)_第6张图片

下面一一对其进行学习:

 

linux网络编程之system v信号量(一)_第7张图片

下面用具体代码来实践一下,会封装一些对信号量集的一些函数:

linux网络编程之system v信号量(一)_第8张图片

编译运行:

linux网络编程之system v信号量(一)_第9张图片

linux网络编程之system v信号量(一)_第10张图片

另外,可以用命令来删除已经创建的信号量集,跟消息队列一样(ipcrm -S key 或ipcrm -s semid两种):

linux网络编程之system v信号量(一)_第11张图片

linux网络编程之system v信号量(一)_第12张图片

下面创建了之后,则可以封装一个打开信号量集的方法:

linux网络编程之system v信号量(一)_第13张图片

当创建了一个信号量集,并里面有一个信号量时,这时候最想做的事情是对进信号量设置一个计数值,于是第二个函数出现了:

linux网络编程之system v信号量(一)_第14张图片

linux网络编程之system v信号量(一)_第15张图片

 其中先看下SETVAL参数,查看MAN帮助:

linux网络编程之system v信号量(一)_第16张图片

于是将其结构体拷贝一下,来给信号集来设置一个计数值:

linux网络编程之system v信号量(一)_第17张图片

有了设置计数值,那接下来就可以用GETVAL来获取信号量集中的信号量的计数值:

linux网络编程之system v信号量(一)_第18张图片

接下来封装一个删除指定的信号量集,注意:不可以直接删除某个信号量,只能删除一个信号量集,并将里面所有的信号量给删除了,如下:

linux网络编程之system v信号量(一)_第19张图片

下面则在main中修改一下,来实验下删除功能是否有效:

linux网络编程之system v信号量(一)_第20张图片

编译运行一下:

linux网络编程之system v信号量(一)_第21张图片

可以看出五秒之后,已经成功删除了信号集。

接下来第三个函数是一个比较核心的函数,用来进行P、V操作的:

linux网络编程之system v信号量(一)_第22张图片

linux网络编程之system v信号量(一)_第23张图片

下面用它来封装一下P、V操作:

 linux网络编程之system v信号量(一)_第24张图片

下面对其sembuf进行进一步说明:

linux网络编程之system v信号量(一)_第25张图片

其中sem_op表示我们要操作的方式,而代码中我们写的是-1跟+1,实际上还可以-2,-3,+2,+3,减一个大于零的数字,表示要将信号量的数值减去相应的值,如果当前的个数小于计数值时则会阻塞,处于等待状态,当前前提是sem_flg等于0,如果sem_flg为IPC_NOWAIT而又没有可用资源时,这时semop函数就会返回失败,返回-1,并且错误代码为EAGAIN;而当sem_flg为SEM_UNDO,表示撤消,当一个进程终止的时候,对信号量所做的P或V操作会被撤消, 比如我们对信号进行了一个P操作,对其进行了-1,当进程结束时,最后一次-1将会被撤消,同样的,如果进行了一个V操作,也就是对其进行了+1,当进程结束时,最后的一次+1则会被撤消。

接下来再通过一个例子,来更好的理解信号量的一些机制:

 在看代码之前,先看一下该示例的一个实际效果:

linux网络编程之system v信号量(一)_第26张图片

当运行此程序时,会给出命令使用方法,带不同的参数则会有不同的功能,下面具体解释一下:

①、创建一个信号量集

②、删除一个信号量集

③、进行一个P操作

④、进行一个V操作

⑤、对信号量集中的信号量设置一个初始的计数值

⑥、获取信号量集中信号量的计数值

⑦、查看信号量集的权限

⑧、更改信号量集的权限

下面则具体来使用一下:

linux网络编程之system v信号量(一)_第27张图片

linux网络编程之system v信号量(一)_第28张图片

linux网络编程之system v信号量(一)_第29张图片

linux网络编程之system v信号量(一)_第30张图片

下面继续往下减:

linux网络编程之system v信号量(一)_第31张图片

linux网络编程之system v信号量(一)_第32张图片

但是并不能无限往上加,整数的最大值是有限制的,实际上计数值内部是一个short类型,也就是范围为-32768~32767

linux网络编程之system v信号量(一)_第33张图片

linux网络编程之system v信号量(一)_第34张图片

linux网络编程之system v信号量(一)_第35张图片

接下来分析下程序,首先解析参数:

linux网络编程之system v信号量(一)_第36张图片

linux网络编程之system v信号量(一)_第37张图片

其中查看一下ftok函数帮助:

linux网络编程之system v信号量(一)_第38张图片

这里用"s"一个字符的低八位可以确何不为0,而“.”表示当前路径,两个参数通过ftok就可以产生唯一的一个key_t,至于内部怎么实现不需要关心。

接下来来判断这些参数选项:

linux网络编程之system v信号量(一)_第39张图片

【说明】:关于这里面用到的方法全是上面封装的

下面两个参数是还没有在上面进行封装过,关于权限的获取和设置,下面来看下:

linux网络编程之system v信号量(一)_第40张图片

其中来看一下具体函数的实现:

linux网络编程之system v信号量(一)_第41张图片

其中权限保存的字段可以从man帮助中查看到:

linux网络编程之system v信号量(一)_第42张图片

所以很容易理解,下面为了进一步演示信号量的其它P、V用法,下面更改一下程序:

linux网络编程之system v信号量(一)_第43张图片

下面编译来看下效果: 

linux网络编程之system v信号量(一)_第44张图片

linux网络编程之system v信号量(一)_第45张图片

下面来看下它的效果:

linux网络编程之system v信号量(一)_第46张图片

也就是所做的最后一次操作将会被撤消,同样的,对于v操作这个SEM_UNDO也同样适用,这里就不演示了。

好了,今天先学到这,今天是2015年的第一天,用全心的心情去迎接这美好的新年,明天和小伙伴们去滑雪,想来就刺激, 为了积聚能量,早点睡啦~ 

转载于:https://www.cnblogs.com/webor2006/p/4190943.html

你可能感兴趣的:(linux网络编程之system v信号量(一))