定义在头文件asm/atomic.h中;
原子操作指的是在执行过程中不会被别的代码路径所打断的操作;
Linux内核提供了一系列的函数来实现内核中的原子操作,这些函数又分为两类,分别针对位变量和整型变量进行原子操作;它们的共同点是:在任何情况下操作都是原子的,内核代码可以安全地调用它们而不会被打断;位变量和整型变量的原子操作都依赖于底层CPU的原子操作来实现,因此所有这些函数都是与CPU架构密切相关;
使用原子变量的操作,可以使设备最多只能被一个进程打开;
一、整型原子变量操作
1).设置原子变量的值:
void atomic_set(atomic_t* v, int i); //设置原子变量v的值为i;
atomic_t v = ATOMIC_INIT(0); //定义原子变量v,并初始化为0;
2).获取原子变量的值:
atomic_read(atomic_t* v); //返回原子变量v的值;
3).原子变量加/减:
void atomic_add(int i, atomic_t* v); //原子变量v增加i;
void atomic_sub(int i, atomic_t* v); //原子变量v减少i;
4).原子变量自增/自减:
void atomic_inc(atomic_t* v); //原子变量增加1;
void atomic_dec(atomic_t* v); //原子变量自减1;
5).操作并测试:
int atomic_inc_and_test(atomic_t* v);        //先自增1,然后测试其值是否为0,若为0,则返回true,否则返回false;
int atomic_dec_and_test(atomic_t* v);        //先自减1,然后测试其值是否为0,若为0,则返回true,否则返回false;
int atomic_sub_and_test(int i, atomic_t* v); //先加i,然后测试其值是否为0,若为0,则返回true,否则返回false;
6).操作并返回:
int atomic_add_return(int i, atomic_t* v);   //v的值加i后返回新的值;
int atomic_sub_return(int i, atomic_t* v);   //v的值减i后返回新的值;
int atomic_inc_return(atomic_t* v); //v的值自增1后返回新的值;
int atomic_dec_return(atomic_t* v); //v的值自减1后返回新的值;
二、位原子变量操作
1).设置/清除位:
void set_bit(int nr, volatile void* addr);    //设置地址addr的第nr位,所谓设置位,就是把位写为1;
void clear_bit(int nr, volatile void* addr);  //清除地址addr的第nr位,所谓清除位,就是把位写为0;
2).改变位:
void change_bit(int nr, volatile void* addr); //把地址addr的第nr位反转;
3).测试位:
int test_bit(int nr, volatile void* addr);    //返回地址addr的第nr位;
4).测试并操作位:
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);  //测试并清除位;若addr的第nr位非0,则返回true; 若addr的第nr位为0,则返回false;
int test_and_change_bit(int nr, volatile void* addr); //测试并反转位;若addr的第nr位非0,则返回true; 若addr的第nr位为0,则返回false;
注意:位变量的操作函数中的参数nr的取值从0开始计算:[0,7]或[0,15]或[0,31]或[0,63];
例子:
#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/jiffies.h>
#include <linux/delay.h>

//这三个头文件与内核线程的使用有关;
#include <linux/sched.h>
#include <linux/kthread.h>
#include <linux/err.h>

//原子操作相关
#include <asm/atomic.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("*************");
MODULE_VERSION("2.6.35.000");

static int sleep_time = (1*10*HZ);
static atomic_t shared_res;
static unsigned int bit_var = 3;

//STEP5:实现线程函数
static int thread_process1(void* param)
{
  int val = 0, ret = 0;
  while(1)
  {
    set_current_state(TASK_UNINTERRUPTIBLE);

if(kthread_should_stop())
    {
      printk("kernel thread '%s' should stop;file:%s;line:%d\n", __FUNCTION__, __FILE__, __LINE__);
      break;
    }

set_bit(0, (volatile void*)&bit_var);
    printk("%s: set bit_var = %u;\n", __FUNCTION__, bit_var);

clear_bit(0, (volatile void*)&bit_var);
    printk("%s: clear bit_var = %u;\n", __FUNCTION__, bit_var);

//atomic_add(1, &shared_res);
    //val = atomic_read(&shared_res);
    //val = atomic_add_return(1, &shared_res);
    //val = atomic_inc_return(&shared_res);
    ret = atomic_inc_and_test(&shared_res);
    val = atomic_read(&shared_res);
    printk("%s: shared resource = %d, true=%d;\n%s", __FUNCTION__, val, ret, ((val % 3) ? "" : "\n"));

mdelay(sleep_time);
  }
  return 123;
};

