《Android深度探索 卷1 HAL与驱动开发》笔记之Linux驱动程序中的并发操作(1)——原子操作

本文介绍了Linux驱动程序中并发控制的重要性,解释了并发和竞态的概念,并详细讨论了原子操作的原理和用法,包括整型、64位整型及位原子操作。通过实例展示了如何使用原子操作防止设备文件被多个进程同时打开,从而避免数据异常。
摘要由CSDN通过智能技术生成

为什么需要并发控制

通常一个 Linux 驱动程序并不是为了给某个用户空间使用而编写的。调用到这个 Linux 驱动程序的用户有可能会有很多个,这就有可能出现多个用户程序同时对这个 Linux 驱动程序进行readwriteioctl等操作。由于 Linux 驱动程序还会使用一些全局数据(即共享数据),如果同时对这些全局数据进行操作,就有可能会出现异常数据,这就使得 Linux 驱动必须具有能控制对共享数据访问的能力。
例如:

  • 在读共享数据时不能修改共享数据;
  • 不能同时有两个或两个以上的任务访问共享数据;

为了避免上述所说的问题,就需要在 Linux 驱动中实现并发控制,由此产生了并发控制的技术。这些技术包括原子操作、自旋锁、RCU、信号量、互斥体和完成量

什么是并发

并发(concurrency) 指的是多个任务线程或进程同时被执行。

什么是竞态

竞态(race) 指的是多个任务线程或进程同时对共享数据(如硬件资源、程序中的全局变量、静态变量等)进行修改。

主要的并发控制技术

  • 原子操作
  • 自旋锁(Spin lock)
  • 读-复制-更新(RCU)机制
  • 信号量(Semaphore)
  • 互斥体(Mutex)
  • 完成量(Completion)

原子操作

原子操作就是指单位操作,也就是说,原子操作在执行的过程中是不能够被打断的。原子操作根据执行的对象数据类型可分为:整型原子操作、64位整型原子操作、位原子操作

  • 整型原子操作

对整型数据(int)进行操作变成原子操作就是整型原子操作,它的实现依赖于一个数据类型:atomic_t。这个数据类型在头文件 linux/types.h中实现,代码如下:

typedef struct {
   
	int counter;
} atomic_t;

只要将变量类型定义为atomic_t,并通过一些函数来操作atomic_t.counter变量,则atomic_t.counter变量值的变化就是原子的。

定义atomic_t类型的变量和定义普通类型的变量是一样的,只需要使用ATOMIC_INIT宏初始化,可参考如下代码:

atomic_t v; /* 定义atomic_t类型的变量 */
atomic_t n = ATOMIC_INIT(1); /* 定义atomic_t类型的变量,并初始化该变量 */

操作atomic_t类型的变量在 Linux 内核中提供了相应的接口函数。其中包括对原子变量的初始化,增加或减少变量的值。比如,定义一个原子变量n,将该变量赋值为2,然后在这个变量n的值加5,在减去1,最后输出变量的值,它的实现参考代码如下:

atomic_t n; /* 定义atomic_t类型的变量 */
atomic_set(&n, 2)/* 将变量n的初始值设为2 */
atomic_add(5, &n); /* 将变量n的值加5 */
atomic_inc(&n)/* 将变量你的值加1 */
atomic_sub(4, &n); /* 将变量的值减4 */
atomic_dec(&n); /* 将变量n的值减1 */
printk("n = %d", atomic_read(&n)); /* 输出变量n的值,输出值为3 */

由之前的结构体可以知道整型原子变量主要是用来计数的。例如,通过计数跟踪和限制设备文件被打开的次数。可以通过以下原子操作函数来实现:

int result = atomic_dec_and_test(&n); /* 将变量n减去1后,再判断变量n
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值