简体   繁体   中英

Simple character driver crash

I'm making a simple a simple character driver that is suppose to write to my char device "/dev/coffee_bean" and when read from, it should display the string "Hi There!" in the console. I read from the device via "cat /dev/coffee_bean", instead my system crashes and resets. Bellow is my source code. Thanks for help.

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/kdev_t.h>
#include <linux/types.h>
#include <linux/completion.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
#include <linux/semaphore.h>
MODULE_LICENSE("Dual BSD/GPL");

#define DEVICE_NAME "coffee_grinds"
#define COUNT 4
#define FIRST_MINOR 0
#define CONST_QUANTUM 4000
#define CONST_QSET 4000

int test;

module_param(test, int, S_IRUGO);

struct my_char_structure{
    struct cdev my_cdev;
    struct semaphore sem;
    unsigned int access_key;
    unsigned long size;
};

static dev_t dev_num;

int dev_open(struct inode *in_node, struct file *filp){
    struct my_char_structure *my_dev;

    my_dev = container_of(in_node->i_cdev, struct my_char_structure, my_cdev);
    filp->private_data = my_dev;
    return 0;
}

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

ssize_t dev_write(struct file *filp, const char __user *buff, size_t count, loff_t *offp){
    struct my_char_structure *my_dev = filp->private_data;
    ssize_t retval = -ENOMEM; /* value used in "goto out" statements */
    char *my_string;
    int counting;
    printk(KERN_ALERT "Write was accessed, Lol");
    if (down_interruptible(&my_dev->sem))
        return -ERESTARTSYS;
    my_string = kmalloc(count,GFP_KERNEL);
    counting = copy_from_user(my_string,buff,count);
    printk(KERN_ALERT "You wrote %s",my_string);
    kfree(my_string);
    up(&my_dev->sem);

    printk(KERN_ALERT "We wrote %d bytes",counting);
        return retval;
    // Here is some experimental code
}

    ssize_t dev_read(struct file *filp, char __user *buff, size_t count, loff_t *offp){
        struct my_char_structure *my_dev = filp->private_data;
        ssize_t retval = 0;
        char *my_string;

        printk(KERN_ALERT "Read was accessed Lol");

        if (down_interruptible(&my_dev->sem))
            return -ERESTARTSYS;
        my_string = "Hi there!";
        copy_to_user(buff,my_string,10);
        up(&my_dev->sem);
        return retval;

    }

struct file_operations fops = {
    .owner  = THIS_MODULE,
    .read   = dev_read,
    .write  = dev_write,
    .open   = dev_open,
    .release= dev_release,
};

int start_mod(void){
    //Because we are dealing with a fictitious device, I want
    //the driver to create my two devices with arbitrarly 
    //assigned major numbers.
    static struct my_char_structure Dev;
    static struct my_char_structure *my_dev = &Dev;
    int err;

    alloc_chrdev_region(&dev_num, FIRST_MINOR, COUNT, DEVICE_NAME);

    sema_init(&(my_dev->sem),1);

    cdev_init(&(my_dev->my_cdev), &fops);
    my_dev->my_cdev.owner = THIS_MODULE;
    my_dev->my_cdev.ops = &fops;// fops is my file operations struct

    err = cdev_add(&my_dev->my_cdev, dev_num, COUNT);
    if(err)
        printk(KERN_ALERT "There was an error %d.",err);
    printk(KERN_ALERT " insmod to major number %d",MAJOR(dev_num));

    return 0;   
}

void end_mod(void){

    unregister_chrdev_region(dev_num, COUNT);

}

module_init(start_mod);
module_exit(end_mod);

Things could go wrong before dev_read is reached. Did you see your KERN_ALERT message on the console?

Obviously that is not all there is to your source code, because the module is initialized, the character device registered, and there are other functions like the open routine. What makes you think the bug is in dev_read just because reading from the device crashes the machine?

sizeof(my_string) is sizeof(char *) which is 4 or 8. You're taking the size of the pointer. If you're on a 64 bit kernel, you will at most get Hi there without the ! when you have this debugged well enough to go that far. :)

Ie it is apparent that you might benefit from tutorials in the basics of C, like the difference between arrays and pointers.

Looking at the full code you have posted now, I don't see any obvious cause for the crash. The things you are doing are done in other drivers.

Just some observations.

There is very little error checking. That will bite you because the successful execution of the next thing generally depends on the successful execution the previous thing as a precondition.

Also, when you do get to the point that the read function is called without any crash, you will find that it doesn't produce anything because you return 0 and do not move the offset! Most programs will interpret the zero return as end-of-file.

You have to honor the buffer size that is passed in otherwise you will corrupt user space. The cat program might not do a read(fd, buf, 5); (note that 5 is less than the 10 bytes you are copying to user space) but something might.

By the way, copy_to_user and copy_from_user are functions you have to test for failure also and return -EFAULT to user space, telling the calling application it passed in a bad area.

To debug the crash, there are two traditional approaches. One is to add more printk statements. In a block of code where there are no branches, and printing isn't buffered, if one print statement produces output prior to the crash but another one doesn't, the crash is somewhere between them.

The other technique is to interpret the crash dump: machine registers, byte surrounding the instruction pointer, call trace, etc. If you have that info from the crash, you can usually pinpoint where the crash is and by looking at the machine code and the values of registers, you can guess what the C variables and data structures are doing.

Good luck.

不能仅仅通过查看代码就能看出来。您可以帮自己检查错误。在所有条件失败的地方,您都可以使用KERN_ERR来打印错误,还可以添加goto OUT(其中OUT:return -1),以便崩溃的机会很小。这可以肯定地告诉您哪里出了问题,还请先创建仅write函数,并检查其是否正常运行,然后再开始使用dev_read函数。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM