linux驱动程序中的并发控制(原子操作)-43(代码片段)

杨斌并 杨斌并     2022-12-03     426

关键词:

原子操作

整型的原子操作

  • 使对整型的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驱动程序中的并发控制(自旋锁)-44(代码片段)

自旋锁(spinlock)简介原子锁和自旋锁的使用范围原子操作是一种很好的避免竞态的方式,使用非常简单。但在某些方面却显得过于简单。例如,有很多数据需要被格式化,被添加到某些数据结构中,然后... 查看详情

linux驱动程序中的并发控制-2(自旋锁)-44(代码片段)

自旋锁(spinlock)简介原子锁和自旋锁的使用范围原子操作是一种很好的避免竞态的方式,使用非常简单。但在某些方面却显得过于简单。例如,有很多数据需要被格式化,被添加到某些数据结构中,然后... 查看详情

设备驱动中的并发控制

在为操作系统编写驱动设备时,因为涉及到中断、多任务和多处理器SMP的处理,所以内核提供了诸如中断屏蔽、原子操作、信号量、完成量等几种并发控制机制,对公用资源进行保护。下文将分别予以阐述。0、中断中断屏蔽使... 查看详情

linux设备驱动的并发控制学习笔记(代码片段)

文章目录并发和竞态编译乱序和执行乱序并发控制机制中断屏蔽原子操作整型原子操作位原子操作自旋锁自旋锁的使用读写自旋锁顺序锁读-复制-更新信号量互斥体完成量并发和竞态并发:多个执行单元同时、并行被执行。... 查看详情

linux驱动开发原子操作自旋锁信号量互斥体(代码片段)

...片内存区域的情况,多个任务可能会相互覆盖掉内存中的数据,造成内存数据混乱。Linux系统并发主要原因多线程并发访问抢占式并发访问中断程序并发访问多核间并发访问通常需要对全局变量、设备结构体这些共享资源... 查看详情

linux驱动之并发与竞争(代码片段)

...同一片内存区域,这些任务可能会相互覆盖这段内存中的数据,造成内存数据混乱。针对这个问题必须要做处理,严重的话可能会导致系统崩溃。linux存在以下并发访问:①、多线程并发访问,Linux是多任务(线程)的... 查看详情

linux并发与竞争(原子操作自旋锁信号量互斥体)(代码片段)

目录并发与竞争原子操作原子操作简介原子整形操作API函数原子位操作API函数自旋锁自旋锁简介自旋锁API函数其他类型的锁自旋锁使用注意事项信号量信号量简介信号量API函数互斥体互斥体简介互斥体API函数Linux是一个多任务操... 查看详情

linux并发与竞争实验(代码片段)

...试实验程序编写运行测试在上一章中我们学习了Linux下的并发与竞争,并且学习了四种常用的处理并发和竞争的机制:原子操作、自旋锁、信号量和互斥体。本章我们就通过四个实验来学习如何在驱动中使用这四种机制。... 查看详情

go语言并发编程-原子操作(代码片段)

...并发操作而言,当两个或两个以上的goroutines同时读取内存中的n值,然后将n+1的值放回内存,可能多次自增的结果,这个n只自增了1次!这里需要使用原子操作,以保证多个goroutines对同一块内存的操作是原子的,即保证本例中... 查看详情

go语言并发编程-原子操作(代码片段)

...并发操作而言,当两个或两个以上的goroutines同时读取内存中的n值,然后将n+1的值放回内存,可能多次自增的结果,这个n只自增了1次!这里需要使用原子操作,以保证多个goroutines对同一块内存的操作是原子的,即保证本例中... 查看详情

linux设备驱动基础01之并发与竞态(代码片段)

...问同一片内存区域的情况,可能会相互覆盖这段内存中的数据,最终造成内存数据混乱,严重的话会导致系统崩溃。驱动开发中要注意对共享资源的保护,需要管理对共享资源的并发访问。Linux系统产生并发访问... 查看详情

实战java高并发程序设计5让普通变量也享受原子操作

【实战Java高并发程序设计1】Java中的指针:Unsafe类【实战Java高并发程序设计2】无锁的对象引用:AtomicReference【实战Java高并发程序设计3】带有时间戳的对象引用:AtomicStampedReference【实战Java高并发程序设计4】数组也能无锁:Atomi... 查看详情

linux内核并发与竞争-原子操作

...成了3句,那么程序在执行的时候肯定是按照示例代码中的汇编语句一条一条的执行。假设现在线程A要向a变量写入10这个值,而线程B也要向a变量写入20这个值,我们理想中的执行顺序如图所示:按照图所示的流程&... 查看详情

linux内核并发与竞争-原子操作

...成了3句,那么程序在执行的时候肯定是按照示例代码中的汇编语句一条一条的执行。假设现在线程A要向a变量写入10这个值,而线程B也要向a变量写入20这个值,我们理想中的执行顺序如图所示:按照图所示的流程&... 查看详情

在linux的用户空间,有没有原子操作的函数

...问者和网友采纳 参考技术Bopen函数加O_APPEND这个标志那么并发文件操作就是一个原子,否则会覆盖。intopen(constchar*pathname,intflags); 查看详情

java并发

...说,操作系统执行指令是原子的,但是高级语言中的指令不一定是原子的,例如n++这个指令,在操作系统中会被拆成多条指令执行如果不加锁的话,两个结果可能都是1,所以n++不是原 查看详情

linux设备驱动中的并发

参考技术A并发就是多个执行单元或多个进程并行执行,而这多个执行单元对资源进行共享,比如访问同一个变量或同一个硬件资源,这个时候就很容易出现竞态(说简单点就是竞争同一个”女朋友”)。为了处理并发带来的问题,... 查看详情

多线程&高并发深入浅出原子性(代码片段)

...“原子”被称为不可再分割的微粒,而我们并发编程中的“原子性”与该概念类似,指的是某一个操作能否在一个CPU时间段内完成。(要么把该操作相关的指令全都执行完,要不执行)📑能完成最好,... 查看详情