zoukankan      html  css  js  c++  java
  • linux并发控制之原子操作

    原子操作指的是在执行过程中不会被别的代码路径所中断的操作。
    分为两类:整型原子操作 和 位原子操作。
    特点:
    1.任何情况下操作都是原子的。
    2.都依赖底层的CPU的原子操作来实现,所以和CPU架构密切相关。

    注意:
        1.原子操作在不同体系架构实现的方法不同,基本采用汇编实现
        2.上述的整数原子函数集仅针对32位,内核中关于64位有另一套函数
        3.对于SMP系统,内核还提供了local_t数据类型,实现对单个CPU的整数原子操作,接口函数仅将atomic_替换成local_即可,定义于linux/asm-generic/local.h

    一.整型原子操作
    定义于#include<asm/atomic.h>
    分为 定义,获取,加减,测试,返回。

    void atomic_set(atomic_t *v,int i);    //设置原子变量v的值为i
    atomic_t v = ATOMIC_INIT(0);     //定义原子变量v,并初始化为0;

    atomic_read(atomic_t* v);     //返回原子变量v的值;

    void atomic_add(int i, atomic_t* v);     //原子变量v增加i;
    void atomic_sub(int i, atomic_t* v);    

    void atomic_inc(atomic_t* v);     //原子变量增加1;
    void atomic_dec(atomic_t* v);     

    int atomic_inc_and_test(atomic_t* v);        //先自增1,然后测试其值是否为0,若为0,则返回true,否则返回false;
    int atomic_dec_and_test(atomic_t* v);        
    int atomic_sub_and_test(int i, atomic_t* v);     //先减i,然后测试其值是否为0,若为0,则返回true,否则返回false;
    注意:只有自加,没有加操作

    int atomic_add_return(int i, atomic_t* v);   //v的值加i后返回新的值;
    int atomic_sub_return(int i, atomic_t* v);  
    int atomic_inc_return(atomic_t* v);     //v的值自增1后返回新的值;
    int atomic_dec_return(atomic_t* v);    

    二.位原子操作
    定义于#include<asm/bitops.h>
    分为 设置,清除,改变,测试

    void set_bit(int nr, volatile void* addr);        //设置地址addr的第nr位,所谓设置位,就是把位写为1;
    void clear_bit(int nr, volatile void* addr);      //清除地址addr的第nr位,所谓清除位,就是把位写为0;

    void change_bit(int nr, volatile void* addr);     //把地址addr的第nr位反转;

    int test_bit(int nr, volatile void* addr);    //返回地址addr的第nr位;

    int test_and_set_bit(int nr, volatile void* addr);    //测试并设置位;若addr的第nr位非0,则返回true; 若addr的第nr位为0,则返回false;
    int test_and_clear_bit(int nr, volatile void* addr);    //测试并清除位;
    int test_and_change_bit(int nr, volatile void* addr);    //测试并反转位;
    上述操作等同于先执行test_bit(nr,voidaddr)然后在执行xxx_bit(nr,voidaddr)

    举个简单例子:
    为了实现设备只能被一个进程打开,从而避免竞态的出现

    static atomic_t scull_available = ATOMIC_INIT(1);      //init atomic

    在scull_open 函数和scull_close函数中:

    int scull_open(struct inode *inode, struct file *filp)
    {
        struct scull_dev *dev;         // device information

        dev = container_of(inode->i_cdev, struct scull_dev, cdev);
        filp->private_data = dev;         // for other methods 
        if(!atomic_dec_and_test(&scull_available)){
            atomic_inc(&scull_available);
            return -EBUSY;
        }
        return 0;         // success 
    }

    int scull_release(struct inode *inode, struct file *filp)
    {
        atomic_inc(&scull_available);
        return 0;
    }

    同样也可以用位原子操作实现
  • 相关阅读:
    Unity 3(一):简介与示例
    MongoDB以Windows Service运行
    动态SQL中变量赋值
    网站发布IIS后堆栈追踪无法获取出错的行号
    GridView Postback后出错Operation is not valid due to the current state of the object.
    Visual Studio 2010 SP1 在线安装后,找到缓存在本地的临时文件以便下次离线安装
    SQL Server 问题之 排序规则(collation)冲突
    IIS 问题集锦
    linux下安装mysql(ubuntu0.16.04.1)
    apt-get update 系列作用
  • 原文地址:https://www.cnblogs.com/hehehaha/p/6332964.html
Copyright © 2011-2022 走看看