免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1587 | 回复: 0
打印 上一主题 下一主题

功能较为完善的驱动--并发,异步,阻塞,ioctl [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-03-15 17:11 |只看该作者 |倒序浏览


文件:
driver-all.rar
大小:
4KB
下载:
下载
/*
* (C) copyright 2008
panhuachun@hotmail.com
*/
#define __NO_VERSION__
#include  
#include  
#include  
#include  
#include  
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
unsigned int test_major = 0;
//#define MAJOR_NUM 254
//MODULE_LICENSE("GPL")
static int count;
//static char data[100];
char *data="wodeshen" ;
static spinlock_t spin=SPIN_LOCK_UNLOCKED;
static struct semaphore sem;
static wait_queue_head_t outq;
static struct fasync_struct fasync_t;
struct fasync_struct *myfasync=&fasync_t;
static struct completion test_completion;//DECLARE_COMPLETION(comp);
static int flag=0;

/*
static int __init test_init(void)
{
int ret;
ret=register_chrdev(0 ,"test",&test_op);
if(ret
static int test_ioctl(struct inode* inode, struct file* filp, unsigned int cmd, unsigned long arg)
{
long retval = 0;
switch(cmd){
case 1:
  printk("1\n");
  break;
case 2:
  printk("2\n");
  break;
case 3:
  printk("3\n");
  break;
case 4:
  printk("4\n");  
  break;
default:
  return -ENOTTY;
}
return retval;
}
/*
static int test_mmap(struct file* filp, struct vm_area_struct *vma)
{

}
*/
static ssize_t test_open(struct inode *inode ,struct file *file)
{
spin_lock(&spin);
//防止多个进程进入,这里允许俩个进程(方便俩个终端测试),一个写一个读
if(count>1){
  spin_unlock(&spin);
  return -EBUSY;
}
count++;
spin_unlock(&spin);
return 0;
}
static int test_release(struct inode *inode,struct file *file)
{
count--;
return 0;
}
static ssize_t test_read( struct file *file, char *buf, size_t len, loff_t *off)
{
//slect的poll机制
DECLARE_WAITQUEUE(wait, current);
add_wait_queue(&outq, &wait);
//read的阻塞机制
//if(wait_event_interruptible(outq,flag!=0))
  //return -ERESTARTSYS;
//轻量级通知机制
wait_for_completion(&test_completion);
if(down_interruptible(&sem))
  return - ERESTARTSYS;
/*
即交换wait_event_interruptible(outq, flag != 0)和down_interruptible(&sem)的顺序,
这个驱动程序将变得不可运行。实际上,当两个可能要阻塞的事件同时出现时,
即两个wait_event或down摆在一起的时候,将变得非常危险,死锁的可能性很大,
这个时候我们要特别留意它们的出现顺序。当然,我们应该尽可能地避免这种情况的发生!
*/
flag=0;
if(copy_to_user(buf,data,len)){
  up(&sem);
  return -EFAULT;
}
up(&sem);
//删除很重要啊,要不下次一个进程执行write时候wake_up_interruptible(&outq);将崩溃
remove_wait_queue(&outq, &wait);
       return len;
}
//static ssize_t test_write(struct file *file,char *buf, size_t len, loff_t *off)
static ssize_t test_write(struct file *file, const char *buf, size_t len, loff_t *f_pos)
{
printk("------test_write--------\n");
if(down_interruptible(&sem))
  return -ERESTARTSYS;
if(copy_from_user(data,buf,len)){
  up(&sem);
  return -EFAULT;
}
up(&sem);
flag=1;
printk("------write ok--------\n");
wake_up_interruptible(&outq);
       complete(&test_completion);
kill_fasync(&myfasync, SIGIO, POLL_IN);
printk("------send ok--------\n");
return len;
}
static unsigned int test_poll(struct file *file, poll_table *wait)
{
unsigned int mask = 0;
//poll_wait函数所做的工作是把当前进程添
//加到wait参数指定的等待列表(poll_table)中。
//poll_wait函数并不阻塞,
//程序中poll_wait(filp, &outq, wait)这句话的意思并不是说
//一直等待outq信号量可获得,
//真正的阻塞动作是上层的select/poll函数中完成的。
poll_wait(file,&outq,wait);

printk("2-----poll_wait\n");
if (flag!=0)
  mask|=POLLIN |POLLRDNORM;
return mask;
}
static int test_fasync(int fd, struct file* file, int mode)
{
printk("1-----test_fasync\n");
  return fasync_helper(fd, file, mode, &myfasync);
}
struct file_operations test_op={
read   : test_read,
write  : test_write,
open   : test_open,
release: test_release,
poll    : test_poll,

//异步通知和poll,和read的阻塞有一拼
fasync : test_fasync,

//存放数据和read比较mmap好
//mmap   : test_mmap,

//cmd控制
ioctl  : test_ioctl,
};
static unsigned int major =254;
int init_module(void)
{
//unsigned int ret;
//int i;
int ret;
printk("-------------\n");
//printk("---%d---\n",register_chrdev(0, "test", &test_op));
ret=register_chrdev(0, "test", &test_op);
if(ret
printk("---%d---\n",ret);
return 0;
}
void cleanup_module(void)
{
//test_exit();
  printk("------unregister_chrdev--------\n");
unregister_chrdev(test_major, "test");
  printk("------unregister_chrdev-- ok------\n");
}
MODULE_LICENSE("GPL");
MODULE_AUTHOR("
panhuachu@hotmail.com
");


------------------------------------




本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/33226/showart_497152.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP