Chinaunix首页 | 论坛 | 博客
  • 博客访问: 309341
  • 博文数量: 20
  • 博客积分: 3011
  • 博客等级: 中校
  • 技术积分: 440
  • 用 户 组: 普通用户
  • 注册时间: 2007-03-12 10:01
文章分类

全部博文(20)

文章存档

2008年(20)

我的朋友

分类: LINUX

2008-03-15 17:11:02

文件: driver-all.rar
大小: 4KB
下载: 下载
/*
 * (C) copyright 2008
 */
#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<0)
  printk("register   *  failure\n");
 init_MUTEX(&sem);
 init_waitqueue_head(&outq);
 test_major=ret;
 return ret; 
}
*/
/*
static void __exit test_exit(void)
{
 int ret;
 ret=unregister_chrdev(test_major ,"test");
 if(ret<0)
  printk("unregister failure\n");
}
*/
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<0)
  printk("register eeee  failure\n");
 
 init_MUTEX(&sem);
 init_waitqueue_head(&outq);
 init_completion(&test_completion); //DECLARE_COMPLETION(test_completion);
 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("");
 
 
------------------------------------
 

 
阅读(1896) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~