免费注册 查看新帖 |

Chinaunix

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

根据ldd3写的小character driver,可以insmod后找不到major,rmmod有segment fault [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-10-24 08:46 |只看该作者 |倒序浏览
这个driver的主要功能就是在kernel memory里开辟一个空间,存数据,将来可以把它读出来。小弟是初学者,请各位大侠不吝赐教,源码如下:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>       
#include <linux/cdev.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
#include <linux/types.h>

#define DEVICE_NAME "prince"

int prince_major = 0;
int prince_minor = 0;
int prince_alloc_space = 1000;
int prince_dev_no = 1;

MODULE_AUTHOR("Prince Pei");
MODULE_LICENSE("Dual BSD/GPL");

struct prince_dev {
  char * msg;
  int alloc_space;
  int msg_size;
  struct cdev cdev;
} *prince_device;



int prince_trim(struct prince_dev *dev)
{
  if (dev->msg)
    kfree(dev->msg);
  dev->msg = NULL;
  dev->msg_size = 0;
  return 0;
}


int prince_open(struct inode *inode, struct file *filp)
{
  struct prince_dev *dev;  /*device information */

  dev = container_of(inode->i_cdev, struct prince_dev, cdev);
  filp->private_data = dev;  /* for other methods */
  
  if ((filp->f_flags & O_ACCMODE) == O_WRONLY) {
    prince_trim(dev);
  }
  return 0;
}



int prince_release(struct inode *inode, struct file *filp)
{
  return 0;
}

ssize_t prince_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
  struct prince_dev *dev = filp->private_data;
  int alloc_space = dev->alloc_space;
  ssize_t retval;

  if (!dev->msg) {
    dev->msg = kmalloc(alloc_space, GFP_KERNEL);
    if (!dev->msg)
      goto out;
  }

  if (count > alloc_space)
    count = alloc_space;

  dev->msg_size = count;

  if (copy_from_user(dev->msg, buf, count)) {
    retval = -EFAULT;
    goto out;
  }
  
  //*f_pos += count;
  retval = count;
  return count;  

out:
  return retval;
}

ssize_t prince_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
  struct prince_dev *dev = filp->private_data;

  ssize_t retval = 0;

  if (*f_pos >= dev->msg_size)
    goto out;
  if (*f_pos + count > dev->msg_size)
    count = dev->msg_size - *f_pos;

  if (dev->msg ==NULL)
    goto out;

  if (copy_to_user(buf, dev->msg, count)) {
    retval = -EFAULT;
    goto out;
  }

  *f_pos += count;
  retval = count;
  return retval;


out:
  return retval;
}

struct file_operations prince_fops = {
  .owner = THIS_MODULE,
  .open = prince_open,
  .release = prince_release,
  .read = prince_read,
  .write = prince_write,
};

void prince_cleanup_module(void)
{
  dev_t devno = MKDEV(prince_major, prince_minor);

  if (prince_device) {
    prince_trim(prince_device);
    cdev_del(&prince_device->cdev);
  }
  kfree(prince_device);

  unregister_chrdev_region(devno, 1);
}

static void prince_setup_cdev(struct prince_dev *dev)
{
  int err, devno = MKDEV(prince_major, prince_minor);

  cdev_init(&dev->cdev, &prince_fops);
  dev->cdev.owner = THIS_MODULE;
  dev->cdev.ops = &prince_fops;
  err = cdev_add(&dev->cdev, devno, prince_dev_no);

  if (err)
    printk(KERN_NOTICE "Error %d adding prince", err);
}
  
int prince_init_module(void)
{
  int result;
  dev_t dev = 0;

  if (prince_major)
    {
      dev = MKDEV(prince_major, prince_minor);
      result = register_chrdev_region(dev, prince_dev_no, DEVICE_NAME);
    }
  else
    {
      result = alloc_chrdev_region(&dev, prince_minor, prince_dev_no, DEVICE_NAME);
      prince_major = MAJOR(dev);
    }
  if (result < 0)
    {
      printk("<1>prince: can't get major %d\n", prince_major);
      return result;
    }

  prince_device = kmalloc(sizeof(struct prince_dev), GFP_KERNEL);
  if (!prince_device) {
    result = -ENOMEM;
    goto fail;
  }
  memset(prince_device, 0, sizeof(struct prince_dev));

  prince_device->alloc_space = prince_alloc_space;
  prince_device->msg_size = 0;

  prince_setup_cdev(prince_device);

fail:
  prince_cleanup_module();
  return result;
}



