进程如何同步你造了么

  前言:线程如何同步应该知道了吧?不知道也没关系,可以参考我的这篇博客:https://www.cnblogs.com/liudw-0215/p/9685498.html,带你get线程同步。那进程如何同步呢?将介绍两种方式:互斥锁、文件锁,由我娓娓道来。

  一、互斥锁

   1、介绍

     一看到互斥锁,就会想到线程也用这个方法同步,那怎么应用到进程呢?

   进程间也可以使用互斥锁来达到同步的目的。但应在pthread_mutex_init初始化之前修改其属性为进程间共享

  2、主要函数 

  pthread_mutexattr_t mattr 类型: 用于定义mutex锁的【属性】

  (1)pthread_mutexattr_init函数

   初始化一个mutex属性对象

  int pthread_mutexattr_init(pthread_mutexattr_t *attr);

  (2)pthread_mutexattr_destroy函数

  销毁mutex属性对象 (而非销毁锁)

  int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);

  (3)pthread_mutexattr_setpshared函数

  修改mutex属性。

  int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared);

  参2pshared取值:

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

  进程锁:PTHREAD_PROCESS_SHARED

  主要就是要用这个pthread_mutexattr_setpshared函数,将属性设置为进程间共享。

  3、示例程序

  程序如下:

  

#include 
#include 
#include 
#include 
#include <string.h>
#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);
    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);
    memset(mm, 0, sizeof(*mm));

    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)++;
            pthread_mutex_unlock(&mm->mutex);
            printf("-child----------num++   %d\n", mm->num);
        }
    } else if (pid > 0) {
        for ( i = 0; i < 10; i++) {
        //    sleep(1);
            pthread_mutex_lock(&mm->mutex);
            mm->num += 2;
            pthread_mutex_unlock(&mm->mutex);
            printf("-------parent---num+=2  %d\n", mm->num);
        }
        wait(NULL);
    }

    pthread_mutexattr_destroy(&mm->mutexattr);          //销毁mutex属性对象
    pthread_mutex_destroy(&mm->mutex);                  //销毁mutex
    munmap(mm,sizeof(*mm));                             //释放映射区

    return 0;
}
View Code

  

  二、文件锁

  1、fcntl函数

  文件锁的实现主要就是通过fcntl函数来实现的,所以先来介绍这个函数。

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

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

  参数说明:

  参数1:文件描述符

  参数2:

  F_SETLK (struct flock *) 设置文件锁(相当于trylock,不成功直接返回

 

  F_SETLKW (struct flock *) 设置文件锁(相当于lock,不成功一直阻塞W --> wait

 

  F_GETLK (struct flock *) 获取文件锁

   

  struct flock {

              ...

              short l_type;     锁的类型:F_RDLCK F_WRLCK F_UNLCK

              short l_whence;   偏移位置:SEEK_SETSEEK_CURSEEK_END

              off_t l_start;    起始偏移:1000

              off_t l_len;      长度:0表示整个文件加锁

              pid_t l_pid;      持有该锁的进程ID(F_GETLK only)

              ...

         };

  2、示例程序

  程序如下:

#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 = SEEK_SET;
    f_lock.l_start = 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;
}
View Code

  

  总结:喜欢的帮忙推荐一下,在此谢过了;欢迎评论,交流与学习

 

你可能感兴趣的:(进程如何同步你造了么)