简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!
优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀
优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀
优质视频课程:AAOS车载系统+AOSP14系统攻城狮入门实战课【原创干货持续更新中……】🚀
人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.
🍉🍉🍉文章目录🍉🍉🍉
🌻1.前言
本篇目的:Linux内核之等待队列wait_queue_head_t用法实例
🌻2.Linux内核之等待队列wait_queue_head_t介绍
wait_queue_head_t
是 Linux 内核中用于实现等待队列的基本数据结构。在 Linux 内核中,等待队列是一种常见的机制,用于让进程在某个条件不满足时进入睡眠状态,当条件满足时被唤醒继续执行。这种机制在很多内核子系统中都有应用,如进程调度、设备驱动、同步等。wait_queue_head_t
结构体定义了一个等待队列的头部,它包含了等待队列的基本信息和一个用于同步的锁。等待队列实际上是一个进程列表,这些进程都在等待某个条件变为真。每个等待队列都有一个对应的wait_queue_head_t
结构体,用于管理这个队列。- 在 Linux 内核中,可以通过
DECLARE_WAIT_QUEUE_HEAD
宏来静态地声明一个wait_queue_head_t
对象,也可以通过init_waitqueue_head
函数动态地初始化一个wait_queue_head_t
对象。初始化后,可以通过wait_event
、wait_event_interruptible
、wait_event_timeout
等函数将进程加入到等待队列中,这些函数会阻塞进程,直到指定的条件变为真或超时。 - 当条件满足时,需要调用
wake_up
、wake_up_interruptible
等函数来唤醒等待队列中的进程。这些函数会遍历等待队列中的所有进程,并设置它们的唤醒标志,然后唤醒它们。 wait_queue_head_t
结构体的定义如下:
typedef struct __wait_queue_head {
spinlock_t lock;
struct list_head task_list;
} wait_queue_head_t;
- 其中,
spinlock_t
是一个自旋锁,用于同步对等待队列的操作;struct list_head
是一个双向链表,用于存储等待队列中的进程。 - 在 Linux 内核中,等待队列的使用非常广泛。例如,在进程调度中,等待队列用于实现等待某个进程的状态变化(如等待子进程退出);在设备驱动中,等待队列用于实现等待设备准备好读写;在文件系统中,等待队列用于实现等待文件的锁定状态变化等。
- 总之,
wait_queue_head_t
是 Linux 内核中实现等待队列的关键数据结构,它为内核提供了一种简单有效的同步机制,使得内核能够以优雅的方式处理各种同步问题。
🌻3.代码实例
以下为:Linux内核驱动程序中使用 wait_queue_head_t 数据结构和相关的等待函数来实现进程同步。
🐓3.1 wait_event_interruptible() 实现等待队列
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/kthread.h>
MODULE_LICENSE("GPL");
static wait_queue_head_t my_wait_queue;
static int condition = 0;
static int my_thread_function(void *data) {
printk(KERN_INFO "Thread started\n");
wait_event_interruptible(my_wait_queue, condition != 0);
printk(KERN_INFO "Thread awakened\n");
return 0;
}
static int __init my_init(void) {
printk(KERN_INFO "Module init\n");
init_waitqueue_head(&my_wait_queue);
kthread_run(my_thread_function, NULL, "my_thread");
msleep(5000); // Simulate some work
condition = 1; // Set the condition
wake_up(&my_wait_queue); // Wake up waiting thread
return 0;
}
static void __exit my_exit(void) {
printk(KERN_INFO "Module exit\n");
}
module_init(my_init);
module_exit(my_exit);
🐓3.2 wait_event_interruptible_timeout() 实现超时等待
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/kthread.h>
MODULE_LICENSE("GPL");
static wait_queue_head_t my_wait_queue;
static int condition = 0;
static int my_thread_function(void *data) {
printk(KERN_INFO "Thread started\n");
wait_event_interruptible_timeout(my_wait_queue, condition != 0, 5000); // Wait for 5 seconds
if (condition != 0)
printk(KERN_INFO "Condition met\n");
else
printk(KERN_INFO "Timeout occurred\n");
return 0;
}
static int __init my_init(void) {
printk(KERN_INFO "Module init\n");
init_waitqueue_head(&my_wait_queue);
kthread_run(my_thread_function, NULL, "my_thread");
msleep(7000); // Simulate some work
condition = 1; // Set the condition
wake_up(&my_wait_queue); // Wake up waiting thread
return 0;
}
static void __exit my_exit(void) {
printk(KERN_INFO "Module exit\n");
}
module_init(my_init);
module_exit(my_exit);