Linux内核之 内核同步

Linux内核同步操作详解 Linux内核同步操作详解,英文版,开发驱动必备。 立即下载

 

一、同步介绍

 

1、临界区与竞争条件

所谓临界区(critical regions)就是访问和操作共享数据的代码段。为了避免在临界区中并发访问,编程者必须保证这些代码原子地执行——也就是说,代码在执行结束前不可被打断,就如同整个临界区是一个不可分割的指令一样。如果两个执行线程有可能处于同一个临界区中同时执行,那么就是程序包含一个bug,如果这种情况发生了,我们就称之为竞争条件(race conditions,简称竞态),避免并发和防止竞争条件被称为同步(synchronization)。

在linux中,主要的竞态发生在如下几种情况:

(1)对称多处理器(SMP)多个CPU

特点是多个CPU使用共同的系统总线,因此可访问共同的外设和存储器。

(2)单CPU内进程与抢占它的进程

(3)中断(硬中断、软中断、Tasklet、中断下半部)与进程之间

只要并发的多个执行单元存在对共享资源的访问,竞态就有可能发生。

如果中断处理程序访问进程正在访问的资源,则竞态也会发生。

多个中断之间本身也可能引起并发而导致竞态(中断被更高优先级的中断打断)。

互斥锁,自旋锁,CAS,原子操作详细说明点击:「链接」

2、死锁

死锁的产生需要一定条件:要有一个或多个执行线程和一个或多个资源,每个线程都在等待其中的一个资源,但所有的资源都已经被占用了,所有线程都在相互等待,但它们永远不会释放已经占有的资源,于是任何线程都无法继续,这便意味着死锁的发生。

最简单的死锁例子是自死锁:

  • 获得锁

  • 再次试图获得锁

  • 等待锁重新利用

  • ......

这种情况属于一个线程一把锁,自己等自己,一般是一个函数等另一个函数,从广义上说就是一种嵌套使用。我曾经的经验总结《踩坑经验总结(四):死锁》就属于这种情况。

最常见的死锁例子是ABBA锁:

  • 线程1

  • 获得锁A

  • 试图获得锁B

  • 等待锁B

  • ......

  • 线程2

  • 获得锁B

  • 试图获得锁A

  • 等待锁A

  • ......

这种问题确实很常见,在数据库《MySQL InnoDB技术内幕:内存管理、事务和锁》出现的往往也是这种类型的死锁。

3、加锁规则

预防死锁非常重要,那该注意些什么呢?

(1)按顺序加锁。使用嵌套锁是必须保证以正确的顺序获取锁,这样可以阻止致命的拥抱类死锁,即ABBA锁。最好能记录下锁的顺序,后续都按此顺序使用。

(2)防止发生饥饿。特别是在一些大循环中,尽量将锁移入内部,否则外面等太久。如果发生死循环,就会出现饥饿。

(3)不要重复请求同一把锁。这是针对自死锁的情况,但是一旦出现这种情况,往往不明显,即不是很明显的嵌套,转了几个弯弯,就叫曲线嵌套吧。

(4)设计应力求简单。越复杂的加锁方案越有可能造成死锁。

这里的每一项都很重要,对于应用程序同样适合。再重点说下设计。

在最开始设计代码的时候,就应该考虑加锁;越往后考虑,付出代价越大,效果反而越不理想。那么设计阶段加锁时一定要考虑,为什么要加锁,为了保护什么数据?我认为这是一个定位的问题。需求阶段对一个产品的定位,设计阶段对数据的定位,决定了后续一系列的动作比如采用的方案、采用的算法、采用的结构体......开始经验之谈了:)。

那么到底该如何加锁,记住:要给数据而不是给代码加锁。我认为这是一个黄金规则,在《死锁》也这么强调过。

4、争用与扩展性

