insmod命令加载字符设备驱动成功后,在/proc/devices文件内却并没有该驱动名字和主设备号信息

gongmin856 2013-05-05 08:06:10
insmod命令加载globalfifo字符设备驱动成功后,我从globalfifo_init函数打出的调试信息显示,系统分配给该设备的主设备号为253,次设备号为0,但在/proc/devices文件内却并没有该设备名字和主设备号信息.

以下是该设备驱动代码,请大家帮帮忙,看看是怎么回事啊?提前谢谢了!

#include<linux/cdev.h>
#include<linux/fs.h>
#include <linux/module.h>
#include<linux/sched.h>
#include<asm/uaccess.h>
#include<linux/slab.h>

#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 clear\n");
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 %lu\n", 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:%d\n", 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 < 0) ||((unsigned int)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 %d\n", 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 < 0)
return result;
}

printk("devno:%d,%d\n",MAJOR(devno),MINOR(devno));

/*动态申请设备结构体的内存*/
globalfifo_devp = kmalloc(sizeof(struct globalfifo_dev), GFP_KERNEL);
if (!globalfifo_devp) {
result = -ENOMEM;
goto fail_malloc;
}

memset(globalfifo_devp, 0, sizeof(struct globalfifo_dev));

globalfifo_setup_cdev(globalfifo_devp, 0);

sema_init(&(globalfifo_devp->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");
...全文
781 3 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
水枂 2021-06-30
  • 打赏
  • 举报
回复 1

遇到了同样的问题,也是在return上面出问题了,感谢

Carl_CCC 2013-05-06
  • 打赏
  • 举报
回复
两个问题,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;
gongmin856 2013-05-06
  • 打赏
  • 举报
回复
果然是这个问题,万分感谢楼上的解答!

1,324

社区成员

发帖
与我相关
我的任务
社区描述
主要是开发驱动技术
社区管理员
  • 驱动程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