免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 7172 | 回复: 18
打印 上一主题 下一主题

scull驱动奇怪的问题。不能运行。已解决 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-12-01 10:34 |只看该作者 |倒序浏览
本帖最后由 HJLin 于 2010-12-01 17:42 编辑

从昨天晚上开始发现这个问题一直美法解决。非常郁闷啊。。。

问题如下:
ldd3上面的例子,原来我是用一个文件(scull.c)全部实现的。运行没有问题。后来为了优化设计,我把各个功能拆开到多个文件中(scull_fops.h scull_fops.c scull.c)中。出现问题了,编译正常,但是insmod scull.ko加载之后(dmesg, /var/log/messages)没有任何反应。/proc/devices也没有生成scull设备。非常的郁闷啊。

下面是代码,请高手帮助小弟一把: scull.tar.gz (2.85 KB, 下载次数: 62)

论坛徽章:
0
2 [报告]
发表于 2010-12-01 10:38 |只看该作者
附上直观的代码,望高手方便赐教。。

Makefile
  1. obj-m := scull.o

  2. scull-objs := scull_fops.o

  3. KERNELDIR ?= /lib/modules/$(shell uname -r)/build
  4. PWD := $(shell pwd)
  5. default:
  6.         $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

  7. clean:
  8.         $(MAKE) -C $(KERNELDIR) M=$(PWD) clean
  9.         rm -fr *.o *.ko *.symvers *.mod.c
复制代码
scull_fops.h
  1. #ifndef _SCULL_FOPS_H_
  2. #define _SCULL_FOPS_H_

  3. #include <linux/sched.h>
  4. #include <linux/types.h>
  5. //file file_operations etc.
  6. #include <linux/module.h>
  7. #include <linux/fs.h>
  8. #include <linux/cdev.h>
  9. //copy
  10. #include <asm/uaccess.h>


  11. MODULE_LICENSE("Dual BSD/GPL");

  12. loff_t scull_llseek(struct file *, loff_t, int);
  13. ssize_t scull_read(struct file *, char __user *, size_t, loff_t *);
  14. ssize_t scull_write(struct file *, const char __user *, size_t, loff_t *);
  15. int scull_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
  16. int scull_open(struct inode *, struct file *);
  17. int scull_release(struct inode *, struct file *);

  18. struct scull_qset {
  19.   void **data;
  20.   struct scull_qset *next;
  21. };

  22. struct scull_dev {
  23.   struct scull_qset *data;  /* Pointer to first quantum set */
  24.   int quantum;  /* the current quantum size */
  25.   int qset;  /* the current array size */
  26.   unsigned long size;  /* amount of data stored here */
  27.   unsigned int access_key;  /* used by sculluid and scullpriv */
  28.   struct semaphore sem;  /* mutual exclusion semaphore  */

  29.   struct cdev cdev; /* Char device structure */
  30. };

  31. int scull_trim(struct scull_dev *dev);
  32. struct scull_qset *scull_follow(struct scull_dev *dev, int item);

  33. #endif
