当前位置: 技术问答>linux和unix
insmod命令加载字符设备驱动成功后,在/proc/devices文件内却并没有该驱动名字和主设备号信息
来源: 互联网 发布时间:2017-04-10
本文导语: 本帖最后由 gongmin856 于 2013-05-05 20:09:31 编辑 insmod命令加载globalfifo字符设备驱动成功后,我从globalfifo_init函数打出的调试信息显示,系统分配给该设备的主设备号为253,次设备号为0,但在/proc/devices文件内却并没有该...
以下是该设备驱动代码,请大家帮帮忙,看看是怎么回事啊?提前谢谢了!
#include
#include
#include
#include
#include
#include
#define GLOBALFIFO_SIZE (0x1000) /*全家内存最大值4KB*/
#define MEM_CLEAR (0x1) /*清零全局内存*/
#define GLOBALFIFO_MAJOR (0) /*预设的GloabalMem的主设备号*/
static int globalfifo_major = GLOBALFIFO_MAJOR;
/*global_mem设备结构体*/
struct globalfifo_dev{
struct cdev cdev; /*cdev结构体*/
unsigned int current_len;/*fifo有效数据长度*/
unsigned char mem[GLOBALFIFO_SIZE]; /*全局内存*/
struct semaphore sem;/*并发控制用的信号量*/
wait_queue_head_t r_wait;/*阻塞读用的等待队列头*/
wait_queue_head_t w_wait;/*阻塞写用的等待队列头*/
};
struct globalfifo_dev *globalfifo_devp; /*设备结构体指针*/
int globalfifo_open(struct inode *inode, struct file *filp)
{
/*将设备结构体指针赋值给文件私有数据指针*/
filp->private_data = globalfifo_devp;
return 0;
}
int globalfifo_release(struct inode *inode, struct file *filp)
{
return 0;
}
static long globalfifo_ioctl(struct file *filep,unsigned int cmd, unsigned long arg)
{
struct globalfifo_dev *dev = filep->private_data;
switch(cmd) {
case MEM_CLEAR:
memset(dev->mem, 0x0, sizeof(dev->mem));
printk(KERN_INFO "globalmem is clearn");
break;
default:
return -EINVAL;
}
return 0;
}
static ssize_t globalfifo_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos)
{
unsigned long p = *ppos;
unsigned int count = size;
int ret = 0;
struct globalfifo_dev *dev = filp->private_data;
DECLARE_WAITQUEUE(wait, current);
down(&(dev->sem)); /*持有信号量*/
add_wait_queue(&dev->r_wait, &wait);
while(dev->current_len == 0)
{
if(filp->f_flags & O_NONBLOCK)
{
ret = -EAGAIN;
goto out;
}
__set_current_state(TASK_INTERRUPTIBLE); /*改变进程状态为睡眠*/
up(&dev->sem);
schedule();/*调度其他进程运行*/
if(signal_pending(current))
{
ret = -ERESTARTSYS;
goto out2;
}
down(&dev->sem);
}
if(p >= GLOBALFIFO_SIZE)
return 0;
if(count > (GLOBALFIFO_SIZE -p))
count = GLOBALFIFO_SIZE -p;
/*kernel space --> user's space*/
if(copy_to_user(buf, (void *)(dev->mem+p), count)) {
ret = -EFAULT;
goto out;
} else {
//*ppos += count;
memcpy(dev->mem, dev->mem + count, dev->current_len- count);
ret = count;
printk(KERN_INFO "read %u bytes from %lun", count, p);
wake_up_interruptible(&dev->w_wait); /*唤醒写等待队列*/
}
out:up(&dev->sem);
out2:remove_wait_queue(&dev->r_wait, &wait);/*移除等待队列*/
set_current_state(TASK_RUNNING);
return ret;
}
static ssize_t globalfifo_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos)
{
unsigned long p = *ppos;
unsigned int count = size;
int ret = 0;
struct globalfifo_dev *dev = filp->private_data;
DECLARE_WAITQUEUE(wait, current);
down(&(dev->sem)); /*持有信号量*/
add_wait_queue(&dev->w_wait, &wait);
while(dev->current_len == GLOBALFIFO_SIZE)
{
if(filp->f_flags & O_NONBLOCK)
{
ret = -EAGAIN;
goto out;
}
__set_current_state(TASK_INTERRUPTIBLE); /*改变进程状态为睡眠*/
up(&dev->sem);
schedule();/*调度其他进程运行*/
if(signal_pending(current))
{
ret = -ERESTARTSYS;
goto out2;
}
down(&dev->sem);
}
if(p >= GLOBALFIFO_SIZE)
return 0;
if(count > (GLOBALFIFO_SIZE -p))
count = GLOBALFIFO_SIZE -p;
/* user's space --> kernel space */
if(copy_from_user(dev->mem + dev->current_len, buf, count)) {
ret = -EFAULT;
goto out;
} else {
//*ppos += count;
ret = count;
printk(KERN_INFO "write %u bytes,cur_len:%dn", count, dev->current_len);
wake_up_interruptible(&dev->r_wait);
}
out:up(&dev->sem);
out2:remove_wait_queue(&dev->w_wait, &wait);/*移除等待队列*/
set_current_state(TASK_RUNNING);
return ret;
}
static loff_t globalfifo_lllseek(struct file *filp, loff_t offset, int orig)
{
loff_t ret = 0;
switch(orig) {
case 0:/*相对文件开始位置偏移*/
if ((offset GLOBALFIFO_SIZE)) {
ret = -EINVAL;
break;
}
filp->f_pos = (unsigned int)offset;
ret = filp->f_pos;
break;
case 1: /*根据文件当前位置偏移*/
if ((filp->f_pos + offset) > GLOBALFIFO_SIZE) {
ret = -EINVAL;
break;
}
filp->f_pos += (unsigned int)offset;
ret = filp->f_pos;
break;
default:
ret = -EINVAL;
break;
}
return ret;
}
static const struct file_operations globalfifo_filp = {
.owner = THIS_MODULE,
.llseek = globalfifo_lllseek,
.read = globalfifo_read,
.write = globalfifo_write,
.unlocked_ioctl = globalfifo_ioctl,
.open = globalfifo_open,
.release = globalfifo_release,
};
static void globalfifo_setup_cdev(struct globalfifo_dev *dev, int index)
{
int err;
int devno = MKDEV(globalfifo_major, index);
cdev_init(&dev->cdev, &globalfifo_filp);
dev->cdev.owner = THIS_MODULE;
err = cdev_add(&dev->cdev, devno, 1);
if (err)
printk(KERN_NOTICE "Error %d adding globalmem %dn", err, index);
}
int globalfifo_init(void)
{
int result;
dev_t devno = MKDEV(globalfifo_major, 0);
/*申请设备号*/
if (globalfifo_major)
result = register_chrdev_region(devno, 1, "globalfifo");
else {/*动态申请设备号*/
result = alloc_chrdev_region(&devno, 0, 1, "globalfifo");
if(result sem), 1);/*初始化信号量*/
init_waitqueue_head(&(globalfifo_devp->w_wait));/*初始化写等待队列头*/
init_waitqueue_head(&(globalfifo_devp->r_wait));/*初始化读等待队列头*/
fail_malloc:
unregister_chrdev_region(devno, 1);
return result;
}
void globalfifo_exit(void)
{
cdev_del(&globalfifo_devp->cdev);/*注销cdev*/
kfree(globalfifo_devp);
unregister_chrdev_region(MKDEV(globalfifo_major, 0), 1);
}
module_init(globalfifo_init);
module_exit(globalfifo_exit);
module_param(globalfifo_major, int , S_IRUGO);
MODULE_AUTHOR("Barry song");
MODULE_LICENSE("Dual BSD/GPL");
|
两个问题,1, 动态申请设备号的时候没有更新globalfifo_major的值
2
fail_malloc:
unregister_chrdev_region(devno, 1);
return result;
成功的话,在这之前需要return,不然申请后立刻退出,
return 0;加这句就可以了
fail_malloc:
unregister_chrdev_region(devno, 1);
return result;
2
fail_malloc:
unregister_chrdev_region(devno, 1);
return result;
成功的话,在这之前需要return,不然申请后立刻退出,
return 0;加这句就可以了
fail_malloc:
unregister_chrdev_region(devno, 1);
return result;