锁的争用(lock contention),简称争用,是指当锁正在被占用时,有其他线程试图获得该锁。

  • 说一个锁处于高度争用状态,就是指有多个其他线程在等待获得该锁。

  • 由于锁的作用是使程序以串行方式对资源进行访问,所以使用锁无疑会降低系统的性能。被高度争用(频繁被持有,或者长时间持有——两者都有就更糟糕)的锁会成为系统的瓶颈,严重降低系统性能。

扩展性(scalability)是对系统可扩展程度的一个量度。

  • 对于操作系统,我们在谈及可扩展性时就会和大量进程、大量处理器或是大量内存等联系起来。其实任何可以被计量的计算机组件都可以涉及可扩展性。理想情况下,处理器的数量加倍应该会使系统处理性能翻倍。而实际上, 这是不可能达到的。

  • 自从2.0版内核引入多处理支持后,Linux对集群处理器的可扩展性大大提高了。在Linux刚加入对多处理器支持的时候,一个时刻只能有一个任务在内核中执行;在2.2版本中,当加锁机制发展到细粒度加锁后,便取消了这种限制,而在2.4和后续版本中,内核加锁的粒度变得越来越精细。如今,在Linux 2.6版内核中,内核加的锁是非常细的粒度,可扩展性也很好.

  • 加锁粒度用来描述加锁保护的数据规模。

  • 一个过粗的锁保护大块数据——比如,一个子系统用到的所有的数据结构:相反,一个过于精细的锁保护很小的一块数据——比如,一个大数据结构中的一个元素。在实际使用中,绝大多数锁的加锁范围都处于上述两种极端之间,保护的既不是一个完整的子系统也不是一个独立元素,而可能是一个单独的数据结构。许多锁的设计在开始阶段都很粗,但是当锁的争用问题变得严重时,设计就向更加精细的加锁方向进化。

  • 在前面讨论过的运行队列,就是一个锁从粗到精细化的实例。

  • 在2.4版和更早的内核中,调度程序有一个单独的调度队列(回忆一下,调度队列是一个由可调度进程组成的链表),在2.6版内核系列的早期版本中,O(1)调度程序为每个处理器单独配备一个运行队列,每个队列拥有自己的锁,于是加锁由一个全局锁精化到了每个处理器拥有各自的锁。这是一种重要的优化,因为运行队列锁在大型机器上被争着用,本质上就是要在调度程序中每次都把整个调度进程下放到单个处理器上执行。在2.6版内核系列的版本中,CFS调度器进一步提升了锁的可扩展性。

  • 一般来说,提高可扩展性是件好事,因为它可以提高Linux在更大型的、处理能力更强大的系统上的性能。

  • 但是一味地“提高”可扩展性,却会导Linux在小型SMP和UP机器上的性能降低,这是因为小型机器可能用不到特别精细的锁,锁得过细只会增加复杂度,并加大开销。

  • 考虑一个链表,最初的加锁方案可能就是用一个锁来保护链表,后来发现,在拥有集群处理器机器上,当各个处理器需要频繁访问该链表的时候,只用单独一个锁却成了扩展性的瓶颈。为解决这个瓶颈,我们将原来加锁的整个链表变成为链表中的每一个结点都加入自己的锁,这样一来, 如果要对结点进行读写,必须先得到这个结点对应的锁。将加锁粒度变细后,多处理器访问同一 个结点时,只会争用一个锁。可是这时锁的争用仍然没有完全避免,那么,能不能为每个结点中的每个元素都提供一个锁呢?(答案是:不能)严格地讲,即使这么细的锁可以在大规模SMP机器上执行得很好,但它在双处理器机器上的表现又会怎样呢?如果在双处理器机器锁争用表现 得并不明显,那么多余的锁会加大系统开销,造成很大的浪费。

  • 不管怎么说,可扩展性都是很重要的,需要慎重考虑。关键在于,在设计锁的开始阶段就应该考虑到要保证良好的扩展性。因为即使在小型机器上,如果对重要资源锁得太粗,也很容易造成系统性能瓶颈。锁加得过粗或过细,差别往往只在一线之间。当锁争用严重时,加锁太粗会降低可扩展性;而锁争用不明显时,加锁过细会加大系统开销,带来浪费,这两种情况都会造成系统性能下降。但要记住:设计初期加锁方案应该力求简单,仅当需要时再进一步细化加锁方案。 精髓在于力求简单。

上面这大段话来自书上,分析的很好,介绍了锁的粒度过粗和过细的危害,同时也介绍了内核加锁的一个变化和演进。总之,对于我们设计软件都有参考意义。也是理解内核后面为什么出现了多种同步方法的原因。

二、同步方法

Linuxc/c++服务器开发高阶视频学习资料+qun720209036获取。关注VX公众号:Linux C后台服务器开发

内容包括C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis,MongoDB,ZK,流媒体,P2P,K8S,Docker,TCP/IP,协程,DPDK多个高级知识点。

 

1、原子操作

原子操作是其他同步方法的基石。原子操作可以保证指令以原子的方式执行——执行过程不可中断。在数据库事务中这也是基本的要求。

linux内核提供了两组原子操作接口:一组对整数进行操作,一组针对单独的位进行操作。

原子整数操作

针对整数的原子操作只能对atomic_t类型的数据进行处理,在这里之所以引入了一个特殊的数据类型,而没有直接使用C语言的int型,主要是出于两个原因:

第一、让原子函数只接受atomic_t类型的操作数,可以确保原子操作只与这种特殊类型数据一起使用,同时,这也确保了该类型的数据不会被传递给其它任何非原子函数;

第二、使用atomic_t类型确保编译器不对相应的值进行访问优化——这点使得原子操作最终接收到正确的内存地址,而不是一个别名,最后就是在不同体系结构上实现原子操作的时候,使用atomic_t可以屏蔽其间的差异。

atomic_t类型定义在文件<linux/type.h>中:

typedef struct {
    volatile int counter;  
}atomic_t;
 

原子整数操作最常见的用途就是实现计数器。

另一点需要说明原子操作只能保证操作是原子的,要么完成,要么不完成,不会有操作一半的可能,但原子操作并不能保证操作的顺序性,即它不能保证两个操作是按某个顺序完成的。如果要保证原子操作的顺序性,请使用内存屏障指令。

原子操作与更复杂的同步方法相比较,给系统带来的开销小,对高速缓存行的影响也小。

原子位操作

针对位这一级数据进行操作的函数,是对普通的内存地址进行操作的。它的参数是一个指针和一个位号。

2、自旋锁

Linux内核中最常见的锁是自旋锁(spin lock)。自旋锁最多只能被一个可执行线程持有。如果一个执行线程试图获得一个被争用(已经被持有)的自旋锁,那么该线程就会一直进行忙循环—旋转—等待锁重新可用。要是锁未被争用,请求锁的执行线程便能立刻得到它,继续执行。在任意时间,自旋锁都可以防止多于一个的执行线程同时进入临界区。同一个锁可以用在多个位置—例如,对于给定数据的所有访问都可以得到保护和同步。

一个被争用的自旋锁使得请求它的线程在等待锁重新可用时自旋(特别浪费处理器时间),即忙等待,这是自旋锁的要点。所以自旋锁不应该被长时间持有。事实上,这点正是使用自旋锁的初衷,在短期间内进行轻量级加锁。

自旋锁的实现和体系密切相关,代码往往通过汇编实现。实际用到的接口定义在文件中。自旋锁的基本使用形式如下:

DEFINE  SPINLOCK(mr_lock);

spin_lock(&mr_lock);
/*临界区....*/
spin_unlock(&mr_lock);
 

