Linux内核锁实现原理,linux 大内核锁原理

大内核锁(BKL)的设计是在kernel hacker们对多处理器的同步还没有十足把握时,引入的大粒度锁。

他的设计思想是,一旦某个内核路径获取了这把锁,那么其他所有的内核路径都不能再获取到这把锁。

自旋锁加锁的对象一般是一个全局变量,大内核锁加锁的对象是一段代码,里面可能包含多个全局变量。

那么他带来的问题是,虽然A只需要互斥访问全局变量a,但附带锁了全局变量b,从而导致B不能访问b了。

大内核锁最先的实现靠一个全局自旋锁,但大家觉得这个锁的开销太大了,影响了实时性,因此后来将自旋锁

改成了mutex,但阻塞时间一般不是很长,所以加锁失败的挂起和唤醒也是非常costly 所以后来又改成了自旋锁实现。

大内核锁一般是在文件系统,驱动等中用的比较多。目前kernel hacker们仍然在努力将大内核锁从linux里铲除。

下面来分析大内核锁的实现。

我们之前说了大内核锁有两种实现,分别是自旋锁和mutex锁。

如果是mutex锁实现,自然不能在中断环境下使用大内核锁,因为中断下禁止调度是金科玉律。

那么在大内核锁内调度是否可以?我们知道,如果一个内核流程获取到资源后就应该尽快完成操作释放资源,

以便下一个竞争者获取到资源。所以资源持有者不得睡眠是一个普遍共识。可是大内核锁不这么认为,

持有大内核锁的用户是允许睡眠的-虽然我们并不鼓励这样,但是内核的大内核锁的设计方案里,会在进程切换时,

检查当前进程是否持有大内核锁并释放,当重新获取到cpu后,再尝试抓这把大内核锁。也就是说,进程在

持有大内核锁时是可以睡眠的,这就带来资源starvation

来看基于自旋锁的大内核锁实现

static inline void __lock_kernel(void)

{

preempt_disable();

if (unlikely(!_raw_spin_trylock(&kernel_flag))) {

/*

* If preemption was disabled even before this

* was called, there's nothing we can be polite

* about - just spin.

*/

if (preempt_count() > 1) {

_raw_spin_lock(&kernel_flag);

return;

}

/*

* Otherwise, let's wait for the kernel lock

* with preemption enabled..

*/

do {

preempt_enable();

while (spin_is_locked(&kernel_flag))

cpu_relax();

preempt_disable();

} while (!_raw_spin_trylock(&kernel_flag));

}

}

void __lockfunc lock_kernel(void)

{

int depth = current->lock_depth+1;

if (likely(!depth))

__lock_kernel();

current->lock_depth = depth;

}

这段代码的意思是,

1) 如果当前进程如果不是重复加锁的话,就尝试去抓这把锁,

并把锁深度加1。这么做的目的是避免锁重入。

2)实际加锁的时候,先关抢占,如果尝试加锁失败,则会

根据调用lock_kernel之前关抢占与否,来决定是闷头死转,还是大开门户的轮询。

如果是mutex实现的大内核锁kernel_lock,则第2步直接mutex_lock--要么成功要么阻塞。

之前我们提到,在进程发生切换时,会检查当前进程是否持有大内核锁,这是在schedule

里做的。

asmlinkage void __sched schedule(void)

{

release_kernel_lock(prev);

context_switch();

reacquire_kernel_lock(current);

}

release_kernel_lock会判断如果当前进程持有大内核锁,则释放锁。

reacquire_kernel_lock在进程再次被调度回来后,检查当前进程在切换之前是否

因为持有大内核锁。如果有的话,说明在进程切换时,当前进程的大内核锁被强行释放了,

需要再次获取。

需要说明的是自旋锁版本:

release_kernel_lock在释放锁之后还会开抢占,因为获取到大内核锁之后会关闭;

reacquire_kernel_lock在重新获取到锁之后,会关闭抢占。

重点关注__reacquire_kernel_lock的实现

自旋锁的实现版本:

成功抓到锁之后关抢占,如果抓不到锁,则一直遍历need resched标志直至退出。注意和lock_kernel比较。

mutex版本就比较扯淡了:

int __lockfunc __reacquire_kernel_lock(void)

