简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!
优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀
优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀
优质视频课程:AAOS车载系统+AOSP14系统攻城狮入门实战课【原创干货持续更新中……】🚀
人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.
🍉🍉🍉文章目录🍉🍉🍉
- 🌻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); // 假设初始资源数量为10
static int __init resource_manager_init(void) {
// 模拟使用一个资源时,将资源数量减少1
atomic_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), // ACTIVE
ATOMIC_LONG_INIT(0), // IDLE
ATOMIC_LONG_INIT(0) // OFFLINE
};
static int __init device_status_init(void) {
// 假设设备状态切换为 IDLE,将对应状态计数器减少1
enum 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); // 使用资源,数量减少1
printk(KERN_INFO "Thread: Used resource, remaining count: %ld\n", atomic_long_read(&resource_count));
msleep(1000);
atomic_long_inc(&resource_count); // 释放资源,数量增加1
printk(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");