module_init(prince_init_module);
module_exit(prince_cleanup_module);

论坛徽章:
3
金牛座
日期:2014-06-14 22:04:062015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:45
2 [报告]
发表于 2008-10-24 11:23 |只看该作者
可能是你的版本不一致的问题,不知道LZ用的是什么版本的内核?

论坛徽章:
0
3 [报告]
发表于 2008-10-24 13:32 |只看该作者
原帖由 dreamice 于 2008-10-24 11:23 发表
可能是你的版本不一致的问题,不知道LZ用的是什么版本的内核?

2.6.26.3,是我自己编译的,module也是在相应的源码树下编译的!

论坛徽章:
3
金牛座
日期:2014-06-14 22:04:062015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:45
4 [报告]
发表于 2008-10-24 15:09 |只看该作者

回复 #3 sesedi 的帖子

这么新的内核,不知道会不会有问题。如果楼主是新手的话,我建议还是用稍微老一点的内核,比如说FC5,FC6的都行。

论坛徽章:
0
5 [报告]
发表于 2008-10-24 18:12 |只看该作者
  1. int prince_init_module(void)
  2. {
  3.   int result;
  4.   dev_t dev = 0;

  5.   if (prince_major)
  6.     {
  7.       dev = MKDEV(prince_major, prince_minor);
  8.       result = register_chrdev_region(dev, prince_dev_no, DEVICE_NAME);
  9.     }
  10.   else
  11.     {
  12.       result = alloc_chrdev_region(&dev, prince_minor, prince_dev_no, DEVICE_NAME);
  13.       prince_major = MAJOR(dev);
  14.     }
  15.   if (result < 0)
  16.     {
  17.       printk("<1>prince: can't get major %d\n", prince_major);
  18.       return result;
  19.     }

  20.   prince_device = kmalloc(sizeof(struct prince_dev), GFP_KERNEL);
  21.   if (!prince_device) {
  22.     result = -ENOMEM;
  23.     goto fail;
  24.   }
  25.   memset(prince_device, 0, sizeof(struct prince_dev));

  26.   prince_device->alloc_space = prince_alloc_space;
  27.   prince_device->msg_size = 0;

  28.   prince_setup_cdev(prince_device);
  29.   
  30.   
  31.   return 0;                <-------------------------------------------加这一句


  32. fail:
  33.   prince_cleanup_module();
  34.   return result;
  35. }
复制代码

[ 本帖最后由 richardhesidu 于 2008-10-24 18:13 编辑 ]

论坛徽章:
0
6 [报告]
发表于 2008-10-30 08:44 |只看该作者
下面是成功编译的代码,发出来给大家参考,最近在看ioctl和llseek,有问题再和大家讨论,谢谢大家!

#include <linux/init.h>
#include <linux/module.h>
//#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <asm/uaccess.h>

MODULE_AUTHOR("Prince Pei");
MODULE_LICENSE("Dual BSD/GPL");

static struct prince_dev {
  char *data;
  int quantum;
  unsigned long size; /* amount of data */
  struct cdev cdev;
};

struct prince_dev *prince_device;

static int prince_init_module(void);

static void prince_setup_cdev(struct prince_dev *);

static ssize_t prince_read(struct file *, char __user *, size_t, loff_t *);
//#include <unistd.h>
//ssize_t read(int filedes, void *buf, size_t nbytes);
static ssize_t prince_write(struct file *, const char __user *, size_t, loff_t *);
//#include <unistd.h>
//ssize_t write(int filedes, const void *buf, size_t nbytes);
static int prince_open(struct inode *, struct file *);
static int prince_trim(struct prince_dev *);

static int prince_release(struct inode *, struct file *);


static void prince_cleanup_module(void);

static int prince_major = 0;
static int prince_minor = 0;
static int prince_quantum = 4096;



static void prince_cleanup_module(void)
{
  dev_t devno = MKDEV(prince_major, prince_minor);

  if (prince_device) {

    if (prince_device->data)
      kfree(prince_device->data);

    cdev_del(&prince_device->cdev);

    kfree(prince_device);
  }
  printk("<1>prince_device was freed SUCCESSLY\n");

  //extern void unregister_chrdev_region(dev_t, unsigned);
  unregister_chrdev_region(devno, 1);

  printk("<1> unregister_character_device_region finish!\n");
}