static int thread_process2(void* param)
{
  int val = 0, ret = 0;
  while(1)
  {
    set_current_state(TASK_UNINTERRUPTIBLE);

if(kthread_should_stop())
    {
      printk("kernel thread '%s' should stop;file:%s;line:%d\n", __FUNCTION__, __FILE__, __LINE__);
      break;
    }

set_bit(0, (volatile void*)&bit_var);
    printk("%s: set bit_var = %u;\n", __FUNCTION__, bit_var);

clear_bit(0, (volatile void*)&bit_var);
    printk("%s: clear bit_var = %u;\n", __FUNCTION__, bit_var);

//atomic_add(1, &shared_res);
    //val = atomic_read(&shared_res);
    //val = atomic_add_return(1, &shared_res);
    //val = atomic_inc_return(&shared_res);
    ret = atomic_inc_and_test(&shared_res);
    val = atomic_read(&shared_res);
    printk("%s: shared resource = %d, true=%d;\n%s", __FUNCTION__, val, ret, ((val % 3) ? "" : "\n"));

msleep(sleep_time);
  }
  return 456;
};

static int thread_process3(void* param)
{
  int val = 0, ret = 0;
  while(1)
  {
    set_current_state(TASK_UNINTERRUPTIBLE);

if(kthread_should_stop())
    {
      printk("kernel thread '%s' should stop;file:%s;line:%d\n", __FUNCTION__, __FILE__, __LINE__);
      break;
    }

set_bit(0, (volatile void*)&bit_var);
    printk("%s: set bit_var = %u;\n", __FUNCTION__, bit_var);

clear_bit(0, (volatile void*)&bit_var);
    printk("%s: clear bit_var = %u;\n", __FUNCTION__, bit_var);

//atomic_add(1, &shared_res);
    //val = atomic_read(&shared_res);
    //val = atomic_add_return(1, &shared_res);
    //val = atomic_inc_return(&shared_res);
    ret = atomic_inc_and_test(&shared_res);
    val = atomic_read(&shared_res);
    printk("%s: shared resource = %d, true=%d;\n%s", __FUNCTION__, val, ret, ((val % 3) ? "" : "\n"));

msleep(sleep_time);
  }
  return 789;
};

static struct task_struct* my_thread1 = NULL;
static struct task_struct* my_thread2 = NULL;
static struct task_struct* my_thread3 = NULL;

static int __init study_init(void)
{
 int err = 0;
 printk("%s\n", __PRETTY_FUNCTION__);

//shared_res = ATOMIC_INIT(0);
 //printk("int-atomic ATOMIC_INIT=%d\n", atomic_read(&shared_res));
 atomic_set(&shared_res, -100);
 printk("int-atomic atomic_set=%d\n", atomic_read(&shared_res));

my_thread1 = kthread_create(thread_process1, NULL, "my_thread1");
 if(IS_ERR(my_thread1))
 {
   err = PTR_ERR(my_thread1);
   my_thread1 = NULL;
   printk(KERN_ERR "unable to start kernel thread1:%d\n", err);
   return err;
 }

my_thread2 = kthread_create(thread_process2, NULL, "my_thread2");
 if(IS_ERR(my_thread2))
 {
   err = PTR_ERR(my_thread2);
   my_thread2 = NULL;
   printk(KERN_ERR "unable to start kernel thread2:%d\n", err);
   return err;
 }

my_thread3 = kthread_create(thread_process3, NULL, "my_thread3");
 if(IS_ERR(my_thread3))
 {
   err = PTR_ERR(my_thread3);
   my_thread3 = NULL;
   printk(KERN_ERR "unable to start kernel thread3:%d\n", err);
   return err;
 }

wake_up_process(my_thread1);
 wake_up_process(my_thread2);
 wake_up_process(my_thread3);
 printk("%s:all kernel thread start;\n", __FUNCTION__);
 return 0;
}

static void __exit study_exit(void)
{
 int ret = -1;
 printk("%s\n",__PRETTY_FUNCTION__);

if(my_thread1)
 {
   ret = kthread_stop(my_thread1);
   my_thread1 = NULL;
   printk("kernel thread1 stop,exit code is %d;\n",ret);
 }

if(my_thread2)
 {
   ret = kthread_stop(my_thread2);
   my_thread2 = NULL;
   printk("kernel thread2 stop,exit code is %d;\n",ret);
 }

if(my_thread3)
 {
   ret = kthread_stop(my_thread3);
   my_thread3 = NULL;
   printk("kernel thread3 stop,exit code is %d;\n",ret);
 }

printk("%s:all kernel thread stop;\n", __FUNCTION__);
}

module_init(study_init);
module_exit(study_exit);

