博客首页 注册 建议与交流 排行榜 加入友情链接
推荐 投诉 搜索: 帮助

嵌入式linux

构建完善的嵌入式linux平台
   uClinux.cublog.cn
关于作者  
姓名:panhuachun@hotmail.com
职业:软件工程师
年龄:24
位置:China
个性介绍:构建优美的嵌入式平台

我的分类  




功能较为完善的驱动--并发,异步,阻塞,ioctl
文件: driver-all.rar
大小: 4KB
下载: 下载
/*
 * (C) copyright 2008 panhuachun@hotmail.com
 */
#define __NO_VERSION__
#include <linux/module.h>
#include <linux/config.h>
#include <linux/version.h>
#include <linux/wait.h>
#include <asm/uaccess.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <asm/page.h>
#include <linux/poll.h>
#include <linux/kdev_t.h>
#include <asm/semaphore.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
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("panhuachu@hotmail.com");
 
 
------------------------------------
 

 

 发表于: 2008-03-15,修改于: 2008-03-15 17:14 已浏览354次,有评论0条 推荐 投诉

  网友评论

  发表评论



Copyright © 2001-2006 ChinaUnix.net All Rights Reserved

感谢所有关心和支持过ChinaUnix的朋友们
页面生成时间:0.01479

京ICP证041476号