复制代码
scull_fops.c
  1. #include "scull_fops.h"

  2. struct scull_dev dev;
  3. //EXPORT_SYMBOL(dev);

  4. struct file_operations scull_fops = {
  5.   .owner = THIS_MODULE,
  6.   .llseek = scull_llseek,
  7.   .read = scull_read,
  8.   .write = scull_write,
  9.   .ioctl = scull_ioctl,
  10.   .open = scull_open,
  11.   .release = scull_release
  12. };
  13. //EXPORT_SYMBOL(scull_fops);


  14. loff_t
  15. scull_llseek(struct file *filp, loff_t offp, int count) {
  16.   return 0;
  17. }

  18. ssize_t
  19. scull_read(struct file *filp, char __user *buff, size_t count, loff_t *f_pos) {
  20.   printk("scull, scull_read() buff=%p, count=%i, *f_pos=%i\n", buff, count, *f_pos);
  21.   struct scull_dev *dev = (struct scull_dev*)filp->private_data;
  22.   struct scull_qset *p;
  23.   int quantum = dev->quantum;
  24.   int qset = dev->qset;
  25.   int itemsize = qset * quantum;
  26.   ssize_t retval = 0;

  27.   if (down_interruptible(&dev->sem))
  28.     return -ERESTARTSYS;
  29.   if (*f_pos >= dev->size)
  30.     goto out;
  31.   if (*f_pos + count > dev->size)
  32.     count = dev->size - *f_pos;

  33.   int item = (long)*f_pos / itemsize;
  34.   int rest = (long)*f_pos % itemsize;

  35.   int s_pos = rest / quantum;
  36.   int q_pos = rest % quantum;

  37.   //follow the list up to the right qset
  38.   p = scull_follow(dev, item);

  39.   //printk("p = %p \n", p);
  40.   //printk("p->data = %p \n", p->data);
  41.   //printk("p->data[s_pos] = %p \n", p->data[s_pos]);
  42.   
  43.   if (p == NULL || p->data == NULL || p->data[s_pos] == NULL ) {
  44.     printk("something is wrong\n");
  45.     goto out;
  46.   }
  47.    
  48.   char *str = p->data[s_pos] + q_pos;
  49.   //read only up to the end of this quantum
  50.   if (count > quantum - q_pos)
  51.     count = quantum - q_pos;
  52.   
  53.   if (copy_to_user(buff, p->data[s_pos] + q_pos, count) != 0) {
  54.     retval = -EFAULT;
  55.     goto out;
  56.   }  
  57.   
  58.   printk("scull, success read %i bytes\n", count);
  59.   *f_pos += count;
  60.   retval = count;

  61. out:
  62.   up(&dev->sem);
  63.   return retval;
  64. }

  65. ssize_t
  66. scull_write(struct file *filp, const char __user *buff, size_t count, loff_t *f_pos) {
  67.   printk("scull, scull_write() start, buff=%p, count=%i, *f_pos=%i\n", buff, count, *f_pos);   
  68.   struct scull_dev *dev = filp->private_data;
  69.   int itemsize = dev->qset * dev->quantum;

  70.   ssize_t retval = 0;
  71.   if (down_interruptible(&dev->sem)) {
  72.     return -ERESTARTSYS;
  73.   }
  74.   
  75.   int item = (long)*f_pos / itemsize;
  76.   int rest = (long)*f_pos % itemsize;
  77.   int s_pos = rest / dev->quantum;
  78.   int q_pos = rest % dev->quantum;
  79.   
  80.   struct scull_qset *p = scull_follow(dev, item);
  81.   if (p == NULL) {
  82.     printk("scull_follow() failed\n");
  83.     goto out;
  84.   }

  85.   if (p->data == NULL) {
  86.     p->data = kmalloc(sizeof(char*) * dev->qset, GFP_KERNEL);
  87.     if (p->data == NULL)
  88.       goto out;
  89.     memset(p->data, 0, sizeof(char*) * dev->qset);  
  90.   }
  91.   if ((p->data)[s_pos] == NULL) {
  92.     (p->data)[s_pos] = kmalloc(dev->quantum, GFP_KERNEL);
  93.     if ((p->data)[s_pos] == NULL)
  94.       goto out;
  95.   }
  96.   if (count > dev->quantum - q_pos)
  97.     count = dev->quantum - q_pos;

  98.   //printk("p = %p \n", p);
  99.   //printk("p->data = %p \n", p->data);
  100.   //printk("p->data[s_pos] = %p \n", p->data[s_pos]);

  101.   if (copy_from_user(p->data[s_pos] + q_pos, buff, count) != 0) {
  102.     retval = -EFAULT;
  103.     goto out;
  104.   }

  105.   retval = count;
  106.   *f_pos += count;
  107.   
  108.   if (dev->size < *f_pos) {
  109.     dev->size = *f_pos;
  110.   }
  111.   printk("scull, copy_from_user %i bytes\n", count);

  112. out:
  113.   up(&dev->sem);
  114.   return retval;
  115. }
  116. int
  117. scull_ioctl(struct inode *indoe, struct file *filp, unsigned int flag, unsigned long num) {
  118.   return 0;
  119. }

  120. int
  121. scull_open(struct inode *inode, struct file *filp) {
  122.   printk("scull, scull_open() start\n");
  123.   struct scull_dev *dev;
  124.   dev = container_of(inode->i_cdev, struct scull_dev, cdev);
  125.   filp->private_data = dev;

  126.   if ((filp->f_flags & O_ACCMODE) == O_WRONLY) {
  127.     scull_trim(dev);   
  128.   }
  129.   return 0;
  130. }

  131. int
  132. scull_release(struct inode *inode, struct file *filp) {
  133.   printk("scull, scull_release() start\n");
  134.   return 0;
  135. }

  136. int
  137. scull_trim(struct scull_dev *dev) {
  138.   printk("scull, scull_trim() start\n");
  139.   struct scull_qset *p = dev->data;
  140.   while (p != NULL) {
  141.     int i;
  142.     for (i=0; i<dev->qset; i++) {
  143.       kfree((p->data)[i]);
  144.     }
  145.     kfree(p->data);
  146.     struct scull_qset *next = p->next;
  147.     kfree(p);
  148.     p = next;
  149.   }

  150.   dev->size = 0;
  151.   dev->data = NULL;
  152.   return 0;
  153. }

  154. struct scull_qset *
  155. scull_follow(struct scull_dev *dev, int item) {
  156.   printk("scull, scull_follow() start\n");
  157.   struct scull_qset *p = dev->data;
  158.   if (dev->data == NULL) {
  159.     dev->data = kmalloc(sizeof(struct scull_qset), GFP_KERNEL);
  160.     if (dev->data == NULL)
  161.       return NULL;
  162.     p = dev->data;
  163.     p->next = NULL;
  164.     p->data = NULL;
  165.   }

  166.   while (item-- != 0) {
  167.     if (p->next == NULL) {
  168.       p->next = kmalloc(sizeof(struct scull_qset), GFP_KERNEL);
  169.       if (p->next == NULL)
  170.         return NULL;
  171.       p->next->data = NULL;
  172.       p->next->next = NULL;
  173.     }
  174.     p = p->next;
  175.   }

  176.   return p;
  177. }
