当前位置: 首页 > news >正文

长春哪家做网站做的好/台州seo

长春哪家做网站做的好,台州seo,博客登陆wordpress,孟州网站建设第三十九章 linux-并发解决方法二(互斥锁mutex) 文章目录第三十九章 linux-并发解决方法二(互斥锁mutex)互斥锁的定义与初始化互斥锁的DOWN操作互斥锁的UP操作用count1的信号量实现的互斥方法还不是Linux下经典的用法,…

第三十九章 linux-并发解决方法二(互斥锁mutex)


文章目录

  • 第三十九章 linux-并发解决方法二(互斥锁mutex)
  • 互斥锁的定义与初始化
  • 互斥锁的DOWN操作
  • 互斥锁的UP操作


用count=1的信号量实现的互斥方法还不是Linux下经典的用法,Linux内核针对count=1的信号量重新定义了一个新的数据结构,一般都称其为互斥锁或者互斥体。同时内核根据使用场景的不同,把用于信号量的DOWN和UP操作在struct mutex上作了优化与扩展,专门用于这种新的数据类型。

互斥锁的定义与初始化

互斥锁mutex的概念本来就来自semaphore,如果去除掉那些跟调试相关的成员,struct mutex和struct semaphore并没有本质的不同:

struct mutex {/* 1: unlocked, 0: locked, negative: locked, possible waiters */atomic_t        count;spinlock_t        wait_lock;struct list_head    wait_list;
#if defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_MUTEX_SPIN_ON_OWNER)struct task_struct    *owner;
#endif
#ifdef CONFIG_MUTEX_SPIN_ON_OWNERstruct optimistic_spin_queue osq; /* Spinner MCS lock */
#endif
#ifdef CONFIG_DEBUG_MUTEXESvoid            *magic;
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOCstruct lockdep_map    dep_map;
#endif
};

如同struct semaphore一样,对struct mutex的初始化不能直接通过操作其成员变量的方式进行,而应该利用内核提供的宏或者函数定义一个静态的struct mutex变量同时初始化的方法是利用内核的DEFINE_MUTEX:


#define __MUTEX_INITIALIZER(lockname) \{ .count = ATOMIC_INIT(1) \, .wait_lock = __SPIN_LOCK_UNLOCKED(lockname.wait_lock) \, .wait_list = LIST_HEAD_INIT(lockname.wait_list) \__DEBUG_MUTEX_INITIALIZER(lockname) \__DEP_MAP_MUTEX_INITIALIZER(lockname) }#define DEFINE_MUTEX(mutexname) \struct mutex mutexname = __MUTEX_INITIALIZER(mutexname)

如果在程序执行期间要初始化一个mutex变量,则可以使用mutex_init宏。去除掉那些与调试相关的操作之后,mutex_init宏可以展开成如下的函数定义形式:

