Linux设备驱动--等待队列(一)

参考资料:

宋宝华:《linux设备驱动开发详解》

《Mastering Linux Device Driver Development》

原文翻译与理解:

        等待队列用于处理阻塞I/O,等待队列等待特定条件变为true,等待一个给定事件发生,或者是等待数据和资源可以被获得。

        内核中等待队列的数据结构如下:

       成员为一个自旋锁和一个list_head类型的变量。

       等待队列就是一个list,(这个list里面的进程被置为sleep状态,因而当某个条件发生的时候,它们可以被唤醒),等待队列的成员自旋锁用于保护这个list的并发访问。等待队列里面的进程想要进入睡眠状态,并且这种睡眠状态是因为等待一个或多个事件的发生,并且可以被唤醒。head表示这一系列进程。每个想要睡眠并且等待事件发生的进程会在睡眠之间放入到list。当一个进程在list的时候,称为wait queue entry。当事件发生的时候,list中的一个或者多个进程会被唤醒,并且移除出这个list。我们可以用两种方式显式初始化一个wait queue。一种是静态的声明和定义:

      我们也可以动态初始化wait queue:

       

      任何想要sleep并且等待my_event发生的进程可以触发以下两个函数: wait_event_interruptible() 或者 wait_event() 。大多数时候,事件仅仅是资源可达。为了让事情简单,这两个函数第二个参数都是一个表达式,如果表示为false那么进程就会被置为睡眠。

    

       wait_event() 和 wait_event_interruptible() 差异在于:后者的睡眠是可以被信号打断的。它们被调用的时候都会看条件是否满足,条件为false时,进程被置为睡眠态并且被移除出running queue。

      当需要等待的条件可能不再是true或者false,而是一个确定的延时,可以使用:wait_event_timeout。

       

       这个函数有两个行为,取决于timeout走完与否:

(1)timeout已经走完了:

         如果条件为false,wait_event_timeout 返回0;如果条件为true,wait_event_timeout返回1。

(2)timeout还没有走完:如果条件为true返回剩余时间。

时间的单元是jiffies。linux有相关api将毫秒和微秒转为 jiffies。从上可以看出,不管条件是否满足,时间走完都会返回的。

   

        如果一些变量改变,造成这些进程等待的条件发生变化,必须使用wake_up系列的函数。也即是说,要唤醒在wait_queue种睡眠的进程,必须调用wake_up(),wake_up_all()和wake_up_interruptible(),或者wake_up_interruptible_all()。当使用这些函数的时候,条件会被重新评估。如果此时条件为true,则wait_queue相应进程被唤醒,并且这些进程的状态被设置为TASK_RUNNING;否则条件为false,没有任何事情发生。

        例如:

#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/time.h>
#include <linux/delay.h>
#include<linux/workqueue.h>
static DECLARE_WAIT_QUEUE_HEAD(my_wq);  //初始化一个wait_queue
static int condition = 0;    //condition
/* declare a work queue*/
static struct work_struct wrk;
static void work_handler(struct work_struct *work)
{
 pr_info(“Waitqueue module handler %s\n”, __FUNCTION__);
 msleep(5000);
 pr_info(“Wake up the sleeping module\n”);
 condition = 1;
 wake_up_interruptible(&my_wq);
}

static int __init my_init(void)
{
 pr_info(“Wait queue example\n”);
 INIT_WORK(&wrk, work_handler);  
 schedule_work(&wrk);   
 pr_info(“Going to sleep %s\n”, __FUNCTION__);
 wait_event_interruptible(my_wq, condition != 0);
 pr_info(“woken up by the work job\n”);
 return 0;
}

void my_exit(void)
{
 pr_info(“waitqueue example cleanup\n”);
}


module_init(my_init);
module_exit(my_exit);
MODULE_AUTHOR(“John Madieu <john.madieu@labcsmart.com>”);
MODULE_LICENSE(“GPL”);

       这个例子中,进程在wait_queue中被放入5s,然后被work_handler唤醒。输出日志为:

        可以看到module被wait_event_interruptible置为睡眠状态,仅work_handler设置condition=1并且wake_up wait_queue时,module被唤醒继续往下执行。

       

  

  • 25
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux Driver Development for Embedded Processors – Second Edition 版本: Learn to develop Linux embedded drivers with kernel 4.9 LTS The flexibility of Linux embedded, the availability of powerful, energy efficient processors designed for embedded computing and the low cost of new processors are encouraging many industrial companies to come up with new developments based on embedded processors. Current engineers have in their hands powerful tools for developing applications previously unimagined, but they need to understand the countless features that Linux offers today. This book will teach you how to develop device drivers for Device Tree Linux embedded systems. You will learn how to write different types of Linux drivers, as well as the appropriate APIs (Application Program Interfaces) and methods to interface with kernel and user spaces. This is a book is meant to be practical, but also provides an important theoretical base. More than twenty drivers are written and ported to three different processors. You can choose between NXP i.MX7D, Microchip SAMA5D2 and Broadcom BCM2837 processors to develop and test the drivers, whose implementation is described in detail in the practical lab sections of the book. Before you start reading, I encourage you to acquire any of these processor boards whenever you have access to some GPIOs, and at least one SPI and I2C controllers. One of the boards used to implement the drivers is the famous Raspberry PI 3 Model B board. You will learn how to develop drivers, from the simplest ones that do not interact with any external hardware, to drivers that manage different kind of devices: accelerometers, DACs, ADCs, RGB LEDs, Multi-Display LED controllers, I/O expanders, and Buttons. You will also develop DMA drivers, drivers that manage interrupts, and drivers that write/read on the internal registers of the processor to control external devices. To easy the development of some of these drivers, you will use different types of Frameworks: Miscellaneous framework, LED framework, UIO framework, Input framework and the IIO industrial one. This second edition has been updated to the v4.9 LTS kernel.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值