Linux内核同步方法之等待队列

本文详细介绍了Linux内核中的等待队列,包括其定义、相关数据结构(如wait_queue_head_t)、常用函数接口(如wait_event、wake_up)以及在V4L2子系统中的应用实例。等待队列作为内核同步机制,用于进程的阻塞和唤醒,有效处理异步事件通知。
摘要由CSDN通过智能技术生成


前言

软硬件环境:
硬件:PC
软件:ubuntu18.04

本文主要介绍,Linux 内核中的等待队列, 包括它的含义,相关数据结构和函数及使用场景和实例等。

一、什么是等待队列

等待队列是内核中一个重要的数据结构。当以阻塞方式访问设备时,如果设备不可操作,那么进程就会进入休眠状态。等待队列就是来完成进程休眠操作的一种数据结构。

等待队列用于使得进程等待某一特定事件的发生,无需频繁的轮询,进程在等待周期中睡眠,当事件发生后由内核自动唤醒。
等待队列是一种实现阻塞和唤醒的内核机制,很早就作为一个基本的功能单位出现在Linux内核中,它以队列为基础数据结构,与进程调度机制紧密结合,能够用于实现内核中的异步事件通知机制。

二、等待队列相关的数据结构和函数接口

1. 等待队列相关数据结构

  • wait_queue_head_t
    如下图所示, 是数据结构wait_queue_head_t的定义
    在这里插入图片描述

2. 等待队列相关函数接口

  1. 定义和初始化等待队列头
    初始化等待队列头有两种方式:静态和动态
    静态:
    DECLARE_WAIT_QUEUE_HEAD(wait); //静态初始化一个等待队列头 wait
    动态:
    wait_queue_head_t wait;
    init_waitqueue_head(&wait);

  2. 休眠进程
    wait_event(wait, condition) //将当前进程的状态设置为 TASK_UNINTERRUPTIBLE
    wait_event_interruptible(wait, condition) //TASK_INTERRUPTIBLE
    wait_event_timeout(wait, condition, timeout) //TASK_UNINTERRUPTIBLE
    wait_event_interruptible_timeout(wait, condition, timeout) //TASK_INTERRUPTIBLE

说明:

  • wait 是等待队列头, condition 是条件,如果调用 wait_event()前 condition == 0 ,则调用 wait_event 之后,当前进程就会休眠, 如果调用wait_event()前,condition == 1, 则 wait_event()会立即返回;
  • wait_event()与wait_event_interruptible()的区别在于后者的休眠是可以被信号打断,而前者则不会。别的进程发来一个信号比如kill ,TASK_INTERRUPTIBLE 就会被换醒来去处理。然而 TASK_UNINTERRUPTIBLE则不会被唤醒,继续保持睡眠;
  • wait_event_timeout() 当阻塞等待的超时时间到达时,无论condition是否满足,均会立即返回;
  1. 唤醒进程
    wake_up(wait_queue_head_t *wait)
    wake_up_interruptible(wait_queue_head_t *wait)

说明:

  • wake_up()和wake_up_interruptible()会唤醒以wait作为等待队列头的进入休眠的进程,唤醒之后,它会判断
    condition 是否为真,如果还是假的则继续睡眠;
  • wake_up()应与wake_event() 或 wait_event_timeout()成对使用, 而wake_up_interruptible()应与wait_event_interruptible()或 wait_event_interruptibel_timeout()成对使用,wake_up()可唤醒处于TASK_INTERRUPTIBLE 和TASK_UNINTERRUPTIBLE状态的进程,而wake_up_interruptible()只能唤醒处于TASK_INTERRUPTIBLE状态的进程;

三、等待队列的使用实例

1. 等待队列在V4L2子系统中的使用实例

  1. 阻塞操作
    在V4L2子系统中, 当应用程序调用ioctl (DQBUF)操作的时候,最终会通过如下调用顺序调用到__vb2_wait_for_done_vb()函数
    vb2_core_dqbuf()-------->__vb2_get_done_vb()--------->__vb2_wait_for_done_vb()

在__vb2_wait_for_done_vb()函数中会调用等待队列相关的阻塞接口wait_event_interruptible() 等待被唤醒
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2. 唤醒操作
当硬件有数据传递到SOC端的时候, 会产生硬件中断,进入中断处理函数, 在中断处理函数中驱动会调用**vb2_buffer_done()**函数, 唤醒之前等待数据的等待队列, 如下图所示.
在vb2_buffer_done()函数中会去调用wake_up()函数,进行唤醒操作。
在这里插入图片描述

2. 最简单的等待队列使用实例

如下所示,为最简单的等待队列使用实例

wait_queue_demo.c

#include <linux/init.h>
#
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值