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

Unix/Linux
Linux 备份 恢复方法
Linux玩CS反恐精英的方法
在一个ISO镜像中集成多个不同的linux发行版,可刻盘,可引导
Linux 快捷键使用
Linux DHCP 服务器配置方法介绍
Linux 22端口的修改方法
Linux 记录会话过程的命令
Linux 后台执行程序如何操作?
linux Wget命令来浏览网页的方法
Linux tail命令的巧妙应用
Wine 中文存在很多的乱码怎么解决方法
linux 新手教程之创建锁文件的方法
配置Linux 保证其系统的安全
Linux DHCP协议实现过程
Linux系统下破解SAM密码
linux/unix vi 编辑器用法详解
Linux 误删文件的解决方法
Linux系统下的历史记录删除方法
Red Hat Linux 安全设置指南
Linux基本命令-注销、关机、重启

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


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-11-01   浏览: 57 ::
收藏到网摘: 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] 下一页