static ssize_t prince_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
  printk("<1> prince_read() is invoked!\n");

  struct prince_dev *dev = filp->private_data;
  ssize_t retval = 0;

  if (*f_pos >= dev->size)
    goto out;
  if (*f_pos + count > dev->size)
    count = dev->size - *f_pos;
  if (dev->data == NULL)
    goto out;

  if (copy_to_user(buf, dev->data + *f_pos, count)) {
    retval = -EFAULT;
    goto out;
  }
  printk("<1> copy_to_user() SUCCESS!\n");

  *f_pos += count;
  retval = count;

out:
  return retval;
}

static ssize_t prince_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
  printk("<1> prince_write() is invoked!\n");

  struct prince_dev *dev = filp->private_data;
  int quantum = dev->quantum;

  ssize_t retval = -ENOMEM;

  if (dev->data == NULL) {
    dev->data = kmalloc(quantum, GFP_KERNEL);
    printk("<1> kmalloc(quantum, GFP_KERNEL) SUCCESS!\n");
    if (!dev->data) {
      printk("<1> kmalloc(quantum, GFP_KERNLE) FAIL!\n");      
      goto out;
    }
    memset(dev->data, 0, quantum);
  }

  if (count > quantum - *f_pos)
    count = quantum - *f_pos;

  if (copy_from_user(dev->data + *f_pos, buf, count)) {
    retval = -EFAULT;
    goto out;
  }
  printk("<1> prince_write() SUCCESS!\n");

  *f_pos += count;
  retval = count;

  if (dev->size < *f_pos)
    dev->size = *f_pos;


out:
  return retval;
}

static int prince_trim(struct prince_dev *dev)
{
  if (dev->data)
    kfree(dev->data);
  printk("<1> trim dev->data SUCCESS\n");
  dev->data = NULL;
  dev->quantum = prince_quantum;
  dev->size = 0;
  printk("<1> trim reinitial struct prince_dev SUCCESS\n");
  return 0;
}
static int prince_open(struct inode *inode, struct file *filp)
{
  printk("<1> prince_open() is invoked!\n");
  struct prince_dev *dev;

  dev = container_of(inode->i_cdev, struct prince_dev, cdev);
  printk("<1> container_of SUCCESS!\n");
  filp->private_data = dev;
  printk("<1> private_data SUCCESS!\n");

  if ((filp->f_flags & O_ACCMODE) == O_WRONLY) {
    prince_trim(dev);
    printk("<1> prince_open invoke prince_trim complete successfully\n");
  }
  return 0;
}

static int prince_release(struct inode *inode, struct file *filp)
{
  printk("<1> prince_release() is invoked!\n");
  return 0;
}

struct file_operations prince_fops = {
  .owner = THIS_MODULE,
  .read = prince_read,
  .write = prince_write,
  .open = prince_open,
  .release = prince_release,
};

static void prince_setup_cdev(struct prince_dev *dev)
{
  int err, devno = MKDEV(prince_major, prince_minor);

  cdev_init(&dev->cdev, &prince_fops);
  dev->cdev.owner = THIS_MODULE;
  dev->cdev.ops = &prince_fops;
  err = cdev_add(&dev->cdev, devno, 1);

  printk("<1> cdev add SUCCESS\n");
  if (err)
    printk("<1> Error %d adding scull\n", err);
}
static int prince_init_module(void)
{
  int result;
  dev_t dev = 0;

  if (prince_major)
    {
      dev = MKDEV(prince_major, prince_minor);
      result = register_chrdev_region(dev, 1, "prince");
    }
  else
    {
      result = alloc_chrdev_region(&dev, prince_minor, 1, "prince");
      prince_major = MAJOR(dev);
      printk("<1> get major SUCCESS!\n");
    }
  if (result < 0)
    {
      printk("<1>prince: cannot get major %d\n", prince_major);
      return result;
    }
  /* allocate the device */
  prince_device = kmalloc(sizeof(struct prince_dev), GFP_KERNEL);
  if (!prince_device)
    {
      result = -ENOMEM; //why
      goto fail; //how to implement fail:
    }

  memset(prince_device, 0, sizeof(struct prince_dev));

  printk("<1> allocate the device SUCCESS\n");

  prince_device->quantum = prince_quantum;
  prince_device->size = 0;

  prince_setup_cdev(prince_device);
  printk("<1> prince_device initialization complete\n");


  return 0;
fail:
  prince_cleanup_module();
  return result;
}



module_init(prince_init_module);
module_exit(prince_cleanup_module);
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP