免费注册 查看新帖 |

Chinaunix

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

[驱动] 求助!!卸载驱动时,模块仍在使用中。module is in use [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-11-16 17:43 |只看该作者 |倒序浏览
我刚接触驱动开发。学习资料是Linux Device Drivers 3rd。我根据书中的代码,稍微改写了一下,结果试验时就出现以下情况了。
求高手指导!!
1. 编译通过,用complete.init start加载模块时,Failed,但是,查看、proc/devices文件显示该模块已经加载上了,有major number。但是,

用complete.init stop卸载该模块时,出现module complete is in use的提示,不能卸载。此时,我再用complete.init start加载模块时,还是

Failed了,说是file exists,说明该模块已经加载上了。怎么办?

2. 情形如下
user 1:
cat /dev/complete
(block)

user 2:
echo "hello" > complete
(唤醒user1的cat程序,但是没有任何显示,同时,用户从root变为test(自动变的。。。)不懂了。

另外,附上源码。附件中我已经附上文件。
求高手指导。
  1. #ifndef _COMPLETEL_H_
  2. #define _COMPLETEL_H_


  3. struct complete_dev {
  4.         void* data;  /* Pointer to first quantum set */
  5.         struct cdev cdev;          /* Char device structure                */
  6. };

  7. void complete_cleanup(void);

  8. #endif /* _COMPLETEL_H_ */
复制代码

  1. #include <linux/module.h>
  2. #include <linux/init.h>

  3. #include <linux/sched.h>  /* current and everything */
  4. #include <linux/kernel.h> /* printk() */
  5. #include <linux/fs.h>     /* everything... */
  6. #include <linux/types.h>  /* size_t */
  7. #include <linux/cdev.h>
  8. #include <linux/errno.h>        /* error codes */
  9. #include <linux/completion.h>
  10. #include <asm/uaccess.h>        /* copy_*_user */
  11. #include "complete.h"

  12. MODULE_LICENSE("Dual BSD/GPL");
  13. MODULE_AUTHOR("James Chen");

  14. static int complete_major = 0;
  15. struct complete_dev* complete_device;

  16. DECLARE_COMPLETION(comp);

  17. int complete_trim(struct complete_dev *dev)
  18. {
  19.         if (dev->data)
  20.                 {
  21.                 kfree(dev->data);
  22.                 dev->data = NULL;
  23.                 }
  24.         return 0;
  25. }

  26. int complete_open(struct inode *inode, struct file *filp)
  27. {       
  28.          
  29.          /*struct complete_dev *dev; */  /* device information */
  30.         /*
  31.         dev = container_of(inode->i_cdev, struct complete_dev, cdev);
  32.         */
  33.         filp->private_data = complete_device; /* for other methods */

  34.         /* now trim to 0 the length of the device if open was write-only */
  35.         if ( (filp->f_flags & O_ACCMODE) == O_WRONLY) {
  36.                 complete_trim(complete_device); /* ignore errors */
  37.         }
  38.         return 0;          /* success */
  39. }

  40. int complete_release(struct inode *inode, struct file *filp)
  41. {
  42.         return 0;
  43. }

  44. ssize_t complete_read (struct file *filp, char __user *buf, size_t count, loff_t *pos)
  45. {
  46.         struct complete_dev *dev = filp->private_data;
  47.         printk(KERN_DEBUG "process %i (%s) going to sleep\n",
  48.                         current->pid, current->comm);
  49.         wait_for_completion(&comp);
  50.         printk(KERN_DEBUG "awoken %i (%s)\n", current->pid, current->comm);
  51.         copy_to_user(buf, dev->data, count);
  52.         return 0; /* EOF */
  53. }

  54. ssize_t complete_write (struct file *filp, const char __user *buf, size_t count,
  55.                 loff_t *pos)
  56. {
  57.         struct complete_dev *dev = filp->private_data;
  58.         printk(KERN_DEBUG "process %i (%s) awakening the readers...\n",
  59.                         current->pid, current->comm);
  60.         complete(&comp);
  61.         copy_from_user(dev->data, buf, count);
  62.         return count; /* succeed, to avoid retrial */
  63. }


  64. struct file_operations complete_fops = {
  65.         .owner = THIS_MODULE,
  66.         .open = complete_open,
  67.         .release = complete_release,
  68.         .read =  complete_read,
  69.         .write = complete_write,
  70. };


  71. int complete_init(void)
  72. {
  73.         int result;
  74.         dev_t devno;
  75.         /*
  76.          * Register your major, and accept a dynamic number
  77.          */
  78.          /*int  devno = MKDEV(complete_major, 0);*/
  79.         result = register_chrdev(complete_major, "complete", &complete_fops);
  80.         if (result < 0)
  81.                 goto fail;
  82.         if (complete_major == 0)
  83.                 complete_major = result; /* dynamic */
  84.         devno = MKDEV(complete_major, 0);
  85.        
  86.         complete_device= kmalloc(1 * sizeof(struct complete_dev), GFP_KERNEL);
  87.         if (!complete_device) {
  88.                 result = -ENOMEM;
  89.                 goto fail;  /* Make this more graceful */
  90.         }
  91.         complete_device->data = kmalloc(1024, GFP_KERNEL);
  92.         if (!complete_device->data) {
  93.                 result = -ENOMEM;
  94.                 goto fail;  /* Make this more graceful */
  95.         }
  96.         memset(complete_device, 0,1 * sizeof(struct complete_dev));
  97.         memset(complete_device->data, 0, 1024);
  98.        
  99.         cdev_init(&complete_device->cdev, &complete_fops);
  100.         complete_device->cdev.owner = THIS_MODULE;
  101.         complete_device->cdev.ops = &complete_fops;

  102.         result = cdev_add (&complete_device->cdev, devno, 1);
  103.         /* Fail gracefully if need be */
  104.         if (result)
  105.                 {
  106.                         goto fail;
  107.                 }
  108.        
  109.         return 0;

  110.         fail:
  111.                 complete_cleanup();
  112.                 return result;
  113. }

  114. void complete_cleanup(void)
  115. {
  116.         if (complete_device)
  117.                 {
  118.                         complete_trim(complete_device);
  119.                         cdev_del(&complete_device->cdev);
  120.                         kfree(complete_device);
  121.                 }
  122.        
  123.         unregister_chrdev(complete_major, "complete");
  124. }

  125. module_init(complete_init);
  126. module_exit(complete_cleanup);
复制代码
init脚本如下
#!/bin/bash
# Sample init script for the a driver module <rubini@linux.it>

DEVICE="complete"
SECTION="misc"

# The list of filenames and minor numbers: $PREFIX is prefixed to all names
PREFIX="complete"
FILES="     0 0     "

INSMOD=/sbin/insmod; # use /sbin/modprobe if you prefer

function device_specific_post_load () {
    true; # fill at will
}
function device_specific_pre_unload () {
    true; # fill at will
}

# Everything below this line should work unchanged for any char device.
# Obviously, however, no options on the command line: either in
# /etc/${DEVICE}.conf or /etc/modules.conf (if modprobe is used)

# Optional configuration file: format is
#    owner  <ownername>
#    group  <groupname>
#    mode   <modename>
#    options <insmod options>
CFG=/etc/${DEVICE}.conf

# kernel version, used to look for modules
KERNEL=`uname -r`

#FIXME: it looks like there is no misc section. Where should it be?
MODDIR="/lib/modules/${KERNEL}/kernel/drivers/${SECTION}"
if [ ! -d $MODDIR ]; then MODDIR="/lib/modules/${KERNEL}/${SECTION}"; fi

# Root or die
if [ "$(id -u)" != "0" ]
then
  echo "You must be root to load or unload kernel modules"
  exit 1
fi

# Read configuration file
if [ -r $CFG ]; then
    OWNER=`awk "\\$1==\"owner\" {print \\$2}" $CFG`
    GROUP=`awk "\\$1==\"group\" {print \\$2}" $CFG`
    MODE=`awk "\\$1==\"mode\" {print \\$2}" $CFG`
    # The options string may include extra blanks or only blanks
    OPTIONS=`sed -n '/^options / s/options //p' $CFG`
fi


# Create device files
function create_files () {
    cd /dev
    local devlist=""
    local file
    while true; do
        if [ $# -lt 2 ]; then break; fi
        file="${DEVICE}$1"
        mknod $file c $MAJOR $2
        devlist="$devlist $file"
        shift 2
    done
    if [ -n "$OWNER" ]; then chown $OWNER $devlist; fi
    if [ -n "$GROUP" ]; then chgrp $GROUP $devlist; fi
    if [ -n "$MODE"  ]; then chmod $MODE  $devlist; fi
}

# Remove device files
function remove_files () {
    cd /dev
    local devlist=""
    local file
    while true; do
        if [ $# -lt 2 ]; then break; fi
        file="${DEVICE}$1"
        devlist="$devlist $file"
        shift 2
    done
    rm -f $devlist
}

# Load and create files
function load_device () {
   
    if [ -f $MODDIR/$DEVICE.ko ]; then
        devpath=$MODDIR/$DEVICE.ko
    else if [ -f ./$DEVICE.ko ]; then
        devpath=./$DEVICE.ko
    else
        devpath=$DEVICE; # let insmod/modprobe guess
    fi; fi
    if [ "$devpath" != "$DEVICE" ]; then
        echo -n " (loading file $devpath)"
    fi

    if $INSMOD $devpath $OPTIONS; then
        MAJOR=`awk "\\$2==\"$DEVICE\" {print \\$1}" /proc/devices`
        remove_files $FILES
        create_files $FILES
        device_specific_post_load
    else
        echo " FAILED!"
     fi
}

# Unload and remove files
function unload_device () {
    device_specific_pre_unload
    /sbin/rmmod $DEVICE
    remove_files $FILES
}


case "$1" in
  start)
     echo -n "Loading $DEVICE"
     load_device
     echo "."
     ;;
  stop)
     echo -n "Unloading $DEVICE"
     unload_device
     echo "."
     ;;
  force-reload|restart)
     echo -n "Reloading $DEVICE"
     unload_device
     load_device
     echo "."
     ;;
  *)
     echo "Usage: $0 {start|stop|restart|force-reload}"
     exit 1
esac

exit 0

LLD练习complete小程序.rar

3.36 KB, 下载次数: 42

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP