linux驱动程序中的并发控制(原子操作)-43
Posted 杨斌并
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux驱动程序中的并发控制(原子操作)-43相关的知识,希望对你有一定的参考价值。
原子操作
整型的原子操作
- 使对整型的int 的操作变成原子操作,要依靠一个数据类型:atomic_t。此结构体定义在 include/linux/types.h 文件中,定义如下:
typedef struct {
int counter;
} atomic_t;
相关的api
- #include<asm/atomic.h>
函数 | 描述 |
---|---|
ATOMIC_INIT(int i) | 定义原子变量的时候初始化 |
int atomic_read(atomic_t *v) | 读取原子变量 v 的值,并且返回 |
void atomic_set(atomic_t *v, int i) | 向 v 写入 i 值 |
void atomic_add(int i, atomic_t *v) | 给 v 加上 i 值 |
void atomic_sub(int i, atomic_t *v) | 给 v 减去 i 值 |
void atomic_inc(atomic_t *v) | 自增 |
void atomic_dec(atomic_t *v) | 自减 |
int atomic_dec_return(atomic_t *v) | 自减,并返回 v 的值 |
int atomic_inc_return(atomic_t *v) | 自增,并返回 v 的值 |
int atomic_sub_and_test(int i, atomic_t *v) | 从 v 减 i,如果结果为 0 就返回真,否则返回假 |
int atomic_dec_and_test(atomic_t *v) | 从 v 减 1,如果结果为 0 就返回真,否则返回假 |
int atomic_inc_and_test(atomic_t *v) | 给 v 加 1,如果结果为 0 就返回真,否则返回假 |
ATOMIC_INIT(int i) | 定义原子变量的时候初始化 |
int atomic_add_negative(int i, atomic_t *v) | 给 v 加 i,如果结果为负就返回真,否则返回假 |
atomic64_add_unless(atomic64_t *v, long a, long u) | 如果变量v的值不等于u,则v加a,并返回非0的值,否则v的值不变,并返回0 |
atomic64_inc_not_zero(atomic_t *v) | 如果变量v的值不等于0,则v加1,并返回非0的值,否则v的值不变,并返回0 |
位原子操作
- linux 内核提供了可以用原子的方式进行操作的功能,也就是位原子操作。这种操作的操作数类型是 unsigned long。位原子操作函数就是将指定位设为0,或设为1
unsigned long value = 0;
//设置value 的第0位为1,value当前的值是1
set_bit(0,&value);
//设置value 的第2位为1,value当前的值是5
set_bit(2,&value);
函数 | 描述 |
---|---|
void set_bit(int nr, void *p) | 将 p 地址的第 nr 位置 1 |
void clear_bit(int nr,void *p) | 将 p 地址的第 nr 位清零 |
void change_bit(int nr, void *p) | 将 p 地址的第 nr 位进行翻转 |
int test_bit(int nr, void *p) | 获取 p 地址的第 nr 位的值 |
int test_and_set_bit(int nr, void *p) | 将 p 地址的第 nr 位置 1,并且返回 nr 位原来的值 |
int test_and_clear_bit(int nr, void *p) | 将 p 地址的第 nr 位清零,并且返回 nr 位原来的值 |
int test_and_change_bit(int nr, void *p) | 将 p 地址的第 nr 位翻转,并且返回 nr 位原来的值 |
- atomic_test.c
#include<linux/module.h>
#include<linux/init.h>
#include<linux/kernel.h>
#include<linux/fs.h>
#include<linux/miscdevice.h>
#include<asm/uaccess.h>
#include<asm/atomic.h>
//定义设备文件的名字为atomic
#define DEVICE_NAME "atomic"
//模块传递的参数 非0 只有一个设备可以打开, 为0 可以多个进程打开这个atomic 设备
static int atom=1;
//初始化int_atomic_available 变量
static atomic_t int_atomic_available=ATOMIC_INIT(1);
static int atomic_open(struct inode *node,struct file *file){
int ret = 0;
if(atom){
//atomic_dec_and_test 将int_atomic_available 减1 如果为int_atomic_available 为0 则放回1 否则返回0
//int_atomic_available 这个值减1后不为0 则减一后 返回错误
ret = atomic_dec_and_test(&int_atomic_available);
if(!ret){
//将int_atomic_available 减1
printk("atomic_open is busy");
atomic_inc(&int_atomic_available);
return -EBUSY;
}
}
printk("atomic dev open successfully !\\n");
return 0;
}
static int atomic_release(struct inode *node,struct file *file){
if(atom){
//int_atomic_available 正常打开是 0 , 没有打开是1 减一将文件打开状态设置为初始为打开状态
atomic_inc(&int_atomic_available);
}
printk("atomic dev release successfully !\\n");
return 0;
}
static struct file_operations dev_fops={
.owner=THIS_MODULE,
.open=atomic_open,
.release=atomic_release
};
static struct miscdevice misc={
.minor=MISC_DYNAMIC_MINOR,
.name=DEVICE_NAME,
.fops=&dev_fops
};
static int __init atomic_init(void){
int ret=misc_register(&misc);
if(ret < 0 ){
printk("atomic_init is error");
return -1;
}
printk("atomic_init_success\\n");
return ret;
}
static void __exit atomic_exit(void){
printk("atomic_exit_success\\n");
misc_deregister(&misc);
}
module_init(atomic_init);
module_exit(atomic_exit);
module_param(atom,int,S_IRUGO|S_IWUSR);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("binbing.Yang");
- app.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
int main(int argc, char *argv[]){
int handler=open("/dev/atomic",0);
printf("handler : %d\\n",handler);
if(handler>0){
//getchar();让程序停留在这一步,直到它从键盘接收到消息
getchar();
close(handler);
}else{
printf("errno:%d\\n",errno);
}
return 0;
}
insmod day1_proc.ko atom=0 //多设终端访问
insmod day1_proc.ko atom=0 //只能一个终端访问
以上是关于linux驱动程序中的并发控制(原子操作)-43的主要内容,如果未能解决你的问题,请参考以下文章