自旋锁可以使用在中断处理程序中(此处不能使用信号量,因为它们会导致睡眠),在中断处理程序中使用自旋锁时,一定要在获取锁之前,首先禁止本地中断(在当前处理器上的中断请求)。注意,需要关闭的只是当前处理器上的中断,如果中断发生在不同的处理器上,即使中断处理程序在同一锁上自旋,也不会妨碍锁的持有者(在不同处理器上)最终释放锁。

3、读写自旋锁

有时,锁的用途可以明确的分为读取和写入两个场景。那么读写可以分开处理,读时可以共享数据,写时进行互斥。为此,Linux内核提供了专门的读写自旋锁。

这种读写自旋锁为读和写分别提供了不同的锁,所以它具有以下特点:

  1. 读锁之间是共享的,即一个线程持有了读锁之后,其他线程也可以以读的方式持有这个锁。

  2. 写锁之间是互斥的,即一个线程持有了写锁之后,其他线程不能以读或者写的方式持有这个锁。

  3. 读写锁之间是互斥的,即一个线程持有了读锁之后,其他线程不能以写的方式持有这个锁,写锁必须等待读锁的释放。

读写自旋锁的使用用法类似于普通的自旋锁:

DEFINE_RWLOCK(mr_rwlock);

read_lock(&mr_rwlock);
/*critical region, only for read*/
read_unlock(&mr_rwlock);

write_lock(&mr_lock);
/*critical region, only for write*/
write_unlock(&mr_lock);
 

注意:如果写和读不能清晰地进行分离,那么使用一般的自旋锁就够了,不需要使用读写自旋锁。

4、信号量

信号量也是一种锁,和自旋锁不同的是,线程获取不到信号量的时候,不会像自旋锁一样循环去试图获取锁,而是进入睡眠,直至有信号量释放出来时,才会唤醒睡眠的线程,进入临界区执行。

由于使用信号量时,线程会睡眠,所以等待的过程不会占用 CPU 时间。所以信号量适用于等待时间较长的临界区。

信号量消耗CPU时间的地方在于使线程睡眠和唤醒线程--两次明显的上下文切换。

如果(使线程睡眠 + 唤醒线程)的 CPU 时间 > 线程自旋等待 CPU 时间,那么可以考虑使用自旋锁。

信号量有二值信号量和计数信号量两种,其中二值信号量比较常用。

二值信号量表示信号量只有2个值,即0和1。信号量为1时,表示临界区可用,信号量为0时,表示临界区不可访问。所以也可以称为互斥信号量。

计数信号量有个计数值,比如计数值为5,表示同时可以有5个线程访问临界区。所以二值信号量就是计数等于1的计数信号量。

5、读写信号量

读写信号量和信号量的关系与读写自旋锁和自旋锁的关系差不多。

读写信号量都是二值信号量,即计数值最大为1,增加读者时,计数器不变,增加写者,计数器才减一。

也就是说读写信号量保护的临界区,最多只有一个写者,但可以有多个读者。

6、互斥

互斥体(mutex)也是一种可以睡眠的锁,相当于二值信号量,只是提供的API更加简单,使用的场景也更严格一些,如下所示:

  1. mutex的计数值只能为1,也就是最多只允许一个线程访问临界区

  2. 在同一个上下文中上锁和解锁

  3. 不能递归的上锁和解锁

  4. 持有个mutex时,进程不能退出

  5. mutex不能在中断或者下半部中使用,也就是mutex只能在进程上下文中使用

  6. mutex只能通过官方API来管理,不能自己写代码操作它

在面对互斥体和信号量的选择时,只要满足互斥体的使用场景就尽量优先使用互斥体。

在面对互斥体和自旋锁的选择时,参见下表:

 

7、完成变量

完成变量的机制类似于信号量,比如一个线程A进入临界区之后,另一个线程B会在完成变量上等待,线程A完成了任务出了临界区之后,使用完成变量来唤醒线程B。

一般在2个任务需要简单同步的情况下,可以考虑使用完成变量。

8、大内核锁

大内核锁已经不再使用,只存在与一些遗留的代码中。

