根据ldd3写的小character driver,可以insmod后找不到major,rmmod有segment fault

发布于 2022-09-22 12:52:09 字数 6323 浏览 13 评论 0

这个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);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

伪装你 2022-09-29 12:52:09

可能是你的版本不一致的问题,不知道LZ用的是什么版本的内核?

终难遇 2022-09-29 12:52:09

原帖由 dreamice 于 2008-10-24 11:23 发表
可能是你的版本不一致的问题,不知道LZ用的是什么版本的内核?

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

谈场末日恋爱 2022-09-29 12:52:09

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

一世旳自豪 2022-09-29 12:52:09
  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 编辑 ]

顾冷 2022-09-29 12:52:09

下面是成功编译的代码,发出来给大家参考,最近在看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);

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文