百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

Linux系统编程—进程间同步(linux 进程间同步)

gudong366 2025-05-02 17:32 9 浏览

我们知道,线程间同步有多种方式,比如:信号量、互斥量、读写锁,等等。那进程间如何实现同步呢?本文介绍两种方式:互斥量和文件锁。

##互斥量mutex

我们已经知道了互斥量可以用于在线程间同步,但实际上,互斥量也可以用于进程间的同步。为了达到这一目的,可以在pthread_mutex_init初始化之前,修改其属性为进程间共享。mutex的属性修改函数主要有以下几个:

主要应用函数:

pthread_mutexattr_t mattr 类型: 用于定义互斥量的属性 pthread_mutexattr_init函数:初始化一个mutex属性对象 pthread_mutexattr_destroy函数:销毁mutex属性对象 (而非销毁锁)
pthread_mutexattr_setpshared函数:修改mutex属性。

int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared);

我们重点看第二个参数:pshared,它有以下两个取值:

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

进程锁:PTHREAD_PROCESS_SHARED

要想实现进程间同步,需要将mutex的属性改为PTHREAD_PROCESS_SHARED

#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;

    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++) {
            sleep(1);
            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;
}

##文件锁

顾名思义,就是通过文件实现锁机制。具体来讲,是通过借助 fcntl函数来实现锁机制。当操作文件的进程没有获得锁时,虽然可以打开文件,但无法对文件执行执行read、write操作。

###fcntl函数:

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

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

参数介绍: 参数cmd有以下取值: F_SETLK (struct flock )设置文件锁(trylock) F_SETLKW (struct flock ) 设置文件锁(lock)W --> wait F_GETLK (struct flock *)获取文件锁 数据类型flock原型如下: struct flock { ... short l_type; 锁的类型:F_RDLCK 、F_WRLCK 、F_UNLCK short l_whence; 偏移位置:SEEK_SET、SEEK_CUR、SEEK_END off_t l_start; 起始偏移:1000 off_t l_len; 长度:0表示整个文件加锁 pid_t l_pid; 持有该锁的进程ID:(F_GETLK only) ... };

###进程间文件锁示例

多个进程对加锁文件进行访问:

#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\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;
}

文件锁类似于读写锁,依然遵循“读共享、写独占”特性。但是,如果进程不加锁直接操作文件,依然可访问成功,但数据势必会出现混乱。

既然文件锁可用应用在进程中,那在多线程中,可以使用文件锁吗?

答案是不行的。因为多线程间共享文件描述符,而给文件加锁,是通过修改文件描述符所指向的文件结构体中的成员变量来实现的。因此,多线程中无法使用文件锁。

> 2020 精选 阿里/腾讯等一线大厂 面试、简历、进阶、电子书 公众号「**良许Linux**」后台回复「**资料**」免费获取

#### 看完的都是真爱,点个赞再走呗?您的「三连」就是良许持续创作的最大动力!

1. 关注**原创**公众号「**良许Linux**」,第一时间获取最新Linux干货!

2. 公众号后台回复【资料】【面试】【简历】获取精选一线大厂面试、自我提升、简历等资料。