内核并发控制---原子操作(来自网易)相关推荐

  1. 内核并发控制---RCU (来自网易)

    定义在头文件linux/rcupdate.h中; 一.RCU原理 RCU,全名Read-Copy-Update(读-拷贝-更新);对于被RCU所保护的共享资源,读执行单元不需要获得任何锁就可以访问到它 ...

  2. 内核并发控制---自旋锁(来自网易)

    定义在头文件linux/spinlock.h中; 自旋锁(spin lock)是一种对临界资源进行互斥访问的典型手段;为了获得一个自旋锁,在某CPU上运行的代码需要首先执行一个原子操作,该操作测试并设 ...

  3. 内核并发控制---互斥量(来自网易)

    定义在头文件linux/mutex.h中; 互斥体(mutex)是Linux系统提供的另外一种互斥机制;在Linux内核中是真实存在的; 1).定义互斥体 struct mutex my_mutex; ...

  4. 内核并发控制---完成量 (来自网易)

    定义在头文件linux/completion.h中; 完成量(completion)是Linux系统提供的一种比信号量更好的同步机制,是对信号量的一种补充;它用于一个执行单元等待另一个执行单元完成某事 ...

  5. 内核并发控制---读写信号量(来自网易)

    定义在头文件linux/rwsem.h或linux/rwsem-spinlock.h中 读写信号量与信号量之间的关系,类似于读写自旋锁与自旋锁之间的关系;读写信号量可能会引起进程阻塞,但是它允许N个读 ...

  6. 内核并发控制---信号量 (来自网易)

    定义在头文件linux/semaphore.h中; 信号量(semaphore)是用于保护临界区的一种常用方法,它的使用方式与自旋锁类似;与自旋锁相同,只有得到信号量的进程才能执行临界区的代码;但是, ...

  7. 内核并发控制---顺序锁 (来自网易)

    定义在头文件linux/seqlock.h中; 顺序锁(seqlock)是对读写锁的一种优化,若使用顺序锁,读执行单元绝对不会被写执行单元所阻塞,也就是说,读执行单元可以在写执行单元对被顺序锁保护的共 ...

  8. 内核并发控制---中断屏蔽 (来自网易)

    定义在头文件linux/irqflags.h中; 在单CPU内部避免竞态的一种方法是在进入临界区之前先屏蔽系统的中断,离开临界区之前再恢复系统中断;CPU一般都应该具有打开中断和关闭中断的功能;这项功 ...

  9. 内核并发控制---读写自旋锁 (来自网易)

    定义在头文件linux/spinlock.h或linux/rwlock.h中; 自旋锁并不关心其锁定的临界区究竟会进行怎么样的操作,不管是读还是写,都一视同仁,即便是多个执行单元同时并发地读取临界区资 ...

最新文章

  1. 华南理工大学计算机应用基础随堂作业,华南理工大学计算机应用基础随堂练习题目及答案...
  2. 概率论 第四章 随机变量的数字特征
  3. php对提交数据转码,如何使用php程序实现媒体转码消息的接收
  4. mysql语句中%代表什么_常用的Mysql语句你知道多少?
  5. 剑指 Offer II 014. 字符串中的变位词
  6. Spark Streaming 实战案例(二) Transformation操作
  7. 关于@property的一些用法
  8. Linux ext3默认块大小,linux – ext3 / ext4物理块大小视图
  9. Android中对list的日期元素进行排序
  10. Kotlin:比 Java 做得更好
  11. linux命令 剪切,linux剪切命令
  12. Ubuntu操作-01 安装NVIDIA显卡驱动
  13. 基于java企业人事管理系统mysql
  14. 数据库设计5-逻辑结构设计
  15. java中awt和swing是什么关系
  16. Linux软件更新时遇到的各种问题以及解决办法
  17. 掌握销售谈判三大策略,开单成功率提升60%!
  18. echart 多种覆盖物 显示优先级
  19. 电脑硬盘为什么叫计算机,电脑硬盘响得很大声如何解决|电脑磁盘吱吱响是怎么回事...
  20. Python数据可视化:数据分布图表可视化

热门文章

  1. 借助neo4j-admin导入csv文件构建实体与联系
  2. 怎么在delphi显示html,如何在Delphi中将简单的RichText转换为HTML标签?
  3. Bootstrap补充
  4. WIN7与WIN10 安装
  5. Android 实践项目开发二
  6. 存储过程之游标笔记小结
  7. 浅谈C++中内存泄漏的检测
  8. 在资源管理器中使鼠标右键增加一个命令,运行cmd,同时使得当前路径为资源管理器当前的目录...
  9. sscli 2.0 简介
  10. java实现arp断网攻击,可攻击局域网内所有的主机