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

2010年(40)

2009年(140)

2008年(224)

我的朋友

分类: LINUX

2008-09-26 11:03:52

kf701_dev->timer_char = 'A';
        init_timer
( &kf701_dev->timer );
        kf701_dev
->timer_interval = HZ * TIMER_INTERVAL;
        kf701_dev
->timer.function = timer_function;
        kf701_dev
->timer.expires = jiffies + kf701_dev->timer_interval;
        kf701_dev
->timer.data = (unsigned long)kf701_dev;
        add_timer
( &kf701_dev->timer );
        printk
(KERN_DEBUG "%s:init timer OK\n",DEVICE);

        
return SUCCESS;
}

static void __exit chardev_exit(void)
{
        dev_t devno
= MKDEV( major, minor );
        
// 以相反的顺序清除
        del_timer_sync
( &kf701_dev->timer );
        printk
(KERN_DEBUG "%s:del timer OK\n",DEVICE);
        kfree
( kf701_dev->buf );
        cdev_del
( &kf701_dev->cdev );
        kfree
( kf701_dev );
        printk
(KERN_DEBUG "%s:kfree OK\n",DEVICE);
        unregister_chrdev_region
( devno, 1 );
        printk
(KERN_DEBUG "%s:unregister device OK\n",DEVICE);
}

int chardev_open(struct inode *inode, struct file *file)
{
        
struct my_dev *dev = container_of(inode->i_cdev, struct my_dev, cdev);
        
file->private_data = dev;
        printk
(KERN_DEBUG "%s:open OK\n",DEVICE);
        
return SUCCESS;
}

int chardev_release(struct inode *inode, struct file *file)
{
        printk
(KERN_DEBUG "%s:release OK\n",DEVICE);
        
return SUCCESS;
}

ssize_t chardev_read
(struct file *file, char __user *buf, size_t count,loff_t *offset)
{
        
struct my_dev *dev = file->private_data;
        ssize_t retval
= 0;

        
if( down_interruptible(&dev->sem) )
                
return -ERESTARTSYS;
        
// 增加了对NONBLOCK的支持
        
while( 0 == dev->index )
        
{
                up
(&dev->sem);
                
if( file->f_flags & O_NONBLOCK )
                        
return -EAGAIN;
                
// 在这里准备睡眠,等待条件为真
                
if( wait_event_interruptible(dev->rq, (0 != dev->index)) )
                        
return -ERESTARTSYS; // 返回非0表示被信号中断
                
if( down_interruptible(&dev->sem) )
                        
return -ERESTARTSYS; // 先取得锁再检查条件
        
}

        
if( *offset >= dev->index )
                
goto out;
        
if( (*offset+count) > dev->index )
                
count = dev->index - *offset;
        
if( copy_to_user(buf, dev->buf + *offset, count) )
        
{
                retval
= -EFAULT;
                
goto out;
        
}
        
*offset += count;
        retval
= count;

out
:
        up
(&dev->sem);
        
return retval;
}

// omit offset argument for write

ssize_t chardev_write
(struct file *file, const char __user *buf, size_t count, loff_t *offset)
{
        
struct my_dev *dev = file->private_data;
        ssize_t retval
= -ENOMEM;
        
if( down_interruptible(&dev->sem) )
                
return -ERESTARTSYS;
        
if( count > dev->size )
                
count = dev->size - 1;
        
if( copy_from_user(dev->buf, buf, count) )
        
{
                retval
= -EFAULT;
                
goto out;
        
}
        dev
->index = count;
        retval
= count;

out
:
        up
(&dev->sem);
        
// 唤醒阻塞在 read select 上的进程
        
if( retval > 0 )
                wake_up_interruptible
(&dev->rq);
        
return retval;
}

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