Linux设备驱动编程之阻塞与非阻塞

2016-01-29 17:40 1 1 收藏

Linux设备驱动编程之阻塞与非阻塞,Linux设备驱动编程之阻塞与非阻塞

【 tulaoshi.com - Linux 】

  阻塞操作是指,在执行设备操作时,若不能获得资源,则进程挂起直到满足可操作的条件再进行操作。非阻塞操作的进程在不能进行设备操作时,并不挂起。被挂起的进程进入sleep状态,被从调度器的运行队列移走,直到等待的条件被满足。

  在Linux驱动程序中,我们可以使用等待队列(wait queue)来实现阻塞操作。wait queue很早就作为一个基本的功能单位出现在Linux内核里了,它以队列为基础数据结构,与进程调度机制紧密结合,能够用于实现核心的异步事件通知机制。等待队列可以用来同步对系统资源的访问,上节中所讲述Linux信号量在内核中也是由等待队列来实现的。

  下面我们重新定义设备"globalvar",它可以被多个进程打开,但是每次只有当一个进程写入了一个数据之后本进程或其它进程才可以读取该数据,否则一直阻塞。

#include <linux/module.h
#include <linux/init.h
#include <linux/fs.h
#include <asm/uaccess.h
#include <linux/wait.h
#include <asm/semaphore.h
MODULE_LICENSE("GPL");

#define MAJOR_NUM 254

static ssize_t globalvar_read(struct file *, char *, size_t, loff_t*);
static ssize_t globalvar_write(struct file *, const char *, size_t, loff_t*);

struct file_operations globalvar_fops =
{
 read: globalvar_read, write: globalvar_write,
};

static int global_var = 0;
static struct semaphore sem;
static wait_queue_head_t outq;
static int flag = 0;

static int __init globalvar_init(void)
{
 int ret;
 ret = register_chrdev(MAJOR_NUM, "globalvar", &globalvar_fops);
 if (ret)
 {
  printk("globalvar register failure");
 }
 else
 {
  printk("globalvar register success");
  init_MUTEX(&sem);
  init_waitqueue_head(&outq);
 }
 return ret;
}

static void __exit globalvar_exit(void)
{
 int ret;
 ret = unregister_chrdev(MAJOR_NUM, "globalvar");
 if (ret)
 {
  printk("globalvar unregister failure");
 }
 else
 {
  printk("globalvar unregister success");
 }
}

static ssize_t globalvar_read(struct file *filp, char *buf, size_t len, loff_t *off)
{
 //等待数据可获得
 if (wait_event_interruptible(outq, flag != 0))
 {
  return - ERESTARTSYS;
 }

 if (down_interruptible(&sem))
 {
  return - ERESTARTSYS;
 }

 flag = 0;
 if (copy_to_user(buf, &global_var, sizeof(int)))
 {
  up(&sem);
  return - EFAULT;
 }
 up(&sem);
 return sizeof(int);
}

static ssize_t globalvar_write(struct file *filp, const char *buf, size_t len,loff_t *off)
{
 if (down_interruptible(&sem))
 {
  return - ERESTARTSYS;
 }
 if (copy_from_user(&global_var, buf, sizeof(int)))
 {
  up(&sem);
  return - EFAULT;
 }
 up(&sem);
 flag = 1;
 //通知数据可获得
 wake_up_interruptible(&outq);
 return sizeof(int);
}

module_init(globalvar_init);
module_exit(globalvar_exit);


 

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com/linux/)

(本文来源于图老师网站,更多请访问https://www.tulaoshi.com/linux/)

[1] [2] [3] [4]   

来源:https://www.tulaoshi.com/n/20160129/1502482.html

延伸阅读
  序言 Linux是Unix操作系统的一种变种,在Linux下编写驱动程序的原理和思想完全类似于其他的Unix系统,但它dos或window环境下的驱动程序有很大的区别。在Linux环境下设计驱动程序,思想简洁,操作方便,功能也很强大,但是支持函数少,只能依赖kernel中的函数,有些常用的操作要自己来编写,而且调试也不方便。本人这几周来为...
标签: Web开发
阻塞的AJAX请求 我们先来证实一下请求的阻塞情况吧。我们使用如下的代码: 连续发起三个请求 function simpleRequest() {    var request = new XMLHttpRequest();    request.open("POST", "Script.ashx");    request.send(null); } function threeRequests() {    simpleRequest();   ...
不同输卵管阻塞问题的治疗方法 目前用于输卵管堵塞的治疗方法很多,有输卵管通液治疗、经X线的输卵管介入疏通术、宫腔镜、腹腔镜治疗、中药治疗、灌肠治疗、微波物理疗法治疗,以及一些其它的红外线、烤电、妇科治疗仪等治疗方法,可谓鱼龙混杂。 不同阻塞部位的治疗方案 (图老师整理) 根据输卵管堵塞的临床经...
概述 一. Linux设备概述 在概念上一般把设备分为字符设备、块设备。字符设备是指设备发送和接收数据以字符形式的进行;而块设备则以整个数据缓冲区的形式进行。但是,由于网络设备等有其非凡性,实际上系统对它们单独处理。 系统用主设备号(MAJOR)加次设备(MINOR)号来唯一标识一个设备。相同主设备号表示同一类...
本讲主要概述Linux设备驱动框架、驱动程序的配置文件及常用的加载驱动程序的方法;并且介绍Red Hat Linux安装程序是如何加载驱动的,通过了解这个过程, 我们可以自己将驱动程序放到引导盘中;安装完系统后,使用kudzu自动配置硬件程序。 Linux设备驱动概述 1. 内核和驱动模块 操作系统是通过各种驱动程序来驾驭硬件设备,它为用户屏蔽...

经验教程

471

收藏

26
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部