9、 顺序锁

顺序锁为读写共享数据提供了一种简单的实现机制。之前提到的读写自旋锁和读写信号量,在读锁被获取之后,写锁是不能再被获取的,也就是说,必须等所有的读锁释放后,才能对临界区进行写入操作。

顺序锁则与之不同,读锁被获取的情况下,写锁仍然可以被获取。使用顺序锁的读操作在读之前和读之后都会检查顺序锁的序列值,如果前后值不符,则说明在读的过程中有写的操作发生,那么读操作会重新执行一次,直至读前后的序列值是一样的。

顺序锁优先保证写锁的可用,所以适用于那些读者很多,写者很少,且写优于读的场景。

10、禁止抢占

其实使用自旋锁已经可以防止内核抢占了,但是有时候仅仅需要禁止内核抢占,不需要像自旋锁那样连中断都屏蔽掉。

这时候就需要使用禁止内核抢占的方法了:

这里的preempt_disable()和preempt_enable()是可以嵌套调用的,disable和enable的次数最终应该是一样的。

11、顺序和屏障

对于一段代码,编译器或者处理器在编译和执行时可能会对执行顺序进行一些优化,从而使得代码的执行顺序和我们写的代码有些区别。

一般情况下,这没有什么问题,但是在并发条件下,可能会出现取得的值与预期不一致的情况。

在某些并发情况下,为了保证代码的执行顺序,引入了一系列屏障方法来阻止编译器和处理器的优化。

举例如下:

void thread_worker()
{
    a = 3;
    mb();
    b = 4;
}
 

上述用法就会保证 a 的赋值永远在 b 赋值之前,而不会被编译器优化弄反。在某些情况下,弄反了可能带来难以估量的后果。

12、总结

本节讨论了大约11种内核同步方法,除了大内核锁已经不再推荐使用之外,其他各种锁都有其适用的场景。

了解了各种同步方法的适用场景,才能正确的使用它们,使我们的代码在安全的保障下达到最优的性能。

同步的目的就是为了保障数据的安全,其实就是保障各个线程之间共享资源的安全,下面根据共享资源的情况来讨论一下10种同步方法的选择。

10种同步方法在图中分别用蓝色框标出。

最后,在此图基础上再做个总结。

上述的10多种锁中,内核中最常见的还是自旋锁,信号量和互斥锁这三种。其中在第二部分第6节中对这三种如何做出选择已经列出了一个表格,这是全文的重点!

学习内核锁的实现,有助于我们在程序设计中如何使用锁,使用什么类型的锁以及如何设计锁。

