【Linux】进程间同步(进程间互斥锁、文件锁)

一、互斥量 mutex

        进程间也可以使用互斥锁 ,来达到同步的目的。但应在 pthread_mutex_init 初始化之前,修改其属性为进程间共享。mutex 的属性修改函数主要有以下几个。

       主要应用函数:

               1、pthread_mutexattr_t   mutexattr 类型: 用于定义互斥锁的属性。

               2、pthread_mutexattr_init 函数:               初始化一个 mutex 属性对象

                             int pthread_mutexattr_init(pthread_mutexattr_t *attr);

               3、pthread_mutexattr_destroy 函数:        销毁 mutex 属性对象(而非销毁锁)


                              int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);

               4、pthread_mutexattr_setpshared 函数:   修改 mutex 属性

              int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr,int pshared);

                      参数 2 :pshared 取值:

                             线程锁: PTHREAD_PROCESS_PRIVATE( mutex 的默认属性即为线程锁,进程间私有)

                             进程锁:PTHREAD_PROCESS_SHARED


               5、进程间互斥量操作代码示例:

              

/*
    互斥量 实现 多进程 之间的同步 
*/

#include
#include
#include
#include
#include
#include
#include
#include
#include

struct mt
{
    int num;
    pthread_mutex_t mutex;
    pthread_mutexattr_t mutexattr;
};


int main(void)
{
    
    int i;
    struct mt* mm;

    pid_t pid;

    /*
    // 创建映射区文件
    int fd = open("mt_test",O_CREAT|O_RDWR,0777);
    if( fd == -1 ) 
    {
        perror("open file:"); 
        exit(1); 
    }
    ftruncate(fd,sizeof(*mm));
    mm = mmap(NULL,sizeof(*mm),PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
    close(fd);
    unlink("mt_test");
  */

    // 建立映射区
    mm = mmap(NULL,sizeof(*mm),PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANON,-1,0);

//    printf("-------before memset------\n");
    memset(mm,0x00,sizeof(*mm));
//   printf("-------after memset------\n");

    pthread_mutexattr_init(&mm->mutexattr);         // 初始化 mutex 属性
    pthread_mutexattr_setpshared(&mm->mutexattr, PTHREAD_PROCESS_SHARED);               // 修改属性为进程间共享

    pthread_mutex_init(&mm->mutex,&mm->mutexattr);      // 初始化一把 mutex 锁
    
    pid = fork();
    if( pid == 0 )          // 子进程
    {
        for( i=0; i<10;i++ )
        {
            pthread_mutex_lock(&mm->mutex);
            (mm->num)++;
            printf("-child--------------num++    %d\n",mm->num);
            pthread_mutex_unlock(&mm->mutex);
            sleep(1);
        }
    
    }
    else 
    {
        for( i=0;i<10;i++)
        {
            sleep(1); 
            pthread_mutex_lock(&mm->mutex);
            mm->num += 2;
            printf("--------parent------num+=2   %d\n",mm->num);
            pthread_mutex_unlock(&mm->mutex);
        
        }
        wait(NULL);

    }
    pthread_mutexattr_destroy(&mm->mutexattr);  // 销毁 mutex 属性对象
    pthread_mutex_destroy(&mm->mutex);          // 销毁 mutex 锁

    return 0;
}

二、文件锁

         借助 fcntl 函数来实现文件锁。操作文件的进程没有获得锁时,可以打开,但无法执行 read,write 操作。

          fcntl 函数:获取、设置文件访问控制属性。

                      

        #include 
        #include 

                   int fcntl(int fd, int cmd, ... /* arg */ );

         参数 2 :

                    F_SETLK(struct flock *);                  设置文件锁 ( trylock )

                    F_SETLKW(struct flock*);                设置文件锁( lock ) W --- wait 

                    F_GETLK(struct flock*);                   获取文件锁

         参数 3 :

                   

             struct flock {
                            ...
                            short l_type;    /* Type of lock: F_RDLCK,
                                                F_WRLCK, F_UNLCK */
                            short l_whence;  /* How to interpret l_start:
                                                SEEK_SET, SEEK_CUR, SEEK_END */
                            off_t l_start;   /* Starting offset for lock */
                            off_t l_len;     /* Number of bytes to lock */
                            pid_t l_pid;     /* PID of process blocking our lock
                                                (F_GETLK only) */
                             ...
           };

           进程间文件锁 代码示例:

                   

#include
#include
#include
#include
#include
#include

void sys_err(char*str)
{
    perror(str);
    exit(1);
}


int main(int argc,char *argv[])
{
    int fd;
    struct flock f_lock;

    if( argc< 2 )
    {
        printf("./a.out filename\n");
        exit(1);
    }

    if( ( fd = open(argv[1],O_RDWR)) < 0 )
        sys_err("open");

//    f_lock.l_type = F_WRLCK;          // 选用写锁
    f_lock.l_type = F_RDLCK;            // 选用读锁
    f_lock.l_whence = 0;
    f_lock.l_len = 0;                 // 0 表示整个文件加锁

    fcntl(fd,F_SETLKW,&f_lock);
    printf("get flock\n");

    sleep(10);

    f_lock.l_type = F_UNLCK;
    fcntl(fd,F_SETLKW,&f_lock);
    printf("un flock\n");

    close(fd);
    return 0;
}



你可能感兴趣的:(Linux&&操作系统)