# define mutex_init(mutex) \
do {                            \static struct lock_class_key __key;        \\__mutex_init((mutex), #mutex, &__key);        \
} while (0)void
__mutex_init(struct mutex *lock, const char *name, struct lock_class_key *key)
{atomic_set(&lock->count, 1);spin_lock_init(&lock->wait_lock);INIT_LIST_HEAD(&lock->wait_list);mutex_clear_owner(lock);
#ifdef CONFIG_MUTEX_SPIN_ON_OWNERosq_lock_init(&lock->osq);
#endifdebug_mutex_init(lock, name, key);
}

互斥锁的DOWN操作

互斥锁mutex上的DOWN操作在Linux内核中为mutex_lock函数,定义如下:

void __sched mutex_lock(struct mutex *lock)
{might_sleep();/** The locking fastpath is the 1->0 transition from* 'unlocked' into 'locked' state.*/__mutex_fastpath_lock(&lock->count, __mutex_lock_slowpath);mutex_set_owner(lock);
}

函数的设计思想体现在__mutex_fastpath_lock和__mutex_lock_slowpath两条主线上,__mutex_fastpath_lock用来快速判断当前可否获得互斥锁,如果成功获得锁,则函数直接返回,否则进入到__mutex_lock_slowpath函数中·这种设计是基于这样一个事实:想要获得某一互斥锁的代码绝大部分时候都可以成功获得。由此延伸开来在代码层面就是,mutex_lock函数进入__mutex_lock_slowpath的概率很低。

__mutex_fastpath_lock是一平台相关函数,下面以ARM处理器为例,分析其代码实现:

static inline void
__mutex_fastpath_lock(atomic_t *count, void (*fail_fn)(atomic_t *))
{int __done, __res;__asm__ __volatile__ (L1            "movli.l    @%2, %0    \n""add        #-1, %0    \n""movco.l    %0, @%2    \n""movt        %1    \n": "=&z" (__res), "=&r" (__done): "r" (&(count)->counter): "t");if (unlikely(!__done || __res != 0))fail_fn(count);
}

函数在百处通过ldrex完成“__res=count->counter,L2处完成__res=__res-1,L3处试图用__res的当前值来更新count->counter.这里说“试图”是因为这个更新的操作未必会成功,主要是考虑到可能有别的进程也在操作count->counter,为不使这种可能的竞争引起对
作count->counter值更新的混乱,这里用了ARM指令中用于实现互斥访问的指令ldrex和strex(前面在spinlock的代码分析时己经提过)。ldrex和strex保证了对count->counter读取一更新一写回”操作序列的原子性。如果L3处的更新操作成功,那么_ex_flag将为0。

接下来在__res|=__ex_flag执行完之后,通过if语句判断__res是否为0,有两种情况会导致__res不为0:一是在调用这个函数前count->counter=0,表明互斥锁己经被别的进程获得,
这样L2处的__res=-1:二是在L3处的更新操作不成功,表明当前有另外一个进程也在对count->counter进行同样的操作·这两种情况都将导致__mutex_fastpath_lock不能直接返回,而是进入fail_fn也就是调用__mutex_lock_slowpath。

此处if语句中的unlikely是利用GCC编译优化扩展的一个宏,这里的意思是条件语句__res!=0为真的可能性很小,编译器借此可以调整一些编译后代码的顺序达到某种程度的优化。与之对应的是likely。
如果__mutex_fastpath_lock函数不能在第一时间获得互斥锁返回,那么将进入__mutex_lock_slowpath,正如其名字所预示的那样,代码将进入一段艰难坎坷的旅途。

在Linux源码中,__mutex_lock_slowpath函数与信号量DOWN操作中的函数非常相似,不过__mutex_lock_slowpath在把当前进程放入mutex的wait_list之前会试图多次询问mutex中的count是否为1,也就是说当前进程在进入wait_list之前会多次考察别的进程是否己经释放了这个互斥锁。这主要基于这样一个事实:拥有互斥锁的进程总是会在尽可能短的时间里释放·如果别的进程己经释放了该互斥锁·那么当前进程将可以获得该互斥锁而没有必要再去睡眠。

互斥锁的UP操作

互斥锁的操作为mutex_unlock,函数定义如下:

void __sched mutex_unlock(struct mutex *lock)
{/** The unlocking fastpath is the 0->1 transition from 'locked'* into 'unlocked' state:*/
#ifndef CONFIG_DEBUG_MUTEXES/** When debugging is enabled we must not clear the owner before time,* the slow path will always be taken, and that clears the owner field* after verifying that it was indeed current.*/mutex_clear_owner(lock);
#endif__mutex_fastpath_unlock(&lock->count, __mutex_unlock_slowpath);
}

和mutex_lock函数一样,mutex_unlock函数也有两条主线:__mutex_fastpath_unlock和__mutex_unlock_slowpath,分别用于对互斥锁的快速和慢速解锁操作。

static inline void
__mutex_fastpath_unlock(atomic_t *count, void (*fail_fn)(atomic_t *))
{int __done, __res;__asm__ __volatile__ ("movli.l    @%2, %0    \n\t""add        #1, %0    \n\t""movco.l    %0, @%2 \n\t""movt        %1    \n\t": "=&z" (__res), "=&r" (__done): "r" (&(count)->counter): "t");if (unlikely(!__done || __res <= 0))fail_fn(count);
}

这里除了是将count->counter的值加1以外,代码和__mutex_fastpath_lock中的几乎完全一样。在最后的if语句中,导致代码count->counter不为0也有两种情况:一是在调用这个函数前count->counter不为0,表明在当前进程占有互斥锁期间有别的进程竞争该互斥锁:二是对count->counter的更新操作不成功,表明当前有另外一个进程也在对count->counter进行操作,这种情况主要是针对别的进程此时调用mutex1k函数导致的竞争,因为互斥的原因别的进程此时不可能调用mutex_lock。这种情况的处理是非常重要的,不只是关系到count->counter正确更新的问题,还涉及能否防止一个唤醒操作的丢失。

在没有别的进程竞争该互斥锁的情况下,__mutex_fastpath_unlock函数要完成的工作最简单,把count->counter的值加1然后返回·如果有别的进程在竞争该互斥锁,那么函数进入__mutex_unlock_slowpath这个函数主要用来唤醒在当前mutex的wait_list中休眠的进程,如同up函数一样。

相关文章:

第三十九章 linux-并发解决方法二(互斥锁mutex)

第三十九章 linux-并发解决方法二&#xff08;互斥锁mutex&#xff09; 文章目录第三十九章 linux-并发解决方法二&#xff08;互斥锁mutex&#xff09;互斥锁的定义与初始化互斥锁的DOWN操作互斥锁的UP操作用count1的信号量实现的互斥方法还不是Linux下经典的用法&#xff0c;…...

脚本方式本地仓库jar包批量导入maven私服

脚本内容&#xff0c;将以下内容保存为mavenimport.sh&#xff0c;放置于需要上传的目录下&#xff0c;可以是顶层目录&#xff0c;或者某个分包的目录&#xff0c;若私服已有待上传的包&#xff0c;则执行会被替换 #!/bin/bash # copy and run this script to the root of th…...

【c++】引用的学习

引用的定义和声明 引用是一种别名&#xff0c;它允许使用与原变量相同的内存位置。在C中&#xff0c;引用是使用&符号来定义的。引用必须在定义时初始化&#xff0c;并且可以与原变量分别使用。 int a 10; int& b a; // 定义了一个引用b&#xff0c;它指向a引用的作用…...

linux 软件安装及卸载

1.联网在线安装及卸载ubuntu环境下&#xff1a;使用apt-get 工具apt-get install - 安装软件包apt-get remove - 移除&#xff08;卸载&#xff09;软件包CentOS环境下&#xff1a;使用yum工具 &#xff08;银河麒麟系统属于centos&#xff09;yum install - 安装软件包yum rem…...

XShell连接ubuntu20.04.LTS

1 下载XshellXShell官方下载地址打开XSHELL官方下载地址&#xff0c;我们可以选择【家庭和学校用户的免费许可证】&#xff0c;输入邮箱之后即可获得下载链接安装非常简单&#xff0c;跟着提示进行即可。2 连接ubuntu2.1 查看ubuntu的ip地址输入命令查看ip地址ifconfig刚开始可…...

【FPGA】Verilog:MSI/LSI 组合电路之解码器 | 多路分解器

写在前面&#xff1a;本章将理解编码器与解码器、多路复用器与多路分解器的概念&#xff0c;通过使用 Verilog 实现多样的解码器与多路分解器&#xff0c;通过 FPGA 并使用 Verilog 实现。 Ⅰ. 前置知识 0x00 解码器与编码器&#xff08;Decoder / Encoder&#xff09; 解码器…...

深入理解JDK动态代理原理,使用javassist动手写一个动态代理框架

文章目录一、动手实现一个动态代理框架1、初识javassist2、使用javassist实现一个动态代理框架二、JDK动态代理1、编码实现2、基本原理&#xff08;1&#xff09;getProxyClass0方法&#xff08;2&#xff09;总结写在后面一、动手实现一个动态代理框架 1、初识javassist Jav…...

一、策略模式的使用

1、策略模式定义&#xff1a; 策略模式&#xff08;Strategy Pattern&#xff09;定义了一组策略&#xff0c;分别在不同类中封装起来&#xff0c;每种策略都可以根据当前场景相互替换&#xff0c;从而使策略的变化可以独立于操作者。比如我们要去某个地方&#xff0c;会根据距…...

Verilog使用always块实现时序逻辑

这篇文章将讨论 verilog 中一个重要的结构---- always 块&#xff08;always block&#xff09;。verilog 中可以实现的数字电路主要分为两类----组合逻辑电路和时序逻辑电路。与组合逻辑电路相反&#xff0c;时序电路电路使用时钟并一定需要触发器等存储元件。因此&#xff0c…...

面向对象设计模式:行为型模式之迭代器模式

一、迭代器模式&#xff0c;Iterator Pattern aka&#xff1a;Cursor Pattern 1.1 Intent 意图 Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation. 提供一种按顺序访问聚合对象的元素而不公开其基…...

如何快速在企业网盘中找到想要的文件

现在越来越多的企业采用企业网盘来存储文档和资料&#xff0c;而且现在市面上的企业网盘各种各样。在使用企业网盘过程中&#xff0c;很多用户会问到企业网盘中如何快速搜索文件的问题。但是无论是“标签”功能还是普通的“关键词搜索”功能&#xff0c;都是单层级的&#xff0…...

香橙派5使用NPU加速yolov5的实时视频推理(二)

三、将best.onnx转为RKNN格式 这一步就需要我们进入到Ubuntu20.04系统中了&#xff0c;我的Ubuntu系统中已经下载好了anaconda&#xff0c;使用anaconda的好处就是可以方便的安装一些库&#xff0c;而且还可以利用conda来配置虚拟环境&#xff0c;做到环境与环境之间相互独立。…...

算法练习-二分查找(一)

算法练习-二分查找 1 代码实现 1.1 非递归实现 public int bsearch(int[] a, int n, int value) {int low 0;int high n - 1;while (low < high) {int mid (low high) / 2;if (a[mid] value) {return mid;} else if (a[mid] < value) {low mid 1} else {high …...

通用业务平台设计(五):预警平台建设

前言 在上家公司&#xff0c;随着业务的不断拓展(从支持单个国家单个主体演变成支持多个国家多个主体)&#xff0c;对预警的诉求越来越紧迫&#xff1b;如何保障业务的稳定性那&#xff1f;预警可以帮我们提前甄别风险&#xff0c;从而让我们可以在风险来临前将其消灭&#xff…...

Windows openssl-1.1.1d vs2017编译

工具&#xff1a; 1. perl&#xff08;https://strawberryperl.com/&#xff09; 2. nasm&#xff08;https://nasm.us/&#xff09; 3. openssl源码&#xff08;https://www.openssl.org/&#xff09; 可以自己去下载 或者我的网盘提供下载&#xff1a; 链接&#xff1a;…...

【深蓝学院】手写VIO第2章--IMU传感器--笔记

0. 内容 1. 旋转运动学 角速度的推导&#xff1a; 左ω∧\omega^{\wedge}ω∧&#xff0c;而ω\omegaω是在z轴方向运动&#xff0c;θ′[0,0,1]T\theta^{\prime}[0,0,1]^Tθ′[0,0,1]T 两边取模后得到结论&#xff1a; 线速度大小半径 * 角速度大小 其中&#xff0c;对旋转矩…...

网络基础(二)之HTTP与HTTPS

应用层 再谈 "协议" 协议是一种 "约定". socket api的接口, 在读写数据时, 都是按 "字符串" 的方式来发送接收的. 如果我们要传输一些"结构化的数据" 怎么办呢? 为什么要转换呢&#xff1f; 如果我们将struct message里面的信息…...

Python每日一练(20230306)

目录 1. 翻转二叉树 ★★ 2. 最长公共前缀 ★★ 3. 2的幂 ★ 1. 翻转二叉树 翻转一棵二叉树。 示例 1&#xff1a; 输入&#xff1a; 4/ \2 7/ \ / \ 1 3 6 9 输出&#xff1a; 4/ \7 2/ \ / \ 9 6 3 1示例 2&#xff1a; 输入&#xff1a; 1…...

C/C++每日一练(20230305)

目录 1. 整数分解 ☆ 2. 二叉树的最小深度 ★★ 3. 找x ★★ 1. 整数分解 输入一个正整数&#xff0c;将其按7进制位分解为各乘式的累加和。 示例 1&#xff1a; 输入&#xff1a;49 输出&#xff1a;497^2示例 2&#xff1a; 输入&#xff1a;720 输出&#xff1a;720…...

SAS字典的应用

数据字典中常用信息检索DICTIONARY.COLUMNS、DICTIONARY.TABLES以及DICTIONARY.MEMBERS等字典表的内容。在编程实践中&#xff0c;如何以SAS字典表来提高效率。 1、DICTIONARY.COLUMNS 对于当前SAS任务的全部数据集&#xff0c;表格DICTIONARY.COLUMNS包含了诸如变量的名称、类…...

Mysql中的函数和触发器

函数函数是什么&#xff1f;多用于查询语句&#xff0c;实现了某种功能&#xff1b;用途与存储过程不同&#xff0c;但语法是类似的&#xff1b;函数语法create function 函数名([参数列表]) returns 数据类型 begin DECLARE 变量&#xff1b; sql 语句; return 值; end; 设置函…...

分布式架构之(Zookeeper原理)

Zookeeper是一个典型的分布式数据一致性的结局方案&#xff0c;分布式应用程序可以基于它实现注入数据发布、订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master选举、分布式锁和分布式队列等功能&#xff0c; Zookeeper可以保证如下分布式一致性特性&#xff1a; 顺…...

Java框架学习 | MyBatis

问题导向学习MyBatis 为什么要有MyBatis框架&#xff1f; 避免Java开发者直接使用 JDBC重复做数据库操作&#xff0c;同时更便捷地实现想要的数据库相关功能&#xff0c;让Java专注于开发业务。 MyBatis框架如何实现该目的&#xff1f; MyBatis是半自动化持久层ORM框架&#x…...

Cookie+Session详解

文章目录批量删除会话技术简介CookieCookie 查看Cookie 的删除Cookie 使用页面获取 cookie 信息cookie 特点Sessionsession 的使用Session 登录权限验证过滤器简介过滤器的使用WebFilter 注解过滤放行登录权限验证批量删除 servlet 类 dao 层 会话技术 简介 在计算机领域…...

CAPL脚本要注意区分elcount和strlen求数组长度的区别,不然要吃大亏

&#x1f345; 我是蚂蚁小兵&#xff0c;专注于车载诊断领域&#xff0c;尤其擅长于对CANoe工具的使用&#x1f345; 寻找组织 &#xff0c;答疑解惑&#xff0c;摸鱼聊天&#xff0c;博客源码&#xff0c;点击加入&#x1f449;【相亲相爱一家人】&#x1f345; 玩转CANoe&…...

CSS常用选择器

目录 1.CSS是什么 2.CSS的三种写法 2.1内部样式 2.2内联样式 2.3外部样式 3.CSS选择器 3.1标签选择器 3.2类选择器(更好的选择) 3.3ID选择器 3.4后代选择器 3.5子选择器 3.6并集选择器 3.7伪类选择器(复合选择器的特殊用法) 1.CSS是什么 CSS全称Cascding Style Sh…...

Registry与DGC的攻击利用

0x01 2022-02-03写的一篇文章。 0x02 Registry Registry指的是RMI的注册表&#xff0c;攻击的目标是注册表所在的机器&#xff0c;一般注册表和RMI Server在同一个机器上&#xff0c;特殊情况下也会在不同机器上。 在我们通过LocateRegistry#getRegistry获取到目标开启的注…...

赛道持续降温!又一家自动驾驶公司裁员,市值曾超50亿美元

从去年下半年开始&#xff0c;自动驾驶赛道的裁员、倒闭风潮盛行。 本周&#xff0c;美股卡车自动驾驶上市公司Embark Trucks&#xff08;EMBK&#xff09;宣布将裁员70%&#xff0c;同时大幅缩减业务。“痛苦可能还没有结束&#xff0c;”公司首席执行官Alex Rodrigues在给员…...

路径规划 | 图解动态A*(D*)算法(附ROS C++/Python/Matlab仿真)

目录0 专栏介绍1 什么是D*算法&#xff1f;2 D*算法核心概念一览3 D*算法流程图4 步步图解&#xff1a;算法实例5 算法仿真与实现5.1 ROS C实现5.2 Python实现0 专栏介绍 &#x1f525;附C/Python/Matlab全套代码&#x1f525;课程设计、毕业设计、创新竞赛必备&#xff01;详…...

GraphCut、最大流最小割定理

G&#xff08;V&#xff0c;E&#xff09;&#xff1b;V为点集&#xff0c;E为边集&#xff1b; 节点集V中的节点分为&#xff1a; &#xff08;1&#xff09;终端节点。不包含图像像素&#xff0c;用S和T表示。S为源点&#xff0c;T为汇点。图像分割中通常用S表示前景目标&a…...