当前位置: 首页 > 图文教程 > 操作系统 > Unix/Linux > Linux设备驱动编程之阻塞与非阻塞

Unix/Linux
Linux命令Man解释:useradd:帐号建立或更新
Linux 网管 123 --- 第7章. 自订的组态及管理内容 -7.使用 Linuxc
Linux 网管 123 --- 第8章. 备份及回存程序 -1.伺服器备份程序
Linux 网管 123 --- 第8章. 备份及回存程序 -2.伺服器回存程序(tar.
Linux 网管 123 --- 第8章. 备份及回存程序 -3.Cisco 路由器组态备
Linux 网管 123 --- 第9章. 各种杂项管理工作 -1.检查储存空间
Linux 网管 123 --- 第9章. 各种杂项管理工作 -2.管理进程
Linux 网管 123 --- 第9章. 各种杂项管理工作 -3.进程的启动及停止
Linux 网管 123 --- 第9章. 各种杂项管理工作 -4.使用 Cron 及 C
Linux 网管 123 --- 第10章. 升级 Linux 及其他应用软体 -1.使用
Linux 网管 123 --- 1. 前言 2. 简介
Linux 网管 123 --- 第3章. 概观 Linux
Linux 网管 123 --- 第4章. 安装及硬体组态 - 1.建立一张安装磁片
轻轻松松的安装Slackware Linux -- 4.如何在硬碟建置Linux系统
轻轻松松的安装Slackware Linux -- 5.其他非标准安装程序解析
如何重新设定时区
Linux中有没有支援 Solairs x86 的档案系统?有的话要如何mount?
MBR如果被覆盖了怎麽办?
如何使用命令trap来捕捉信号?
如何进行增量备份?

Unix/Linux 中的 Linux设备驱动编程之阻塞与非阻塞


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-11-01   浏览: 151 ::
收藏到网摘: n/a

  阻塞操作是指,在执行设备操作时,若不能获得资源,则进程挂起直到满足可操作的条件再进行操作。非阻塞操作的进程在不能进行设备操作时,并不挂起。被挂起的进程进入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);


 

[1] [2] [3] [4] 下一页