zoukankan      html  css  js  c++  java
  • 进程互斥锁

    进程间共享数据的保护,需要进程互斥锁。与线程锁不同,进程锁并没有直接的C库支持,但是在Linux平台,要实现进程之间互斥锁,方法有很多,大家不妨回忆一下你所了解的。下面就是标准C库提供的一系列方案。

    1、实现方案

    不出意外的话,大家首先想到的应该是信号量(Semaphores)。对信号量的操作函数有两套,一套是Posix标准,另一套是System V标准。

    Posix信号量

    1. sem_t *sem_open(const char *name, int oflag);  
    2. sem_t *sem_open(const char *name, int oflag, mode_t mode, unsigned int value);  
    3. int sem_init(sem_t *sem, int pshared, unsigned int value);  
    4. int sem_wait(sem_t *sem);  
    5. int sem_trywait(sem_t *sem);  
    6. int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout);  
    7. int sem_close(sem_t *sem);  
    8. int sem_destroy(sem_t *sem);  
    9. int sem_unlink(const char *name);  

    System V信号量

    1. int semget(key_t key, int nsems, int semflg);  
    2. int semctl(int semid, int semnum, int cmd, ...);  
    3. int semop(int semid, struct sembuf *sops, unsigned nsops);  
    4. int semtimedop(int semid, struct sembuf *sops, unsigned nsops, struct timespec *timeout);  

    线程锁共享

    其实还有另外一个方案:线程锁共享。这是什么呢,我估计了解它的人不多,如果你知道的话,那可以称为Linux开发牛人了。

    线程锁就是pthread那一套C函数了:

    [html] view plaincopy
    1. int pthread_mutex_init (pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);  
    2. int pthread_mutex_destroy (pthread_mutex_t *mutex);  
    3. int pthread_mutex_trylock (pthread_mutex_t *mutex);  
    4. int pthread_mutex_lock (pthread_mutex_t *mutex);  
    5. int pthread_mutex_timedlock (pthread_mutex_t *restrict mutex, const struct timespec *restrict abstime);  
    6. int pthread_mutex_unlock (pthread_mutex_t *mutex);  

    但是这只能用在一个进程内的多个线程实现互斥,怎么应用到多进程场合呢,被多个进程共享呢?

    很简单,首先需要设置互斥锁的进程间共享属性:

    [html] view plaincopy
    1. int pthread_mutexattr_setpshared(pthread_mutexattr_t *mattr, int pshared);   
    2. pthread_mutexattr_t mattr;   
    3. pthread_mutexattr_init(&mattr);   
    4. 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方式可以解决该问题。但是如果考虑到平台兼容性等问题,这三个方案仍不能满足需求,我会接着介绍一种更好的方案。

  • 相关阅读:
    POJ 1251 Jungle Roads
    1111 Online Map (30 分)
    1122 Hamiltonian Cycle (25 分)
    POJ 2560 Freckles
    1087 All Roads Lead to Rome (30 分)
    1072 Gas Station (30 分)
    1018 Public Bike Management (30 分)
    1030 Travel Plan (30 分)
    22. bootstrap组件#巨幕和旋转图标
    3. Spring配置文件
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13318561.html
Copyright © 2011-2022 走看看