Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1213825
  • 博文数量: 404
  • 博客积分: 10011
  • 博客等级: 上将
  • 技术积分: 5382
  • 用 户 组: 普通用户
  • 注册时间: 2008-09-03 16:29
文章存档

2010年(40)

2009年(140)

2008年(224)

我的朋友

分类: LINUX

2008-09-26 10:59:11

/* * kf701_chardev.c
 * 2006-12-06 13:22:22
 * Contact me: kf701.ye AT gmail.com

 * 2.6内核字符驱动示例程序,供学习。
 * /dev/kf701_chardev0
 * /proc/devices
 *
分配1024个字节的buffer,/dev/kf701_chardev0的读写将
 *
作用到buffer上。目前的写操作会覆盖先前的buffer
 *
内核定时器每次向buffer里追加一个字符和一个回车。
 *
 *
测试方法:
 * $> echo "only for test" > /dev/kf701_chardev0
 * $> cat /dev/kf701_chardev0
 *
 * 2006-12-18 09:19:44
修改
 *
加入对 NONBLOCK poll 的支持。
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/cdev.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
#include <linux/ioctl.h>
#include <linux/poll.h>
#include <linux/wait.h>

int chardev_open(struct inode *, struct file *);
int chardev_release(struct inode *, struct file *);
ssize_t chardev_read
(struct file *, char __user *, size_t, loff_t *);
ssize_t chardev_write
(struct file *, const char __user *, size_t, loff_t *);
int chardev_ioctl(struct inode *,struct file *,unsigned int,unsigned long);
unsigned int chardev_poll(struct file* file, poll_table *wait);
void timer_function(unsigned long);

#define DEVICE "kf701_chardev"
#define SUCCESS 0
#define BUF_SIZE 1024
#define TIMER_INTERVAL 20 // 20秒运行一次定时器函数


int major = 233;
int minor = 0;

// define ioctl command

#define KF701_IOC_MAGIC 'K'
#define KF701_IO_RESET _IO(KF701_IOC_MAGIC,0)
#define KF701_IO_R _IOR(KF701_IOC_MAGIC,1,int)
#define KF701_IO_W _IOW(KF701_IOC_MAGIC,2,int)
#define KF701_IO_RW _IOWR(KF701_IOC_MAGIC,3,int)
#define KF701_IOC_MAXNR 4

struct file_operations fops = {
        
.owner = THIS_MODULE,
        
.read = chardev_read,
        
.write = chardev_write,
        
.open = chardev_open,
        
.release = chardev_release,
        
.ioctl = chardev_ioctl,
        
.poll = chardev_poll,
};

struct my_dev{
        wait_queue_head_t rq
; // 读取等待队列

        
uint8_t *buf;
        
uint32_t size;
        
uint32_t index;
        
struct semaphore sem;
        
struct cdev cdev;
        
struct timer_list timer;
        
char timer_char;
        
uint32_t timer_interval;
};

struct my_dev *kf701_dev;

static int __init chardev_init(void)
{
        
// 1. 分配主设备号

        dev_t devno
= MKDEV( major, minor );
        
int ret = register_chrdev_region( devno, 1, DEVICE );
        
if( ret < 0 )
        
{
          printk
(KERN_DEBUG "register major number failed with %d\n", ret);
          
return ret;
        
}
        printk
(KERN_DEBUG "%s:register major number OK\n",DEVICE);

        
// 2. 注册设备

        kf701_dev
= kmalloc(sizeof(struct my_dev), GFP_KERNEL);//分配内存
        
memset( kf701_dev, 0, sizeof(struct my_dev) );//内存管理
        cdev_init
( &kf701_dev->cdev, &fops );//初始化
        kf701_dev
->cdev.ops = &fops;
        kf701_dev
->cdev.owner = THIS_MODULE;
        ret
= cdev_add( &kf701_dev->cdev, devno, 1 );//设备注册函数
        
if( ret < 0 )
        
{
          printk
(KERN_DEBUG "register device failed with %d\n", ret);
          
return ret;
        
}
        printk
(KERN_DEBUG "%s:register device OK\n",DEVICE);

        
// 3. 分配本驱动要使用的内存

        kf701_dev
->index = 0;  //起始地址
        kf701_dev
->size = BUF_SIZE;//空间大小
        kf701_dev
->buf = kmalloc( kf701_dev->size, GFP_KERNEL );//分配空间
        
if( NULL == kf701_dev->buf )  //空间分配失败
        
{
          printk
(KERN_DEBUG "kmalloc failed\n");
          
return -ENOMEM;
        
}
        printk
(KERN_DEBUG "%s:kmalloc buffer OK\n",DEVICE);

        
// 4. 初始化信号量

        init_MUTEX
( &(kf701_dev->sem) );
        printk
(KERN_DEBUG "%s:init semaphore OK\n",DEVICE);

        
// 5. 初始化等待队列头

        init_waitqueue_head
(&kf701_dev->rq);

        
// 6. 初始化并启动定时器

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