Простой сбой драйвера персонажа - PullRequest
2 голосов
/ 13 марта 2012

Я делаю простой простой символьный драйвер, который должен записывать на мое символьное устройство "/ dev / coffee_bean" и при чтении с него должна отображаться строка "Привет!" в консоли. Я читаю с устройства через "cat / dev / coffee_bean", вместо этого моя система падает и сбрасывается. Ниже - мой исходный код. Спасибо за помощь.

#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);

Ответы [ 3 ]

3 голосов
/ 13 марта 2012

Все может пойти не так, как будет достигнуто dev_read.Вы видели ваше KERN_ALERT сообщение на консоли?

Очевидно, что это не все, что есть в вашем исходном коде, потому что модуль инициализирован, символьное устройство зарегистрировано, и есть другие функции, такие как процедура open,Что заставляет вас думать, что ошибка в dev_read только потому, что чтение с устройства приводит к сбою машины?

sizeof(my_string) равно sizeof(char *), что равно 4 или 8. Вы берете размер указателя.Если вы работаете на 64-битном ядре, вы получите максимум Hi there без !, если отладите это достаточно хорошо, чтобы зайти так далеко.:)

Т.е. очевидно, что вы могли бы извлечь выгоду из учебников по основам C, таких как разница между массивами и указателями.

2 голосов
/ 13 марта 2012

Глядя на полный код, который вы разместили сейчас, я не вижу очевидной причины сбоя. То, что вы делаете, сделано в других драйверах.

Просто некоторые наблюдения.

Очень мало проверок ошибок. Это вас укусит, потому что успешное выполнение следующей вещи, как правило, зависит от успешного выполнения предыдущей вещи в качестве предварительного условия.

Кроме того, когда вы дойдете до того, что функция чтения вызывается без сбоев, вы обнаружите, что она ничего не производит, потому что вы возвращаете 0 и не перемещаете смещение! Большинство программ интерпретируют нулевой возврат как конец файла.

Вы должны соблюдать размер переданного буфера, иначе вы испортите пространство пользователя. Программа cat может не выполнять read(fd, buf, 5); (обратите внимание, что 5 меньше 10 байт, которые вы копируете в пространство пользователя), но что-то может.

Кстати, copy_to_user и copy_from_user - это функции, которые вы также должны проверять на наличие сбоя и возвращать -EFAULT в пространство пользователя, сообщая вызывающему приложению, что оно прошло в плохой области.

Для устранения сбоя существует два традиционных подхода. Один из них - добавить больше операторов printk. В блоке кода, где нет ветвей, и печать не буферизируется, если один оператор печати производит вывод до сбоя, а другой - нет, сбой находится где-то между ними.

Другой метод - интерпретировать аварийный дамп: регистры машины, байт, окружающий указатель команд, трассировку вызовов и т. Д. Если у вас есть эта информация из аварии, вы обычно можете точно определить, где происходит авария, и, глядя на машину код и значения регистров, вы можете догадаться, что делают переменные C и структуры данных.

Удачи.

1 голос
/ 22 сентября 2014

не может сказать, просто взглянув на код. Вы можете сделать себе одолжение для проверки ошибок. Во всех случаях, когда условия могут выйти из строя, вы можете использовать KERN_ERR для печати ошибок и вы можете добавить goto OUT (где OUT: return -1 ) так что шансы на сбой будут минимальными. Это может определенно сказать вам, где это неправильно. Также сначала создайте только функцию записи и проверьте, правильно ли она работает, а затем начните делать функцию dev_read.

...