Linux内核之原子操作:atomic_long_dec用法实例(六十七)

2024-05-03 02:20

本文主要是介绍Linux内核之原子操作:atomic_long_dec用法实例(六十七),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!

优质专栏:Audio工程师进阶系列原创干货持续更新中……】🚀
优质专栏:多媒体系统工程师系列原创干货持续更新中……】🚀
优质视频课程:AAOS车载系统+AOSP14系统攻城狮入门实战课原创干货持续更新中……】🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮

欢迎关注Android系统攻城狮

🍉🍉🍉文章目录🍉🍉🍉

    • 🌻1.前言
    • 🌻2.Linux内核之atomic_long_dec介绍
    • 🌻3.代码实例
      • 🐓3.1 资源计数
      • 🐓3.2 状态切换
      • 🐓3.3 同步机制
      • 🐓3.4 资源管理

🌻1.前言

本篇目的:Linux内核之原子操作:atomic_long_dec用法实例

🌻2.Linux内核之atomic_long_dec介绍

  • atomic_long_dec() 函数是 Linux 内核中用于对长整型(long)原子操作的函数之一。它的作用是以原子方式减少一个长整型变量的值,并且保证这个操作是不可中断的,即在多线程环境下也能保证数据的一致性和正确性。

  • 在 Linux 内核中,原子操作是一种特殊的操作,能够保证在多处理器或者多核系统上的并发执行过程中,对共享数据的访问是安全的,不会发生竞态条件(Race Condition)或者数据不一致的情况。atomic_long_dec() 函数正是通过这种机制来实现对长整型变量的安全减少。

  • 具体来说,atomic_long_dec() 函数接受一个指向 atomic_long_t 类型的变量的指针作为参数,然后将该变量的值减少 1,并且保证这个减少操作是原子的。在执行减少操作期间,如果其他线程尝试对同一个变量进行操作,它们会被阻塞,直到当前操作完成,从而确保了操作的完整性和一致性。

  • 这个函数在 Linux 内核中的应用非常广泛,特别是在实现并发数据结构、同步机制和各种驱动程序中。通过使用原子操作,开发人员可以编写出更加高效、稳定和可靠的多线程代码,而无需担心因为竞态条件而引发的各种问题。

  • atomic_long_dec() 函数是 Linux 内核中重要的原子操作函数之一,它的作用是实现对长整型变量的原子减少操作,确保多线程环境下的数据访问安全和一致性。

🌻3.代码实例

🐓3.1 资源计数

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/atomic.h>// 定义一个原子长整型变量,用于表示可用资源的数量
static atomic_long_t resource_count = ATOMIC_LONG_INIT(10); // 假设初始资源数量为10static int __init resource_manager_init(void) {// 模拟使用一个资源时,将资源数量减少1atomic_long_dec(&resource_count);printk(KERN_INFO "Resource used, remaining count: %ld\n", atomic_long_read(&resource_count));return 0;
}static void __exit resource_manager_exit(void) {printk(KERN_INFO "Exiting...\n");
}module_init(resource_manager_init);
module_exit(resource_manager_exit);MODULE_LICENSE("GPL");
  • 使用 atomic_long_dec() 函数来实现资源计数的功能。
  • 每次模块初始化时,模拟使用一个资源并将资源数量减少1,然后打印剩余资源数量。

🐓3.2 状态切换

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/atomic.h>// 定义一个表示状态的枚举类型
enum device_state {DEVICE_STATE_ACTIVE,DEVICE_STATE_IDLE,DEVICE_STATE_OFFLINE
};// 原子计数器数组,用于统计各个状态的设备数量
static atomic_long_t device_state_counts[] = {ATOMIC_LONG_INIT(0), // ACTIVEATOMIC_LONG_INIT(0), // IDLEATOMIC_LONG_INIT(0)  // OFFLINE
};static int __init device_status_init(void) {// 假设设备状态切换为 IDLE,将对应状态计数器减少1enum device_state current_state = DEVICE_STATE_IDLE;atomic_long_dec(&device_state_counts[current_state]);printk(KERN_INFO "Device status changed to IDLE, count: %ld\n", atomic_long_read(&device_state_counts[current_state]));return 0;
}static void __exit device_status_exit(void) {printk(KERN_INFO "Exiting...\n");
}module_init(device_status_init);
module_exit(device_status_exit);MODULE_LICENSE("GPL");
  • 使用 atomic_long_dec() 函数来实现设备状态的切换功能。
  • 每次模块初始化时,假设设备状态切换为 IDLE,然后将对应状态计数器减少1,并打印变更后的状态计数。

🐓3.3 同步机制

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/atomic.h>
#include <linux/delay.h>
#include <linux/kthread.h>// 全局的原子长整型变量,用于线程间同步
static atomic_long_t shared_variable = ATOMIC_LONG_INIT(10); // 假设初始值为10// 线程函数,每秒减少一次共享变量的值
static int my_thread_func(void *data) {int i;for (i = 0; i < 5; ++i) {msleep(1000);atomic_long_dec(&shared_variable);printk(KERN_INFO "Thread: Decremented shared variable to %ld\n", atomic_long_read(&shared_variable));}return 0;
}static int __init atomic_sync_init(void) {// 创建一个简单的内核线程,用于减少共享变量的值struct task_struct *my_thread;my_thread = kthread_run(my_thread_func, NULL, "my_thread");if (IS_ERR(my_thread)) {printk(KERN_ERR "Failed to create thread\n");return PTR_ERR(my_thread);}return 0;
}static void __exit atomic_sync_exit(void) {printk(KERN_INFO "Exiting...\n");
}module_init(atomic_sync_init);
module_exit(atomic_sync_exit);MODULE_LICENSE("GPL");
  • 使用原子操作来实现简单的线程同步机制。
  • 在初始化时,创建一个内核线程,它的工作是每秒减少一次共享变量的值。
  • 由于 atomic_long_dec() 函数是原子的,因此不需要额外的同步手段,就可以确保在多线程环境下对共享变量的操作是安全的。

🐓3.4 资源管理

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/atomic.h>
#include <linux/delay.h>
#include <linux/kthread.h>// 全局的原子长整型变量,用于表示资源数量
static atomic_long_t resource_count = ATOMIC_LONG_INIT(10); // 假设初始资源数量为10// 线程函数,模拟资源的使用和释放
static int resource_manager_func(void *data) {int i;for (i = 0; i < 5; ++i) {msleep(1000);atomic_long_dec(&resource_count); // 使用资源,数量减少1printk(KERN_INFO "Thread: Used resource, remaining count: %ld\n", atomic_long_read(&resource_count));msleep(1000);atomic_long_inc(&resource_count); // 释放资源,数量增加1printk(KERN_INFO "Thread: Freed resource, remaining count: %ld\n", atomic_long_read(&resource_count));}return 0;
}static int __init resource_management_init(void) {// 创建一个内核线程,模拟资源的使用和释放struct task_struct *resource_thread;resource_thread = kthread_run(resource_manager_func, NULL, "resource_thread");if (IS_ERR(resource_thread)) {printk(KERN_ERR "Failed to create resource management thread\n");return PTR_ERR(resource_thread);}return 0;
}static void __exit resource_management_exit(void) {printk(KERN_INFO "Exiting resource management driver...\n");
}module_init(resource_management_init);
module_exit(resource_management_exit);MODULE_LICENSE("GPL");

这篇关于Linux内核之原子操作:atomic_long_dec用法实例(六十七)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/955633

相关文章

SpringBoot UserAgentUtils获取用户浏览器的用法

《SpringBootUserAgentUtils获取用户浏览器的用法》UserAgentUtils是于处理用户代理(User-Agent)字符串的工具类,一般用于解析和处理浏览器、操作系统以及设备... 目录介绍效果图依赖封装客户端工具封装IP工具实体类获取设备信息入库介绍UserAgentUtils

Python ZIP文件操作技巧详解

《PythonZIP文件操作技巧详解》在数据处理和系统开发中,ZIP文件操作是开发者必须掌握的核心技能,Python标准库提供的zipfile模块以简洁的API和跨平台特性,成为处理ZIP文件的首选... 目录一、ZIP文件操作基础三板斧1.1 创建压缩包1.2 解压操作1.3 文件遍历与信息获取二、进阶技

Java中的@SneakyThrows注解用法详解

《Java中的@SneakyThrows注解用法详解》:本文主要介绍Java中的@SneakyThrows注解用法的相关资料,Lombok的@SneakyThrows注解简化了Java方法中的异常... 目录前言一、@SneakyThrows 简介1.1 什么是 Lombok?二、@SneakyThrows

Java中字符串转时间与时间转字符串的操作详解

《Java中字符串转时间与时间转字符串的操作详解》Java的java.time包提供了强大的日期和时间处理功能,通过DateTimeFormatter可以轻松地在日期时间对象和字符串之间进行转换,下面... 目录一、字符串转时间(一)使用预定义格式(二)自定义格式二、时间转字符串(一)使用预定义格式(二)自

Python中的getopt模块用法小结

《Python中的getopt模块用法小结》getopt.getopt()函数是Python中用于解析命令行参数的标准库函数,该函数可以从命令行中提取选项和参数,并对它们进行处理,本文详细介绍了Pyt... 目录getopt模块介绍getopt.getopt函数的介绍getopt模块的常用用法getopt模

mysql中的group by高级用法

《mysql中的groupby高级用法》MySQL中的GROUPBY是数据聚合分析的核心功能,主要用于将结果集按指定列分组,并结合聚合函数进行统计计算,下面给大家介绍mysql中的groupby用法... 目录一、基本语法与核心功能二、基础用法示例1. 单列分组统计2. 多列组合分组3. 与WHERE结合使

Java中Scanner的用法示例小结

《Java中Scanner的用法示例小结》有时候我们在编写代码的时候可能会使用输入和输出,那Java也有自己的输入和输出,今天我们来探究一下,对JavaScanner用法相关知识感兴趣的朋友一起看看吧... 目录前言一 输出二 输入Scanner的使用多组输入三 综合练习:猜数字游戏猜数字前言有时候我们在

java解析jwt中的payload的用法

《java解析jwt中的payload的用法》:本文主要介绍java解析jwt中的payload的用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java解析jwt中的payload1. 使用 jjwt 库步骤 1:添加依赖步骤 2:解析 JWT2. 使用 N

Linux命令之firewalld的用法

《Linux命令之firewalld的用法》:本文主要介绍Linux命令之firewalld的用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux命令之firewalld1、程序包2、启动firewalld3、配置文件4、firewalld规则定义的九大

SQL BETWEEN 的常见用法小结

《SQLBETWEEN的常见用法小结》BETWEEN操作符是SQL中非常有用的工具,它允许你快速选取某个范围内的值,本文给大家介绍SQLBETWEEN的常见用法,感兴趣的朋友一起看看吧... 在SQL中,BETWEEN是一个操作符,用于选取介于两个值之间的数据。它包含这两个边界值。BETWEEN操作符常用