os临界区保护(critical region)以及mutex原理

什么是临界区保护?

临界区(critical region)是指一段特定的代码行为集合,其中可能包括对数据的修改,执行一段特定逻辑等等。

临界区的概念是因为并发编程(multiprogram)的出现导致的,当出现多个task、多个cpu、甚至网络中多个服务器对同一个逻辑对象操作时,就会有条件竞争出现,如果设对该逻辑对象的操作为A,此时必须对A做特殊保护,约定对这A的这种特殊保护统称为临界区保护(mutex exclue),称A操作的范围为临界区。

临界区不保护会出现什么问题?

举例说明,假设有两个task都执行如下代码:

// p is a global var
// ...
    if (p == NULL) {
        p = malloc(N);
    }
// .do some thing
    free(p);

这里至少有两个问题:

  • 假设任务1和任务2都同步走到判断p是否为NULL的语句,两个任务均判断p为NULL,接着1先分配内存,紧接着2又重新给p分配内存,导致1任务内存泄漏
  • 1任务内存泄漏后p实际指向b任务分配区域,此时1释放p会导致2中不可预期的错误,比如访问0地址

因此在这段代码前后都应作为临界区保护

临界区保护的原理

临界区保护有多种思路,比如可以重新设计任务改造为无锁算法、比如设计任务之间的执行顺序令不会出现同时访问临界区的情况等,但通用的思路一般是在令任务对临界区访问实现互斥,这种思路称为mutex锁。
mutex主要就2种操作,分别是加锁和解锁,我们这里设为P和V操作,那么上述代码应该改为

// p is a global var
// ...
    P(m);
    if (p == NULL) {
        p = malloc(N);
    }
// .do some thing
    free(p);
    V(m);

假设已经实现了P\V接口,则当任务1先获取锁P(m)成功后,此时如果任务2再获取P(m)会发生失败,系统会保证只有任务1释放锁后任务2才可以P成功并进入临界区。
那么mutex接口具体怎么实现呢?

mutex锁的实现原理

mutex锁的原理核心主要两个部分,分别是

  • 原子地判断并设置标志位
  • 对判断结果的处理策略

这两个部分的具体实现在单核和多核平台、有无cache情况下又有较大区别,这里我们先以单核无cache为例说明

原子地判断并置位标志位

这里的标志位本身可以是一个普通内存变量,对于临界区保护而言只需要标志位有两个状态,比如0代表未被上锁,1代表已上锁,只是这里需要注意地是这个过程必须是”原子“的,假设我们这样实现P操作

    // Wrong mutex implement!
    bool P(mutex m)
    {
        if (m == 0) {
            m = 1;
            return true;
        }
        return false;
    }

敏锐的读者应该发现这个方式很显然行不通,原因和上面的例子一样,因为可能出现两个任务同步进入判断m是否为0的语句,同时获取到锁,也就没有起到保护作用。
分析起来根本原因就是mutex标志位的判断本身应该是原子性不可分割的,对于单核平台而言,只需要实现这个过程种没有发生调度切到其他任务即可,一般可以通过关中断实现,

    // not complete mutex implement!
    bool P(mutex m)
    {
        LockInt();  // key step! ensure atomic!
        if (m == 0) {
            m = 1;
            UnLockInt();
            return true;
        }
        UnLockInt();
        return false;
    }

这样便保证了mutex的持有与否的判断是可用的了,但实际上这个实现还是有问题,这个就是对这个判断结果如何处理

对判断结果的处理策略

如果获取到锁,自然是继续往下执行。但如果获取不到锁应该如何处理呢?mutex以及各种变形的具体实现的差异主要就在这里,总体上,分为两种策略 switch/spin

  • switch 策略
    如果获取不到锁,则立刻把当前任务挂起,或者直接切换到其他任务,一般可以在mutex变量里维持一个链表,将未获取到锁的任务挂起并附在这个链表上,一旦已经持有锁的任务释放锁,就会检查这个链表上的任务并唤醒。这样好处是cpu运行效率更高,但任务切换本身有开销,如果对于临界区本身执行时间很短的情况下会造成性能下降

  • spin 策略
    spin,自旋,顾名思义就是当获取不到锁的时候,立刻或者隔一段时间再询问是否获取锁,反复如此直到能够获取到锁,实际上这种策略下一般称为spinlock,而且往往只能用于多核平台,想象一下如果单核平台CPU始终被某任务占据始终轮询锁的标志位,那么实际持有锁的任务无法得到调度也就无法释放锁,便造成死锁。
    这种策略由于没有调度开销对于多核平台会有更高效率,但如果临界区时间较长,会造成CPU被浪费大量时钟只用于轮询,造成CPU利用率的下降

进一步延生

以上只涉及到mutex以及各种变形实现的一个极其简化的基础框架,其中尤其涉及到对锁标志位的原子判断和处理策略在多核平台下有大量的实现方式和研究成果,后面有机会会再整理详述

如果希望阅读os对mutex的源码实现的朋友,建议先读一些RTOS的实现,其原理和思想与linux非常接近,而linux本身需要适配的场景和平台太多,有太多与核心思想无关的代码,尤其是各种适配宏,没有实现理解者很难读。

TIP 打个广告,本人作为开源操作系统Liteos的内核开发组人员,欢迎大家在github上下载使用!
liteos一个开源IOT系统

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容