3. 关注我的博客:[lxlinux.net](http://www.lxlinux.net)

相关推荐

U盘文件被删怎么简单恢复(u盘里的文件被误删了怎么找回)

现在这个社会不是靠关系靠路子,主要还是靠实力。刘强在机关工作,人长得帅气,工作能力又强。唯独一样不好,脾气太大,动不动就发火,因为小事常和同事发生口角。一次他火大的差点把办公桌给掀翻了,领导见他野蛮的...

不小心删除了一些文件?9 个最佳免费硬盘恢复软件

恢复您曾经无意或意外删除的所有文件和数据。您是否曾经错误地删除了一个对您的工作至关重要并导致您丢失所有进度的文件?我们为您提供了一些最好的免费硬盘恢复软件,以帮助您恢复意外删除的文件,以解决您的文件删...

Studio 中文版:数据救援神器,误删 / 分区损坏 / RAID 恢复一键找回

Studio中文版:数据救援神器,误删/分区损坏/RAID恢复一键找回当文件意外删除、分区损坏,或RAID阵列崩溃时,一款可靠的数据恢复工具往往能挽回关键损失。R-Studio中文版...

你值得拥有的11款Linux数据恢复工具

如果你使用的是Linux操作系统,那么你一定想知道一旦硬盘崩溃的话又该如何保存和恢复数据。其实,现在有很多Linux数据恢复工具可以让我们摆脱数据安全的困扰。小编已经为各位准备好了一些最好的Linux...

误删文件内容怎么恢复(误删文件内容怎么恢复回来)

  在日常使用电脑的过程中,误删文件的情况时有发生。无论是由于操作失误还是病毒攻击,误删文件都会给我们带来不小的困扰。幸运的是,随着技术的发展,误删文件恢复已不再是难题。本文将介绍几款国内外知名的误删...

u盘如何恢复删除的文件?推荐5款u盘数据恢复软件!

在日常生活与工作中,U盘作为便捷的数据存储载体,频繁用于传输和保存各类重要文件。然而,误删文件的情况却时有发生,无论是珍贵的照片、重要的工作文档,还是精心制作的视频,一旦删除,都可能带来不小的麻烦。...

怎么恢复删除的数据?5种有效的数据恢复方法汇总!

在数字化办公与生活的时代,电脑里的每一份数据都承载着重要信息。然而,一个误操作就可能导致数据被删除,无论是尚未保存的重要文档,还是珍藏多年的照片,都可能瞬间“消失”。但其实,数据删除并不意味着永久丢...

u盘删除文件怎么找回?5个数据恢复工具汇总,助你巧妙恢复数据!

在日常使用U盘的过程中,误删文件的情况时有发生,重要的工作文档、珍贵的照片视频一旦消失,难免让人焦急万分。别担心,只要选对数据恢复工具,被删除的数据仍有找回的可能。下面就为你汇总5款实用的数据...

Linux下恢复误删文件:思路+实践(linux删除如何恢复)

周五篮球群里有人问误删文件了怎么恢复,得知是ext4文件系统之后我推荐了ext4magic这个工具,然后又有人提到了xfs的话怎么办,正好前几天看到DaveChinner在邮件列表里提到了这个问题,...

苹果放大招!不用虚拟机了,Mac直接跑Linux容器,开发者效率翻倍

苹果这次真给开发者送福利了!今天凌晨(6月10日),苹果在官宣的Containerization框架直接炸了技术圈——Mac现在能原生运行Linux容器镜像了!这可不是虚拟机那种“套娃”方案,而是基...

7 款老牌经典软件,值得收藏(经典老歌软件)

Calibrehttps://calibre-ebook.com/Calibre是一个电脑电子书管理软件。肯定有人说了,电子书还要管理?那当然了。它的功能更强大的让你想象不到,首先它可以导入PDF,...

神仙级的免费开源电子书阅读器,还支持听书功能

神仙级的免费开源电子书阅读器,还支持听书功能,极空间部署『KoodoReader』哈喽小伙伴们好,我是Stark-C~前段时间不是给大家分享的电子书管理工具『TaleBook』嘛~,然后就有粉丝私信...

如何在Ubuntu系统中重置root密码(ubuntu忘记密码重置root密码命令)

很多人有个问题,就是喜欢把密码设置得很长很复杂,结果谁也没防住,却成功防住了自己ヽ(.ˇдˇ;)ノ对于现代人,特别是年轻人,都有过忘记密码的经历吧。在这篇文章中,我们来了解如何在Ubuntu1...

5款功能强大的PDF阅读器,让PDF阅读更轻松

分享5款功能强大的PDF阅读器,拥有丰富的PDF阅读工具,支持PDF文档划线、笔记、标记等操作,让PDF阅读更轻松!1.嗨动PDF编辑器一款实用的PDF处理软件,不仅可以阅读PDF文档,还能直接编辑、...

上班摸鱼利器! 免费好用的电子书阅读器,NAS轻松部署Koodo Reader

哈喽,大家好我是生活爱好者。笔者也是一名小说爱好者,平时用手机用某信读书,会员也开了,在家看体验也不错,但是上班的时候,在工作快速完成之后,想摸个鱼用手机就不太方便啦,作为爱折腾的人,必须要工作认真,...