复制代码
scull.c
  1. #include <linux/module.h>
  2. #include <linux/init.h>
  3. #include <linux/types.h>
  4. #include <linux/cdev.h>

  5. #include "scull_fops.h"

  6. extern struct scull_dev dev;
  7. extern struct file_operations scull_fops;

  8. dev_t devno;
  9. int major = 0;
  10. int minor = 0;
  11. int nr_devs = 4;

  12. //init
  13. int scull_init(void);
  14. //exit
  15. void scull_exit(void);
  16. //分配设备
  17. int alloc_dev(void);
  18. //注册设备
  19. int register_dev(void);

  20. int
  21. scull_init(void) {
  22.   printk("hello, scull\n");
  23.   printk("The process is \"%s\" (pid %i)\n", current->comm, current->pid);
  24.   if (alloc_dev() == -1) {
  25.     printk("scull: can't alloc devno, %i\n", major);
  26.     return -1;
  27.   }
  28.   if (register_dev() == -1) {
  29.     printk("scull, register_dev() failed\n");
  30.     return -1;
  31.   }
  32.   return 0;
  33. }

  34. void
  35. scull_exit(void) {
  36.   printk("Goodbye, scull %i,%i\n", major, minor);
  37.   unregister_chrdev_region(devno, nr_devs);
  38.   cdev_del(&dev.cdev);
  39. }

  40. int
  41. alloc_dev(void) {
  42.   int result = 0;
  43.   printk("scull, alloc_dev() start\n");
  44.   if (major == 0) {
  45.     result = alloc_chrdev_region(&devno, minor, nr_devs, "scull");
  46.     major = MAJOR(devno);
  47.   } else {
  48.     devno = MKDEV(major, minor);
  49.     result = register_chrdev_region(devno, nr_devs, "scull");
  50.   }
  51.   return result;
  52. }

  53. int
  54. register_dev(void) {
  55.   printk("scull, register_dev() start\n");
  56.   dev.data = NULL;
  57.   dev.quantum = 4000;
  58.   dev.qset = 1000;
  59.   dev.size = 0;
  60.   init_MUTEX(&dev.sem);
  61.   
  62.   cdev_init(&dev.cdev, &scull_fops);
  63.   dev.cdev.owner = THIS_MODULE;
  64.   dev.cdev.ops = &scull_fops;
  65.   return cdev_add(&dev.cdev, devno, 1);
  66. }

  67. module_init(scull_init);
  68. module_exit(scull_exit);
复制代码

