• 进程如何同步你造了么


      前言:线程如何同步应该知道了吧?不知道也没关系,可以参考我的这篇博客: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 <stdio.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <stdlib.h>
    #include <string.h>
    #include <pthread.h>
    #include <sys/mman.h>
    #include <sys/wait.h>
    
    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
    ", 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
    ", 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 <stdio.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <stdlib.h>
    
    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
    ");
            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
    ");
    
        sleep(10);
    
        f_lock.l_type = F_UNLCK;
        fcntl(fd, F_SETLKW, &f_lock);
        printf("un flock
    ");
    
        close(fd);
    
        return 0;
    }
    View Code

      

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

  • 相关阅读:
    使用socket BPF/Linux内核工程导论——网络:Filter(LSF、BPF、eBPF)
    使用Iperf工具测试android系统网络wifi的吞吐量wifithrougput
    html input中 button和submit的区别
    Linux转发性能评估与优化(转发瓶颈分析与解决方案)
    交叉编译器 arm-linux-gnueabi 和 arm-linux-gnueabihf 的区别
    MySQL查询不区分大小写的sql写法
    Docker镜像保存save、加载load
    将Spring-boot应用部署到Docker容器
    Docker 安装使用
    Scalatra文件下载时中文乱码
  • 原文地址:https://www.cnblogs.com/liudw-0215/p/9705390.html
Copyright © 2020-2023  润新知