{

int saved_lock_depth = current->lock_depth;

BUG_ON(saved_lock_depth < 0);

current->lock_depth = -1;

preempt_enable_no_resched();

mutex_lock(&kernel_sem);

preempt_disable();

current->lock_depth = saved_lock_depth;

return 0;

}

我们之前看到kernel_lock的mutex实现就是一句mutex_lock 而这里的__reacquire_kernel_lock

有些细节差别。

1)首先将当前进程的加锁深度设置为-1,代表无人加锁。这么做的意义是,第2步的mutex_lock如果产生调度,

再次进入shedule时,不会重复释放大内核锁,因为__reacquire_kernel_lock之前已经释放锁了。

2)接着临时强行开抢占后执行mutex_lock

因为在schedule里是关抢占的,此时不能发生进程切换。

3)如果抓到锁则关抢占

恢复到schedule里调__reacquire_kernel_lock之前的抢占状态

4)将加锁深度恢复到__reacquire_kernel_lock之前的深度

恢复到schedule里调__reacquire_kernel_lock之前的大内核锁持有状态

总而言之,关于大内核锁,记住两点就可以了:

1)由spinlock或者mutex_lock锁住一个全局变量来实现

2)进程切换时会检查当前进程是否持有大内核锁,而采取释放和重获的操作,以支持持有大内核锁的用户代码睡眠。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/368095.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Sass学习日志

一、什么是SASS SASS是一中CSS的开发工具&#xff0c;提供了许多便利的写法&#xff0c;大大节约了设计者们的时间&#xff0c;使得CSS的开发&#xff0c;变得简单和可维护。本文总结了SASS的主要方法。我们的目标是&#xff0c;有了这篇文章&#xff0c;日常的一般使用就不需…

ptyhon中文本挖掘精简版

import xlrd import jieba import sys import importlib import os #python内置的包&#xff0c;用于进行文件目录操作&#xff0c;我们将会用到os.listdir函数 import pickle #导入cPickle包并且取一个别名pickle #持久化类 import random import numpy as np …

[UWP]了解模板化控件(9):UI指南

[UWP]了解模板化控件(9)&#xff1a;UI指南 原文:[UWP]了解模板化控件(9)&#xff1a;UI指南1. 使用TemplateSettings统一外观 TemplateSettings提供一组只读属性&#xff0c;用于在新建ControlTemplate时使用这些约定的属性。 譬如&#xff0c;修改HeaderedContentControl的Co…

Java的反射API

如果您曾经问​​过自己以下问题&#xff1a; –“如何在字符串中仅包含其名称的方法调用&#xff1f;” –“如何动态列出类中的所有属性&#xff1f;” –“如何编写一种将任何给定对象的状态重置为默认值的方法&#xff1f;” 然后您可能已经听说过Java的Reflection API…

linux服务器基本常识,服务器搭建-Linux基础知识

服务器搭建还是需要一些Linux知识的&#xff0c;这节就聊点基础的。文件权限操作查看权限Linux中每个文件对每个用户来说都有对应的权限&#xff0c;在任一路径中输入ll就可以查看这些信息&#xff1a;rootip-*** /usr/local # lltotal 32Kdrwxr-xr-x 2 root root 4.0K Jan 14 …

mysql基本命令入门

背景 作为一个前端&#xff0c;重新学习后台相关知识&#xff0c;记录下自己遇到及用到的命令及爬坑经验。 基本命令 1.创建数据库 create database 数据库名称 eg: create database test //创建一个名为test的数据库 2.查看所有数据库 show databases 3.选择某一个数据库 use …

不完善迷你计算器

html代码&#xff1a; <!DOCTYPE html PUBspanC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns"http://www.w3.org/1999/xhtml"><head><meta http-e…

LINQ和Java

LINQ已经非常成功&#xff0c;但在.NET生态系统中也引起了争议。 许多人正在Java世界中寻找可比的解决方案。 为了更好地理解什么是可比的解决方案&#xff0c;让我们看一下LINQ解决的主要问题&#xff1a; 查询语言通常是具有许多关键字的声明性编程语言。 它们提供的控制流元…

怎样 测试 某个 端口 是否打开

我们一般最常见的工具是telnet&#xff0c;但是telnet使用的是tcp协议&#xff0c;换句话说telnet只能检测tcp的这个端口打开了没。 方法很简单&#xff0c;假设我们要看192.192.193.211这个IP的tcp 22端口是否打开&#xff0c;则运行telnet 192.192.193.211 22 来查看 如果cen…

