zoukankan      html  css  js  c++  java
  • 10内核同步方法

    linux内核提供了一套相当完备的内核同步方法。我们将介绍它们的接口、行为及用途。

    一、原子操作

      原子操作可以保证指令以原子的方式执行——执行过程中不被打断。

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

      1.1 原子整数操作

      针对整数的原子操作只能对atomic_t类型的数据进行处理。atomic_t类型定义在<linux/types.h>中:

    1 typedef struct {
    2    volatile int counter;   
    3 } atomic_t;

       使用原子操作需要的声明都在<asm/atomic.h>中,

      定义一个atomic_t类型的数据结构方法如下所示:

    atomic_t v;  //定义v
    atomic_t u = ATOMIC_INIT(0); //定义u并将其初始化为0
    

       原子操作如下:

    atomic_set(&v,4); //v = 4 原子的
    atomic_add(2,&v); //v = v + 2 = 6 原子的
    atomic_inc(&v);  / / v = v + 1= 7; 原子的
    printk("%d
    ", aotmic_read(&v)); //打印7 将atomic_t 转换为int
    int atomic_dec_and_test(atomic_t *v) //用原子整数操作原子的执行一个操作并检查结果

       1.2 顺序性和原子性的比较

      原子性确保指令执行期间不被打断,要么全部执行完,要么根本不执行。顺序性确保两条或多条指令出现在独立的执行线程中,甚至独立的处理器上,它们本该的执行顺序却依然要保持。

      顺序性通过屏障(barrier)指令来实施。

      在编写代码时,能使用原子操作,就尽量不要使用复杂的加锁机制。

      1.3 64位原子操作

    typedef struct{
      volatile long counter;   
    }atomic64_t;

      1.4 原子位操作

      定义在<asm/bitops.h>中,位操作函数是对普通的内存地址进行操作的。它的参数是一个指针和一个位号。


    二、自旋锁

      情况:先得从一个数据结构中移出数据,然后对其进行格式转换和数据解析,最后再将其加入另一个数据结构中,整个执行过程必须是原子的,在数据被更新完毕之前不允许被其他线程访问。

      自旋锁最多只能被一个可执行线程持有;如果一个执行线程试图获得一个被已经持有的自旋锁,那么该线程就会被一直进行忙循环——旋转——等待锁重新使用。要是锁未被争用,请求锁的执行线程便可以立即获得它,继续执行。

      一个被争用的自旋锁使得请求它的线程在等待锁重新可用时自旋(特别浪费处理时间),且持有自旋锁的时间最好小于完成两次上下文切换的消耗。

      1.4 自旋锁方法

      接口定义于<linux/spinlock.h>中,自旋锁的基本使用形式如下:

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

       一个时刻只有一个线程位于临界区内,linux内核实现的自旋锁是不可递归的,所以如果你试图获取一个你正持有的锁,你必须自旋,等待你自己释放这个锁;

      内核提供的进制中断同时请求锁的接口,如下所示:

      

      

  • 相关阅读:
    AOP-面向切面编程-1
    记一次付工解决Sqlserver问题的过程
    Mysql ---Sqlserver数据迁移到Mysql(Mysql建表迁移数据)
    Mysql ---部署,创建用户
    【C++】C++未定义行为
    【C++】回看面向对象与C++
    【作业】2017级面向对象程序设计——总结作业
    【笔记】Cocos2dx学习笔记
    【个人】绝地求生—吃豆人
    【团队】汇总博客
  • 原文地址:https://www.cnblogs.com/ccpang/p/11757051.html
Copyright © 2011-2022 走看看