前言
进程间通过共享内存实现进程间通信,但是临界资源需要保护,可以使用信号量进行控制。信号量在这里就起到了锁的作用, 对临界资源进行协调。
信号量也是System V体系的一部分, 跟共享内存、消息队列类似。
共享内存
之前讲sysrepo是一个基于共享内存的数据库,sysrepo主要还是通过文件映射的方式实现共享内存的,属于高一个层级的使用。这里讲一下,共享内存的底层接口使用。
创建共享内存
首先,创建之前,我们要有一个 key 来唯一标识这个共享内存。这个 key 可以根据文件系统上的一个文件的 inode 随机生成。
创建一个共享内存,都是使用 xxxget 来创建。
1 |
|
key 就是前面生成的那个 key,shmflag 如果为 IPC_CREAT,就表示新创建,还可以指定读写权限 0777。这里返回一个共享内存的id。
内存映射
生成了共享内存以后,接下来就是将这个共享内存映射到进程的虚拟地址空间中。
1 |
|
这里面的 shm_id,就是上面创建的共享内存的 id,addr 就是指定映射在某个地方。如果不指定,则内核会自动选择一个地址,作为返回值返回。
然后,我们通过强制类型转换,对该内存进行数据写入。
当共享内存使用完毕,我们可以通过 shmdt 解除它到虚拟内存的映射。
1 |
|
信号量
信号量,也是类似的。
首先,创建之前,我们同样需要有一个 key,来唯一标识这个信号量集合。这个 key 同样可以根据文件系统上的一个文件的 inode 随机生成。
然后,我们需要创建一个信号量集合,同样也是使用 xxxget 来创建,其中创建信号量集合使用的是下面这个函数。
1 |
|
这里面的 key,就是前面生成的那个 key,shmflag 如果为 IPC_CREAT,就表示新创建,还可以指定读写权限 0777。
信号量是以集合的形式存在,一次可以申请nsems个信号量,一般我们申请一个就可以了。
信号量对应的有P、V的操作,分别用于获取信号量和释放信号量。信号量可以设置同时并发的个数,每一个P操作就是对信号量的值减一,每一个V操作就是对信号量的值加一。当信号量的值为0的时候,P操作就会挂住,等待信号量的值大于0之后才继续执行。
我们设置信号量的初值为1,那么就可以实现同时仅能有一个访问者对资源操作的功能,就是锁的功能了。
示例程序
源码:
https://gitee.com/fishmwei/blog_code/tree/master/linux-kernel/sem
运行效果
1 |
|
更多
前几天到公司的时间早了一点,下车前突然想到很久没有在极客时间上面学习了,打开趣谈linux操作系统,开始学了大概半小时,感觉效果挺不错,四周挺安静的。嗯,每天挤出来半个小时,学习一下,积少成多,加油。
行动,才不会被动!
欢迎关注个人公众号 微信 -> 搜索 -> fishmwei,沟通交流。