论坛徽章:
3
金牛座
日期:2014-06-14 22:04:062015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:45
3 [报告]
发表于 2010-12-01 11:12 |只看该作者
你为什么要写这一行:
scull-objs := scull_fops.o

论坛徽章:
3
金牛座
日期:2014-06-14 22:04:062015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:45
4 [报告]
发表于 2010-12-01 11:13 |只看该作者
看起来应该是你的Makefile的问题

论坛徽章:
0
5 [报告]
发表于 2010-12-01 11:22 |只看该作者
本帖最后由 HJLin 于 2010-12-01 13:25 编辑

scull-objs := scull_fops.o 这个是说这个模块(scull)依赖哪些文件的。
如果不加,编译的话报警告找不到符号。
insmod失败


这个语法也是昨天网上查到的。

论坛徽章:
0
6 [报告]
发表于 2010-12-01 16:21 |只看该作者
编译没出现错误或者警告信息么?

论坛徽章:
0
7 [报告]
发表于 2010-12-01 16:26 |只看该作者
编译没有什么问题。就是一些代码混编的警告。


[root@localhost scull]# make
make -C /lib/modules/2.6.18-92.el5/build M=/root/ldd3/scull  modules
make[1]: Entering directory `/usr/src/kernels/2.6.18-92.el5-i686'
  CC [M]  /root/ldd3/scull/scull_fops.o
/root/ldd3/scull/scull_fops.c: In function ‘scull_read’:
/root/ldd3/scull/scull_fops.c:25: warning: format ‘%i’ expects type ‘int’, but argument 4 has type ‘loff_t’
/root/ldd3/scull/scull_fops.c:26: warning: ISO C90 forbids mixed declarations and code
/root/ldd3/scull/scull_fops.c:40: warning: ISO C90 forbids mixed declarations and code
/root/ldd3/scull/scull_fops.c:58: warning: ISO C90 forbids mixed declarations and code
/root/ldd3/scull/scull_fops.c:58: warning: unused variable ‘str’
/root/ldd3/scull/scull_fops.c: In function ‘scull_write’:
/root/ldd3/scull/scull_fops.c:79: warning: format ‘%i’ expects type ‘int’, but argument 4 has type ‘loff_t’
/root/ldd3/scull/scull_fops.c:80: warning: ISO C90 forbids mixed declarations and code
/root/ldd3/scull/scull_fops.c:88: warning: ISO C90 forbids mixed declarations and code
/root/ldd3/scull/scull_fops.c: In function ‘scull_open’:
/root/ldd3/scull/scull_fops.c:142: warning: ISO C90 forbids mixed declarations and code
/root/ldd3/scull/scull_fops.c: In function ‘scull_trim’:
/root/ldd3/scull/scull_fops.c:161: warning: ISO C90 forbids mixed declarations and code
/root/ldd3/scull/scull_fops.c:168: warning: ISO C90 forbids mixed declarations and code
/root/ldd3/scull/scull_fops.c: In function ‘scull_follow’:
/root/ldd3/scull/scull_fops.c:181: warning: ISO C90 forbids mixed declarations and code
  LD [M]  /root/ldd3/scull/scull.o
  Building modules, stage 2.
  MODPOST
  CC      /root/ldd3/scull/scull.mod.o
  LD [M]  /root/ldd3/scull/scull.ko
make[1]: Leaving directory `/usr/src/kernels/2.6.18-92.el5-i686'

论坛徽章:
0
8 [报告]
发表于 2010-12-01 17:14 |只看该作者
本帖最后由 EZWORD 于 2010-12-01 17:15 编辑

程序本身没有问题,问题在于程序太乱,以下我测试结果
insmod scull.ko
hello, scull
The process is "insmod" (pid 83)
scull, alloc_dev() start
scull, register_dev() start
cat /proc/device
251 scull   


简单的把那个scull_fops.c包进来。。。。。
makefile中
scull-objs := scull_fops.o
这一行要去掉

建议好好学学c的编程规范

论坛徽章:
0
9 [报告]
发表于 2010-12-01 17:19 |只看该作者
去试试吧,我这里就可以通过,而且出现设备了。

论坛徽章:
0
10 [报告]
发表于 2010-12-01 17:26 |只看该作者
回复 10# EZWORD


    你可以用,是按照我的源码,文件分开的吗?没有把scull_fops 合到scull.c 里面把?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP