专栏首页裸机思维漫谈C变量——天然原子性是怎么回事?

漫谈C变量——天然原子性是怎么回事?

【写在前面的话】

在20世纪初叶,人们曾经一度认为原子是物质的最小组成单位,原子不可再分。虽然很快人们就发现这是一个谬误——原子不仅可以再分,由质子、中字、电子组成,事实上这些微观粒子仍然是可以继续分割的——但计算机科学借用了“原子不可再分”的说法,提出了操作原子性(Atomicity)的概念,即:

对一个由多个步骤构成的操作来说,如果当步骤执行时不能够被打断,我们就说该操作具有原子性——是一个原子操作;反之该操作不具备原子性,不是原子操作。

简单来说,所谓原子操作就是当这个操作执行的时候,其他任务没法打断它,就好像原子无法再分一样——如果存在任务有能力将当前的操作从中间一刀切开,我们就说这个操作不是原子操作。很容易想到,当多个任务共享统一资源时,对资源访问操作的原子性是非常值得讨论的。

【从理解天然原子性开始】


通常我们所说的一个内核是8位、16位还是32位并不是指地址总线的宽度,而是ALU操作数的位宽,习惯上又称之为字长。对8位机来说,ALU一次可以进行8位运算,当我们针对一个32位的数据进行操作时就要拆成4次。对32位机来说,ALU一次就可以完成32位的运算。比较二者的区别,除了操作次数不同以外还隐含着原子性的信息,即对8位机来说,操作32位数据要分4个步骤来完成,这期间如果发生中断/异常,操作是会被打断的,因此不具备原子性;对32位机来说,由于ALU一次运算的过程是不可打断的,因而针对32位数据的运算天然具有原子性,我们称之为天然原子性。

ALU对相同字长数据的处理具有天然原子性。也就是说,16位机对16位数据的处理具有天然原子性;64位机对64位数据的处理具有天然原子性。实际应用中,天然原子性的体现还要受到数据读写对齐方式的限制:为了提升效率,总线往往规定,数据的读写地址需要对齐到数据的宽度,比如对16位数据的读写,其目标地址必须对齐到双字节;对32位数据的读写,其地址必须对齐到四字节。当且仅当数据的地址对齐到数据的宽度时,天然原子性才能得到表达。

以32位机为例,对于图1所示的情形,由于32位数据的地址并未对齐到字,内核会将针对该数据的读写拆解成四个步骤:1)针对变量的第一个字节(8位)发起一个8位的读取;2)针对变量的第二和第三个字节发起一个16位的读取(它们正好对齐到了半字);3)针对变量的最后一个字节发起一个8位的读取;4)最后将三次获得的结果合并成一个完整的32位数据——针对该变量的操作由多个步骤构成,且中途有可能被打断,因而不具备原子性。

基于同样的原因,很多编译器为了提高内核的访问效率,在默认情况下,对结构体的变量采取了同样的策略——每个成员的地址都各自对齐到了与自己类型相同大小的位置上(如图2所示)——具体内容可以通过阅读《漫谈C变量——对齐》系列文章来了解,这里就不再赘述。

实际上,很多处理器的的ALU不光对相同字长数据的访问具有天然原子性,对小于这一字长的数据类型也具有天然原子性。比如Cortex-M的ALU不光对32位的整型变量的访问具有原子性,对16位甚至是8位变量的访问也具有原子性。事实上,这一特性对很多8位机、16位机和64位机都一样适用。基于这一特性,我们基本上可以放心的认为uint8_t和int8_t在几乎所有8位及其以上的系统中都是具有天然原子性的——原因很简单,不光因为8bit的宽度小于等于ALU的宽度,还因为,8bit的对齐方式是字节、在所有支持单字节访问的Memory系统中,基本上可以认为是永远对齐的。这就是为什么布尔类型(bool)几乎在所有的平台中都“可以”被定义为8bit(uint8_t)。

那么,是不是一个变量拥有了“天然原子性”,当多个任务都要对其发起访问时,我们就可以高枕无忧了呢?答案是否定的。关于这一点,我们将在下篇文章中把每一种情况都列举出来——详细的为您分析和展开。

本文分享自微信公众号 - 裸机思维(bare-metal),作者:GorgonMeducer 傻孩子

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-07-01

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 漫谈C变量——对齐 (1)

      谈起变量的访问(Access)就不得不谈到对齐(Alignment)的概念;谈论对齐,离开具体的计算机架构又会显得缺乏支撑,如同谈论空中楼阁一般。今天我们就...

    GorgonMeducer 傻孩子
  • 【编译器玄学研究报告】后续跟踪(1)——诈尸和翻车

    在前几期的【编译器玄学报告】中,我们分别介绍了armcc和armclang的一些比较“阴间”的坑——有些是编译器的bug,有一些就单纯只是C语法上的一些陷阱而已...

    GorgonMeducer 傻孩子
  • 什么?Arm放弃了自家的汇编语法?改投GNU了?

    那么多对于我们初学者来说要学习哪种风格呢?答案是肯定的,学习GNU风格的汇编代码,因为做Linux驱动开发必须掌握的linux内核、uboot,而这两个软件就是...

    GorgonMeducer 傻孩子
  • Nature子刊:科学家用氯原子存储数据,AI硬件技术迎大飞跃

    【新智元导读】原子储存技术又获突破,荷兰科学家在昨天发表于 Nature Nanotechnology 的论文中报告了研究成果,通过快速精准地操纵铜板上的氯原子...

    新智元
  • 开发工具总结(1)之图文并茂全面总结上百个AS好用的插件(上)

    俗话说得好,工欲善其事,必先利其器。做开发时间长了,总想找一些快捷方法,只有拥有好用的工具,才能节省开发时间,提高工作效率。我就是一个 追(喜)求(欢)高(偷)...

    AWeiLoveAndroid
  • 大数据新机遇,教育系统将建设完整安全体系

    随着网络规模的扩大,Web应用承载的业务系统越来越复杂,Web系统也受到越来越多的攻击和威胁。大数据时代,网络安全也直接影响到每一个用户的个人信息安全,但是大数...

    安恒信息
  • 观点 | 深度学习,先跟上再说

    作者 | 孟岩 H是我认识的一个互联网老炮,十多年前 Web 2.0 刚刚兴起的时候,他做了几个创业项目,基本上都是 Copy 2 China 类型的,虽然没有...

    AI科技大本营
  • 如何针对数据不平衡做处理?

    无论是做比赛还是做项目,都会遇到一个问题:类别不平衡。这与 数据分布不一致所带来的影响不太一样,前者会导致你的模型在训练过程中无法拟合所有类别的数据,也就是会弄...

    代码医生工作室
  • 使用 shadow DOM [MDN教程]

    Web components的一个重要特性是封装——可以将html标签结构、css样式和行为隐藏起来,并从页面上的其他代码中分离开来,这样不同的功能不会混在一起...

    Jean
  • java源码之二叉查找树与二叉平衡树

    二叉排序树(Binary Sort Tree),又称为二叉查找树。它或者是一棵空树,或者是具有下列性质的二叉树:

    Java阿呆

扫码关注云+社区

领取腾讯云代金券