文章目录
- 前言
- 一、atomic是什么?
- 二、原子操作API函数
-
- 1.atomic原子操作
- 2.原子位操作API
- 三、atomic驱动实验
- 总结
前言
本文记录的是正点原子rk3568开发板的atomic实验
一、atomic是什么?
不同的线程在进行读写的过程中,可能会冲突乱入,导致会有预想不到的结果。所以为了让数据完整且无误地操作,需要对变量进行原子操作。
二、原子操作API函数
1.atomic原子操作
typedef struct {
int counter;
} atomic_t;
如果要使用原子操作 API 函数,首先要先定义一个 atomic_t 的变量,如下所示:
atomic_t a; //定义 a
也可以在定义原子变量的时候给原子变量赋初值,如下所示:
atomic_t b = ATOMIC_INIT(0); //定义原子变量 b 并赋初值为 0
可以通过宏 ATOMIC_INIT 向原子变量赋初值。
Linux 内核提供了大量的原子操作 API 函数,
2.原子位操作API
如果使用 64 位的 SOC 的话,就要用到 64 位的原子变量,Linux 内核也定义了 64 位原子
结构体,如下所示:
typedef struct {
s64 counter;
} atomic64_t;
原子位操作API函数
三、atomic驱动实验
本实验的目的:用atomic变量控制应用程序只允许打开一个
思路:
- 在驱动程序赋值atomic变量为1
- 应用程序正常打开一次,atomic变量减1。若atomic变量少于等于0,证明有应用程序占用着
- 应用程序结束后,atomic变量加1
驱动代码:atomic.c
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#define GPIOLED_CNT 1 /* 设备号个数 */
#define GPIOLED_NAME "gpioled" /* 名字 */
#define LEDOFF 0 /* 关灯 */
#define LEDON 1 /* 开灯 */
struct led_dev
{
dev_t devid; /* 设备号 */
struct cdev cdev; /* cdev */
struct class *class; /* 类 */
struct device *device; /* 设备 */
int major; /* 主设备号 */
int minor; /* 次设备号 */
struct device_node *nd; /* 设备节点 */
int led_gpio; /* led所使用的GPIO编号 */
atomic_t lock; /* 原子变量 */
};
struct led_dev gpioled;
static int led_drv_open(struct inode *inode, struct file *filp)
{
int val = 0;
val = atomic_read(&gpioled.lock);
if(val <= 0) {
return -EBUSY;
} else {
/* 每打开一次文件都必须要减1 */
atomic_dec(&gpioled.lock);
}
filp->private_data = &gpioled; /* 设置私有数据 */
return 0;
}
static