linux用户空间注册按键事件,linux下获取按键响应事件

1、问题通过一个死循环将读取键盘对应的设备文件将触发键盘事件在屏幕上打印出来&#xff0c;按esc退出程序代码是在unbuntu10.04编译执行通过的2、input_event描述在Linux内核中&#xff0c;input设备用input_dev结构体描述&#xff0c;使用input子系统实现输入设备驱动的时候…

CSS实现单行与多行文字省略(truncation)

在上一篇文章小div布局之卡片堆叠&#xff08;card-stacking&#xff09;中有多行文字溢出省略的效果&#xff0c;这篇文章就对这种效果&#xff08;包括单行文字溢出省略&#xff09;的实现做个简单的记录&#xff0c;以防自己忘记。具体来说&#xff0c;就是要实现这种文字排…

位运算的使用例子

class Data { public:enum Permission{allowSelect 1 << 0,allowUpdate 1 << 1,allowInsert 1 << 2,allowDelete 1 << 3}; public:Data():flag(0){};~Data(){};/*添加某权限*/void enable(int permission){flag | permission;}/*删除某权限*/void…

事务性Lucene

许多用户不喜欢Lucene API的事务性语义&#xff0c;以及这在搜索应用程序中如何有用。 首先&#xff0c;Lucene实现了ACID属性&#xff1a; 一个 tomicity&#xff1a;当您在更改&#xff08;添加&#xff0c;删除文件&#xff09; IndexWriter会话&#xff0c;然后提交&#…

logback配置详解和使用

最近知道一种打印日志的新方法&#xff0c;在此做一下学习总结。 转自&#xff1a;行走在云端的愚公 https://www.cnblogs.com/warking/p/5710303.html 一、logback的介绍 Logback是由log4j创始人设计的另一个开源日志组件,官方网站&#xff1a; http://logback.qos.ch。它当前…

linux下iostat命令无效,linux iostat命令详解

iostatiostat用于输出CPU和磁盘I/O相关的统计信息.命令格式:iostat [ -c | -d ] [ -k | -m ] [ -t ] [ -V ] [ -x ] [ device [ ... ] | ALL ] [ -p [ device | ALL ] ][ interval [ count ] ]1)iostat的简单使用iostat可以显示CPU和I/O系统的负载情况及分区状态信息.直接执行i…

css样式表

样式表&#xff1a; 一。内联&#xff1a;写在body中 直接在内容的标签中添加style属性&#xff1a;例如<div style"...">1234</div> 二。内嵌&#xff1a;写在head中 一般写在标题标签的后面&#xff0c;添加<style type"text/css"&g…

RAID技术超详细讲解

RAID 技术是一种多磁盘技术&#xff0c;面对数据的各方面有着两面性的影响&#xff0c;整体来说优点大于缺点的&#xff0c;下面我将详细介绍一下 RAID &#xff0c;简称磁盘阵列技术。 一、RAID 概述 1988 年美国加州大学伯克利分校的 D. A. Patterson 教授等首次在论文 “A C…

集群应用服务器环境中会话管理(复制)的Oracle Coherence最佳实践

Oracle Coherence是一种内存中数据网格产品&#xff0c;也广泛用于跨应用程序服务器节点集群的会话复制。 它支持各种应用程序服务器&#xff0c;例如WebLogic&#xff0c;WebSphere&#xff0c;Tomcat&#xff0c;JBoss等。Coherence * Web是会话管理模块&#xff08;基于Cohe…

自适应居中

一、窗体居中 position: absolute; top: 0; right: 0; bottom: 0; left: 0; margin: auto; /*height: 50px; width: 165px; */ 简析&#xff1a; position:固定位置显示&#xff08;absolute|fixed&#xff09;&#xff1b; 【absolute&#xff1a;窗口大小由上层position为ab…

linux ip地址漂移,Linux 实现高可用性(HA) —之ip 漂移方法(vrrp)

在日常的系统管理当中,某些应用对可用性要求比较高,简单的冷备是不能满足需求,所以才需要双机热备即HA.根据此应用要求,我们介绍一个软件实现高可用性.keepalived是Linux下一个双机热备的软件&#xff0c;可提供vrrp以及health-check功能&#xff0c;目前仅用它提供双机漂移ip,…