"); //-->
进程间共享数据的保护,需要进程互斥锁。与线程锁不同,进程锁并没有直接的C库支持,但是在Linux平台,要实现进程之间互斥锁,方法有很多,大家不妨回忆一下你所了解的。下面就是标准C库提供的一系列方案。
1、实现方案
不出意外的话,大家首先想到的应该是信号量(Semaphores)。对信号量的操作函数有两套,一套是Posix标准,另一套是System V标准。
Posix信号量
[cpp] view plaincopy
sem_t *sem_open(const char *name, int oflag);
sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value);
int sem_init(sem_t *sem, int pshared, unsigned int value);
int sem_wait(sem_t *sem);
int sem_trywait(sem_t *sem);
int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);
int sem_close(sem_t *sem);
int sem_destroy(sem_t *sem);
int sem_unlink(const char *name);
System V信号量
[cpp] view plaincopy
int semget(key_t key, int nsems, int semflg);
int semctl(int semid, int semnum, int cmd, ...);
int semop(int semid, struct sembuf *sops, unsigned nsops);
int semtimedop(int semid, struct sembuf *sops, unsigned nsops, struct timespec *timeout);
线程锁共享
其实还有另外一个方案:线程锁共享。这是什么呢,我估计了解它的人不多,如果你知道的话,那可以称为Linux开发牛人了。
线程锁就是pthread那一套C函数了:
[html] view plaincopy
int pthread_mutex_init (pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);
int pthread_mutex_destroy (pthread_mutex_t *mutex);
int pthread_mutex_trylock (pthread_mutex_t *mutex);
int pthread_mutex_lock (pthread_mutex_t *mutex);
int pthread_mutex_timedlock (pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);
int pthread_mutex_unlock (pthread_mutex_t *mutex);
但是这只能用在一个进程内的多个线程实现互斥,怎么应用到多进程场合呢,被多个进程共享呢?
很简单,首先需要设置互斥锁的进程间共享属性:
[html] view plaincopy
int pthread_mutexattr_setpshared(pthread_mutexattr_t *mattr, int pshared);
pthread_mutexattr_t mattr;
pthread_mutexattr_init(&mattr);
pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
其次,为了达到多进程共享的需要,互斥锁对象需要创建在共享内存中。
最后,需要注意的是,并不是所有Linux系统都支持这个特性,程序里需要检查是否定义了_POSIX_SHARED_MEMORY_OBJECTS宏,只有定义了,才能用这种方式实现进程间互斥锁。
2、平台兼容性
我们来看看这三套方案的平台移植性。
绝大部分嵌入式Linux系统,glibc或者uclibc,不支持_POSIX_SHARED_MEMORY_OBJECTS;
绝大部分嵌入式Linux系统,不支持Posix标准信号量;
部分平台,不支持System V标准信号量,比如Android。
3、匿名锁与命名锁
当两个(或者多个)进程没有特殊关系(比如父子进程共享)时,我们只能通过约定好的名字来访问同一个锁,这就是命名锁。然而,如果我们有其他途径定位一个锁,那么匿名锁是更好的选择。这三套方案是否都支持匿名锁与命名锁呢?
Posix信号量
通过sem_open创建命名锁,通过sem_init创建匿名锁,其实sem_init也支持进程内部锁。
System V信号量
semget中的key参数可以看成是名字,所以支持命名锁。该方案不支持匿名锁。
线程锁共享
不支持命名锁,支持匿名锁。
4、缺陷
在匿名锁与命名锁的支持上,一些方案是有不足的,但这还是小问题,更严重的问题是异常状况下的死锁问题。
与多线程环境不一样的是,在多进程环境中,一个进程的异常退出不会影响其他进程,但是如果使用了进程互斥锁呢?假如一个进程获取了互斥锁,但是在访问互斥资源的代码中crash了,或者遇到信号退出了,那么其他等待同一个锁的进程(内部某个线程)就挂死了。在多线程环境中,程序异常整个进程退出,不需要考虑异常时锁的释放,多进程环境则是一个实实在在的问题。
System V信号量通过UNDO方式可以解决该问题。但是如果考虑到平台兼容性等问题,这三个方案仍不能满足需求,我会接着介绍一种更好的方案。
-----------------------------------
进程互斥锁
https://blog.51cto.com/u_15069489/4537237
专栏文章内容及配图由作者撰写发布,仅供工程师学习之用,如有侵权或者其他违规问题,请联系本站处理。 联系我们
相关推荐
嵌入式Linux优化:加快系统起动和应用起动的过程
Linux系统的DS18B20驱动程序源代码
ARM 开发板使用手册 在三星 S3C2410开发板上烧写linux
Kontron与Congatec合作开发安全的嵌入式Linux平台
[转帖]NeuLinux嵌入式Linux开发平台
[链接]Firefox_ 重新发现网络
嵌入式LINUX开发套件常见问题解答
Linux中的fork与exec系列函数分析
Linux 今天 34 岁了
Linux系统下USB摄像头驱动开发
彻底告别486:Linux内核维护者正式移除英特尔486处理器支持
uClinux系统分析
linux入门精华
Linux内核源代码的阅读和工具介绍(aqian转)
实时Linux技术:如何在嵌入式LINUX中应用实时特性
基于ARM的嵌入式Linux系统开发 中
基于ARM的嵌入式Linux系统开发 下
FFT公司9200的板子的资料
GeForce 590 驱动分支是首个不支持 GTX 9 和 10 系列 GPU 的分支——Linux 版本标志着定义时代显卡的终结
由于英特尔裁员和公司重组,主要的英特尔 Linux 驱动项目正在消亡
uClinux系统分析
基于ARM-Linux的MiniGUI的仿真与移植
U-BOOT 与 MontaVista Linux 的移植
53年后,惠普于1972年推出的总线标准获得了稳定的Linux驱动——通用接口总线拥有惊人的8 MB/s带宽
一种嵌入式ARM-Linux GPS智能终端设计
Linux就AI生成代码定下规则:允许Copilot类工具、拒绝劣质AI代码,错误由人类负责
基于ARM的嵌入式Linux系统开发 上
Linus Torvalds 称谷歌工程师提交的 RISC-V 代码为“垃圾”,并表示它“让世界变得更糟糕”
基于Linux平台的温度传感器DS18B20驱动程序设计
RK3506核心板SDK重磅升级,解锁三核A7实时控制新架构