Linux内核的同步机制 一、引言         在现代操作系统里,同一时间可能有多个内核执行流在执行,因此内核其实象多进程多线程编程一样也需要一些同步机制来同步各执行单元对共享数据的访问。尤其是在多处理器系统上,更需要一些同步机制来同步不同处理器上的执行单元对共享的数据的访问。         在主流的Linux内核中包含了几乎所有现代的操作系统具有的同步机制,这些同步机制包括:原子操作、信号量(semaphore)、读写信号量(rw_semaphore)、spinlock、BKL(Big Kernel Lock)、rwlock、brlock(只包含在2.4内核中)、RCU(只包含在2.6内核中)和seqlock( 立即下载

相关推荐

ADRV9026初始化避坑指南:手把手调试PostMcsInit常见故障

本文详细解析了ADRV9026多片同步初始化过程中的PostMcsInit常见故障,包括时钟校准失败、JESD链路建立问题和ARM核通信异常等。通过实际项目经验,提供了硬件检查清单、软件配置要点和分层诊断方法,帮助工程师快速定位和解决问题,提升系统稳定性。

hadoop5ranger的博客 620

linux 如何防止进程访问内核空间,读书笔记:《Linux内核设计与实现》第五章 —— “系统调用”...

目录5.1与内核通信5.2API、POSIX和C库5.3系统调用5.4系统调用处理程序5.5实现系统调用5.6系统调用上下文在第五章中,讲述了系统调用究竟是什么?以及Linux内核如何实现系统调用,以及执行系统调用的连锁反应:陷入内核——>传递系统调用号和参数——>执行正确的系统调用函数——>把返回值带回用户空间。内核提供了用户进程与内核进行交互的一组接口,这些接口让应用程序受限...

weixin_35097346的博客 461

别再到处找包了!Keil5芯片支持包(Pack)最全管理指南:安装、更新、迁移与离线备份

本文详细解析了Keil5芯片支持包(Pack)的全生命周期管理,包括安装、更新、迁移与离线备份的工程化解决方案。针对STM32F10x等常见芯片,提供了高效获取Pack的策略、版本管理技巧及团队协作方案,帮助开发者解决常见的'Device Family Pack missing'等问题,提升嵌入式开发效率。

weixin_28729205的博客 541

Linux内核调试篇——获取内核函数地址的四种方法(一文解决)

在内核调试中,经常需要知道某个函数的地址,或者根据函数地址找到对应的函数,从而进行更深一步的debug。命令是用于查看二进制文件(如可执行文件、目标文件、库)的符号表的工具,所以可以用。由于vmlinux比较大,如果要查找某个函数的地址,需要使用grep进行过滤。内核符号表是一个映射,它将内核代码段中的地址映射到对应的函数名或全局变量名。这会返回与指定函数名匹配的符号的地址、类型和名称。等工具来查看它的符号表,从而获取函数地址。反汇编出来,得到的反汇编文件就会包含。编译出来的内核映像文件,可以通过。

youzhangjing_的博客 1870

MODIS 遥感数据批量下载(使用Cygwin)

MODIS 遥感数据批量下载(使用Cygwin)包含Cygwin的下载教程

weixin_45913084的博客 916

开源libmodbus编译为32位和64位动态库

libmodbus 是支持Linux,Mac OS X,window 的一个开源库,支持modbus TCP和RTU 两种模式。

lemontree1945的博客 1923

Linux 内核同步

Linux 内核同步是指控制多个进程按照一定的规则或顺序访问某些系统资源的机制,下面是几个关键概念1、临界区和竞争条件a.临界区:访问和操作共享数据的代码段b.竞争条件:多个执行线程在一个临界区同时执行2、死锁:每个线程都在互相等待,但它们永远不会释放占用的资源a.自死锁:一个执行线程试图去获取一个自己已经持有的锁,它不得不等待锁释放,但因为它忙于等待这个锁,所以自己永远也不会有机会释放释放锁b.ABBA死锁:每个线程都持有一把其他进程需要得到的锁。

Sofine 817

(10)Proteus 8.9上的STM32仿真系列(HAL)---freertos

实验设计:通过cubemxide生成freertos工程,然后创建一个 pc13 led灯间隔200ms闪烁的任务。非常遗憾的是proteus8.9仿真失败,实物上没有问题,但还是把流程过一遍。 一、原理图 实物是淘宝上stm32f103 c8t6的核心板,proteus上没有这个芯片,这里图上大概表示一下,用的是核心板自带的pc13引脚的led灯。 二、cubemxide配置 1.RCC如之前工程一样配置 2、配置SYS timebase Source不要使用systick,自己选择一个定时器,我这

qq_35442550的博客 7344

深度解析Linux kernel同步机制(上篇)

这里的owner实际上是task_struct的指针,也就是地址,由于task_struct的地址是L1_cache对齐的,因此实际上指针地址后三位为0,因此linux内核利用这三个比特位用于设置mutex的标志位,不影响指针地址的表示也更高效利用了冗余的比特位。MCS 的实现较为复杂,具体可参考一些内核书籍。当unlock时,不考虑等待队列的影响,则与上述类似,当且仅当之前持有锁的owner可以解锁,解锁时本来应将lock的owner置为初始0,但是这里保留了mutex的flag以便后续操作。

youzhangjing_的博客 857

保姆级教程:用STM32CubeMX配置GD32的CAN总线(含异常处理)

本文提供了一份详细的STM32CubeMX配置GD32 CAN总线开发指南,涵盖从HAL库移植到异常处理的全过程。重点解析GD32与STM32在CAN总线初始化、报文发送优先级处理等方面的关键差异,并提供优化代码维护与版本控制的实用策略,帮助开发者高效完成项目迁移。

onion的博客 830

ABB机器人C#二次开发实战:从通信打通到数据读写的落地指南(附完整工程)

最近在做自动化产线升级项目时,遇到一个核心需求:用C#上位机实时读取ABB机器人的关节角度、IO信号,同时下发运动指令和参数配置。翻遍全网,要么是Robot Studio的基础操作教程,要么是C++/VC++的老旧案例,C#相关的实操内容要么只给片段代码,要么跳过通信配置、权限设置等关键步骤,导致刚上手时踩了无数坑——连接超时、数据读不到、写入无响应,甚至误触发机器人安全保护。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1394

Linux内核深入学习 - 内核同步

在我们开始之前,先来看看内核抢占,他是我们为了解决的东西而引出来的内核同步!

charlie114514191的博客 1440

拆解歌尔2718硅麦:2.75mm超小封装背后的MEMS技术解析

本文深度解析歌尔2718硅麦的2.75mm超小封装技术,探讨MEMS麦克风在微型化过程中的声学性能与结构可靠性平衡。通过ASIC芯片堆叠、纳米级应力控制等创新技术,歌尔2718在TWS耳机和智能手机中实现卓越性能,同时克服微型化带来的声学挑战。

weixin_28292761的博客 610

Linux内核同步

目录临界区与竞争条件加锁参考资料 如果多个执行线程同时访问和操作数据,就有可能发生各线程之间互相覆盖共享数据的情况,造成被访问数据处于不一致状态,因此共享资源需要防止并发访问。 临界区与竞争条件 临界区就是访问和操作共享数据的代码段,如果两个执行线程有可能处于同一个临界区中同时执行,那么这种情况就称为竞争条件。 同步即避免并发和防止竞争条件。 加锁 参考资料 《Linux内核设计与实现(中文第三版)》 死锁面试题 进程、线程、死锁 ...

weixin_44164489的博客 685

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Linux中的内核同步源码相关总结

Linux 内核同步是保障多并发场景下共享资源访问安全的核心技术,通过原子操作、自旋锁、互斥锁、RCU 等机制,针对不同场景提供了灵活高效的解决方案。理解这些机制的适用场景和实现原理,是编写稳定内核模块和驱动程序的基础。

qq_28576837的博客 1243

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Linux内核下的同步

内核中的同步 摘自《Linux内核之旅》 内核只要存在任务交错执行,就必然会存在对共享数据的并发问题,也就必然存在对数据的保护。而内核中任务交错执行的原因归根结底还是由于内核任务调度造成的。我们下面归纳一下内核中同步的原因。 同步原因 l  中断——中断几乎可以在任何时刻异步发生,也就可能随时打断当前正在执行的代码。 l  睡眠及与用户空间的同步——在内核执行的进程可能会睡眠,这就会唤醒

raymond的专栏 1242

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

浅析Linux内核同步机制

很早之前就接触过同步这个概念了,但是一直都很模糊,没有深入地学习了解过,近期有时间了,就花时间研习了一下《linux内核标准教程》和《深入linux设备驱动程序内核机制》这两本书的相关章节。趁刚看完,就把相关的内容总结一下。为了弄清楚什么事同步机制,必须要弄明白以下三个问题: l        什么是互斥与同步? l        为什么需要同步机制? l        Linux内核提供哪

fzubbsc的专栏 6899

linux内核之内核同步

当处理多处理器之间或硬件设备之间的同步问题时,有时需要在程序中以指定的顺序发出读内存和写内存的指令(指令的指令要按照特定的顺序)。但是为了提高效率,编译器或处理器可能会对程序指令重新排序(例如,处理器在执行指令期间,会在取指令和分派时,把表面上看上去无关的指令按照自认为最好的方式排序)。在读取数据前后,序列值都会被读取,如果读取的序列值相同,则说明读操作过程中没有新的数据写入。如果在中断处理程序中使用了自旋锁,那么,在其他地方获取锁之前(例如,可以被中断的进程上下文中),需要先禁止本地中断。

抱猫人的博客 844

Linux内核同步方法

原子操作 自旋锁、读-写自旋锁 信号量:二值信号量、读-写信号量 互斥量 完成变量

瓦釜苑 673

【Linux内核】同步

内核同步介绍 1.从2.0开始,Linux开始支持多处理器 2.所谓临界区就是访问和操作共享数据的代码段 3.我们应该不让两个执行线程在同一个临界区同时执行 4.i++的机器指令步骤 得到当前变量i的值并且拷贝到一个寄存器中 将寄存器的值+1 将i的新值写会到内存中 5.内核为我们实现了一些原子操作的接口 6.一个锁被高度争用,会严重降低系统性能 7.锁争用严重时,加锁太粗不好,锁争用不严重时,加锁太细也不好,在小型机上,CPU核数较少,争用也较少,加锁太细有时也不好 1.造成并发执行的原因 在单处理器

屎蛋的铲屎官 202

Linux内核设计与实现——内核同步

内核同步 同步介绍 同步的概念 临界区:也称为临界段,就是访问和操作共享数据的代码段。 竞争条件: 2个或2个以上线程在临界区里同时执行的时候,就构成了竞争条件。 所谓同步,其实防止在临界区中形成竞争条件。 如果临界区里是原子操作(即整个操作完成前不会被打断),那么自然就不会出竞争条件。但在实际应用中,临界区中的代码往往不会那么简单,所以为了保持同步,引入了锁机制。但又会产生一些关于锁

walkerkalr的专栏 1071

Linux内核同步,进程,线程同步各种方法

Linux内核同步,进程,线程同步各种方法包括我自己在内,很多人对内核,进程,线程同步都不是很清楚,下面稍微总结一下:内核同步:主要是防止多核处理器同时访问修改某段代码,或者在对设备驱动程序进行临界区保护。主要有一下几种方式:1. Mutex(互斥)头文件:#include 初始化方法:DEFINE_MUTEX(name);或者void mutex_init(struct mutex *lock);使用方法:void mutex_lock (struct mutex *lock);Tries to lock

cainiao413的专栏 936

linux内核笔记-内核同步

linux内核就相当于不断对请求进行响应的服务器,这些请求可能来自CPU,可能来自发出中断的外部设备。我们将内核看作两种请求的侍者。   (1)老板提出请求,侍者如果空闲,为老板服务。(系统调用或异常)   (2)侍者正在无顾客服务时,老板提出请求,则转去为老板服务。(中断异常嵌套)   (3)侍者正为老板服务时,另一老板提出请求,此时转去为另一个老板服务,回头再给这个老板服务。(中断嵌套)

继续微笑lsj 1395

[内核同步]浅析Linux内核同步机制

转自:http://blog.youkuaiyun.com/fzubbsc/article/details/37736683?utm_source=tuicool&utm_medium=referral 很早之前就接触过同步这个概念了,但是一直都很模糊,没有深入地学习了解过,近期有时间了,就花时间研习了一下《linux内核标准教程》和《深入linux设备驱动程序内核机制》这两本书的相关章节...

anxuan3201的博客 125
上一篇: 11道腾讯微信面试过程的随口题,道道经典,学到就是赚到
下一篇: 【Linux内核系列】百分百干货篇丨不要错过,5个方面分析内核架构,让你对内核不再陌生
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值