Linux内核同步方法(一)

简介: 版权声明:您好,转载请留下本人博客的地址,谢谢 https://blog.csdn.net/hongbochen1223/article/details/49101259 LInux...
版权声明:您好,转载请留下本人博客的地址,谢谢 https://blog.csdn.net/hongbochen1223/article/details/49101259

LInux内核提供了一组相当完备的同步方法.

(一):原子操作

原子操作是其他同步方法的基石.原子操作可以保证指令以原子的方式执行--执行过程不被打断.原子原本是指不可分割的微粒,所以,原子操作也就是不能够被分割的指令.两个原子操作绝对不可能并发的访问同一个变量.

内核提供了两组原子操作接口--一组针对整数的操作,另一组针对单独的位进行操作.在Linux支持的所有体系结构上都实现了这两组接口.大多数体系结构会提供支持原子操作的简单算术指令.

(1):原子整数操作

针对整数的原子操作只能对atomic_t类型的数据进行处理.在这里之所以引入了一个特殊的数据类型,而没有直接使用C语言的int类型,主要是出于两个原因:首先,让原子函数只接收atomic_t类型的操作数,可以确保原子操作只与这种特殊类型数据一起使用.同时,这也保证了该类型的数据不会被传递给任何非原子函数.其次,使用atomic_t类型确保编译器不对相应的值进行访问优化--这点使得原子操作最终接收到正确的内存地址,而不只是一个别名.最后,在不同体系结构上实现原子操作的时候,使用atomic_t可以屏蔽其间的差异.atomic_t类型定义在

typedef struct {
    volatile int counter;
} atomic_t;

#ifdef CONFIG_64BIT

typedef struct {
    volatile long counter;
} atomic64_t;
#endif

尽管Linux支持的所有机器上的整数数据都是32位的,但是使用atomic_t的代码只能将该类型的数据当做24位来使用.这个限制完全是因为在APARC体系结构上,原子操作的实现不同于其他体系结构:32位int类型的低8位被嵌入了一个锁,因为SPARC体系结构对原子操作缺乏指令级支持,所以只能利用该锁来避免对原子类型数据的并发访问.所以在SPARC机器上就只能使用24位了.虽然其他机器上的代码完全可以使用全部的32位,但是在SPARC机器上却可能会造成一些奇怪和微妙的错误.不过,最近SPARC可能已经支持32位的atomic_t了.

这里写图片描述

使用原子操作需要的声明都在asm/atomic.h文件中.有些体系结构会提供一些只能在该体系结构上使用的额外原子操作方法,但是所有的体系结构都能保证内核使用到的所有操作的最小集.在编写内核代码的时候,可以肯定,这个最小集合在所有的体系结构上都已经实现了.

定义一个atomic_t类型的数据方法很平常,还可以在定义的时候给他设定初值.

原子整数操作最常见的用途就是实现计数器.使用复杂的锁机制来保护一个单纯的计数器显然是杀鸡用了宰牛刀.所以,对于开发者来说,最好使用atomic_inc()和atomic_dec()这两个相对来说轻便一点的操作.

还可以用原子整数操作原子的执行一个操作并检查结果.一个常见的例子就是原子的减操作和检查.

int atomic_dec_and_test(atomic_t *v)

这个函数将给定的原子变量减1,如果结果为0,就返回真,否则结果返回假.某种特定的体系结构上是实现的所有操作可以在文件asm/atomic.h文件中找到.

我已经在我的另外一篇博客中讲述了该头文件,比较详细,可以看一下.

原子操作通常是内联函数,往往是通过内联汇编指令来实现的.如果某个函数本来就是原子的,那么他往往被定义成一个宏.例如,在大部分体系结构上,读取一个字本身就是原子操作,也就是说,在对一个字进行写入操作期间不可能完成对该字的读取.这样,把atomic_read()定义成一个宏,只须返回ztomic_t类型的整数值就可以了.

原子性和顺序性是不一样的.原子性确保指令执行期间不被打断,要么全部执行完,要么根本不执行.另一方面,顺序性确保即使两条或多条指令出现在独立的执行线程中,甚至独立的机器上,他们本该的执行顺序却依然要保持.

(2):64位原子操作

64位的原子操作是对长整型的一个封装,如果要使用64位的原子变量,则要使用atomic64_t,使用的方法和32位是一样的.

(3):原子位操作

除了原子整数操作以外,内核也提供了针对位这一级数据进行操作的函数.他们是与体系结构相关的操作,定义在文件asm/bitops.h中.

其中位操作函数是对普通的内存地址进行操作的.他的参数是一个指针和一个位号,第0位是给定地址的最低有效位,第31位是给定地址的最高有效位,第32位是下一个字的最低有效位.虽然,使用原子位操作在多数情况下是对一个字长的内存进行访问,因而位号应该位于0~31之间(64位是0~63),但是,对位号的范围并没有限制.

由于原子位操作是对普通的指针进行的操作,所以不像原子整型对应atomic_t,这里没有特殊的数据类型.相反,只要指针指向了任何你希望的数据,你就可以对他进行操作.

内核还提供了一组对于位的非原子操作.非原子函数和原子函数的操作完全相同.但是,前者不保证原子性,且其名字前缀多两个下划线.例如,与test_bit()相对应的非原子函数为__test_bit().如果你不需要原子操作(比如说,你已经用锁保护了自己的数据),那么这些非原子的位函数比原子的位函数可能会执行的快一些.

内核还提供了两个例程用来从指定的地址开始搜索第一个被设置的(或未被设置的)位:

int find_first_bit(unsigned long *addr,unsigned int size);
int find_first_zero_bit(unsigned long *addr,unsigned int size);

这两个函数中第一个参数是一个指针,第二个参数是要搜索的总位数.返回值分别是第一个被设置的(或没被设置)的位的位号.如果你的搜索范围仅限一个字,使用_ffs()和ffz()这两个函数更好,他们只需要给定一个要搜索的地址做参考.

 未完,待续----  

目录
相关文章
|
10天前
|
算法 Linux 调度
深入理解Linux内核调度器:从基础到优化####
本文旨在通过剖析Linux操作系统的心脏——内核调度器,为读者揭开其高效管理CPU资源的神秘面纱。不同于传统的摘要概述,本文将直接以一段精简代码片段作为引子,展示一个简化版的任务调度逻辑,随后逐步深入,详细探讨Linux内核调度器的工作原理、关键数据结构、调度算法演变以及性能调优策略,旨在为开发者与系统管理员提供一份实用的技术指南。 ####
44 4
|
14天前
|
缓存 算法 Linux
深入理解Linux内核调度器:公平性与性能的平衡####
真知灼见 本文将带你深入了解Linux操作系统的核心组件之一——完全公平调度器(CFS),通过剖析其设计原理、工作机制以及在实际系统中的应用效果,揭示它是如何在众多进程间实现资源分配的公平性与高效性的。不同于传统的摘要概述,本文旨在通过直观且富有洞察力的视角,让读者仿佛亲身体验到CFS在复杂系统环境中游刃有余地进行任务调度的过程。 ####
35 6
|
4天前
|
算法 Linux 开发者
Linux内核中的锁机制:保障并发控制的艺术####
本文深入探讨了Linux操作系统内核中实现的多种锁机制,包括自旋锁、互斥锁、读写锁等,旨在揭示这些同步原语如何高效地解决资源竞争问题,保证系统的稳定性和性能。通过分析不同锁机制的工作原理及应用场景,本文为开发者提供了在高并发环境下进行有效并发控制的实用指南。 ####
|
12天前
|
缓存 资源调度 安全
深入探索Linux操作系统的心脏——内核配置与优化####
本文作为一篇技术性深度解析文章,旨在引领读者踏上一场揭秘Linux内核配置与优化的奇妙之旅。不同于传统的摘要概述,本文将以实战为导向,直接跳入核心内容,探讨如何通过精细调整内核参数来提升系统性能、增强安全性及实现资源高效利用。从基础概念到高级技巧,逐步揭示那些隐藏在命令行背后的强大功能,为系统管理员和高级用户打开一扇通往极致性能与定制化体验的大门。 --- ###
39 9
|
11天前
|
缓存 负载均衡 Linux
深入理解Linux内核调度器
本文探讨了Linux操作系统核心组件之一——内核调度器的工作原理和设计哲学。不同于常规的技术文章,本摘要旨在提供一种全新的视角来审视Linux内核的调度机制,通过分析其对系统性能的影响以及在多核处理器环境下的表现,揭示调度器如何平衡公平性和效率。文章进一步讨论了完全公平调度器(CFS)的设计细节,包括它如何处理不同优先级的任务、如何进行负载均衡以及它是如何适应现代多核架构的挑战。此外,本文还简要概述了Linux调度器的未来发展方向,包括对实时任务支持的改进和对异构计算环境的适应性。
32 6
|
12天前
|
缓存 Linux 开发者
Linux内核中的并发控制机制:深入理解与应用####
【10月更文挑战第21天】 本文旨在为读者提供一个全面的指南,探讨Linux操作系统中用于实现多线程和进程间同步的关键技术——并发控制机制。通过剖析互斥锁、自旋锁、读写锁等核心概念及其在实际场景中的应用,本文将帮助开发者更好地理解和运用这些工具来构建高效且稳定的应用程序。 ####
31 5
|
12天前
|
算法 Unix Linux
深入理解Linux内核调度器:原理与优化
本文探讨了Linux操作系统的心脏——内核调度器(Scheduler)的工作原理,以及如何通过参数调整和代码优化来提高系统性能。不同于常规摘要仅概述内容,本摘要旨在激发读者对Linux内核调度机制深层次运作的兴趣,并简要介绍文章将覆盖的关键话题,如调度算法、实时性增强及节能策略等。
|
13天前
|
存储 监控 安全
Linux内核调优的艺术:从基础到高级###
本文深入探讨了Linux操作系统的心脏——内核的调优方法。文章首先概述了Linux内核的基本结构与工作原理,随后详细阐述了内核调优的重要性及基本原则。通过具体的参数调整示例(如sysctl、/proc/sys目录中的设置),文章展示了如何根据实际应用场景优化系统性能,包括提升CPU利用率、内存管理效率以及I/O性能等关键方面。最后,介绍了一些高级工具和技术,如perf、eBPF和SystemTap,用于更深层次的性能分析和问题定位。本文旨在为系统管理员和高级用户提供实用的内核调优策略,以最大化Linux系统的效率和稳定性。 ###
|
12天前
|
Java Linux Android开发
深入探索Android系统架构:从Linux内核到应用层
本文将带领读者深入了解Android操作系统的复杂架构,从其基于Linux的内核到丰富多彩的应用层。我们将探讨Android的各个关键组件,包括硬件抽象层(HAL)、运行时环境、以及核心库等,揭示它们如何协同工作以支持广泛的设备和应用。通过本文,您将对Android系统的工作原理有一个全面的认识,理解其如何平衡开放性与安全性,以及如何在多样化的设备上提供一致的用户体验。
|
12天前
|
缓存 运维 网络协议
深入Linux内核架构:操作系统的核心奥秘
深入Linux内核架构:操作系统的核心奥秘
30 2
下一篇
无影云桌面