简单字符设备无法按预期工作

时间:2017-10-22 18:20:46

标签: linux module linux-kernel operating-system kernel-module

我一直在为简单的角色设备和测试脚本编写代码。一切都妥善编译。字符设备有一个设备文件,make命令,insmod和rmmod命令等都可以正常工作,并且在检查/ var / log / syslog时有预期的输出。此外,测试脚本编译并运行而不返回被杀死或任何东西 - 除了以下问题之外,它具有预期的行为。

组装模块的任何内容似乎都没有任何问题。但是,当我运行我的测试脚本来评估我的设备/它的功能时,不会返回任何内容。例如,当我运行write并输入“hello world”时,它不会返回任何类型的错误。但是,如果我运行seek并将whence和offset设置为0,然后使用read,则它不会输出任何内容。但是,我在代码中找不到任何可以解释此行为的问题。 已编辑(此外,如果我检查日志,init和exit函数的kern警报会起作用,但其他任何kern警报都不会返回任何内容,这让我相信也许它们永远不会被输入,尽管我无法想象为什么会出现这种情况。)任何见解都会受到赞赏。我的角色设备如下所示:

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

#include <linux/fs.h>  //gets the functions for device driver coding
#include <linux/slab.h>
#include <asm/uaccess.h>  //move data b/t userspace and kernel

#define BUFFER_SIZE 1024
#define MAJOR_NUMBER 240
#define DEVICE_NAME "simple_character_device"

char device_buffer[BUFFER_SIZE];
int openNum = 0;
int closeNum = 0;
char* buffer;


ssize_t simple_char_driver_read (struct file *pfile, char __user *buffer, size_t length, loff_t *offset){

    int bytesRead = 0;
    if (*offset >=BUFFER_SIZE){
        bytesRead = 0;
        return bytesRead;
    }
    if (*offset + length > BUFFER_SIZE){
        length = BUFFER_SIZE - *offset;
    }
    printk(KERN_INFO "Reading from device\n");
    if (copy_to_user(buffer, device_buffer + *offset, length) != 0){
        return -EFAULT;
    }
    copy_to_user(buffer, device_buffer + *offset, length);
    *offset += length;
    printk(KERN_ALERT "Read: %s", buffer);
    printk(KERN_ALERT "%d bytes read\n", bytesRead); 
    return 0;
}

ssize_t simple_char_driver_write (struct file *pfile, const char __user *buffer, size_t length, loff_t *offset){
    printk(KERN_INFO "Writing to device\n");
    copy_from_user(device_buffer + *offset, buffer, length);
    *offset = strlen(device_buffer);
    printk(KERN_ALERT "%zu bytes written\n", strlen(buffer));
    printk(KERN_ALERT "%s", device_buffer);
    return length;
}

int simple_char_driver_open (struct inode *pinode, struct file *pfile){
    openNum++;
    printk(KERN_ALERT "Device opened %d times\n", openNum);
    return 0;
}

int simple_char_driver_close (struct inode *pinode, struct file *pfile){
    closeNum++;
    printk(KERN_ALERT "Device closed %d times\n", closeNum);
    return 0;
}

loff_t simple_char_driver_seek (struct file *pfile, loff_t position, int whence){
    printk(KERN_ALERT "!!!!!!!!%llx", position);
    switch (whence) {
        case SEEK_SET: 
            if (position < 0 || position >= BUFFER_SIZE){ 
                return -1;
            }
            pfile->f_pos = position;
            break;
        case SEEK_CUR:  
            pfile->f_pos += position;
            break;
        case SEEK_END: 
            pfile->f_pos = BUFFER_SIZE - position;
            break;
    }
    return 0;
}

struct file_operations simple_char_driver_file_operations = {

    .owner   = THIS_MODULE,
    .read = simple_char_driver_read,
    .write = simple_char_driver_write,
    .open = (*simple_char_driver_open),
    .release = simple_char_driver_close,  
    .llseek = simple_char_driver_seek,
};

static int simple_char_driver_init(void){
    printk(KERN_INFO "initializing/registering device\n");
    buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL);
    register_chrdev(MAJOR_NUMBER, DEVICE_NAME, &simple_char_driver_file_operations);
    return 0;
}

static void simple_char_driver_exit(void){
    printk(KERN_INFO "denitializing/unregistering device\n");
    if (buffer)
        kfree(buffer);
    unregister_chrdev(MAJOR_NUMBER, DEVICE_NAME);
}

module_init(simple_char_driver_init);
module_exit(simple_char_driver_exit);

如上所示,我有初始化和退出方法,从设备文件读取的方法,写入它的方法,以及寻找文件中特定位置的搜索方法。 在下面的测试文件中,read方法采用您想要读取的字节数的参数。搜索方法需要一个和一个偏移量。 write方法接受你想要写的字符串。

我的测试文件如下所示:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#define DEVICE "/dev/simple_character_device"
#define BUFFER_SIZE 1024

int main () {
    char command;
    char buffer[BUFFER_SIZE];
    int length, offsetVal, whence;
    int file = open(DEVICE, O_RDWR);
    while (1) {
        printf("\nr) Read from device\nw) Write to device\ns) Seek\ne) Exit device\nAnything else to continue reading and writing\n\nEnter command: ");
        scanf("%c", &command);
        switch (command) {
            case 'w':
            case 'W':
                printf("Enter data you want to write to the device: ");
                scanf("%s", buffer);
                write(file, buffer, BUFFER_SIZE);
                while (getchar() != '\n');
                break;
            case 'r':
            case 'R':
                printf("Enter the number of bytes you want to read: ");
                scanf("%d", &length);
                char* buffer = (char*)malloc(sizeof(char) *length);
                read(file, buffer, length);
                printf("Device output: %s\n", buffer);
                while (getchar() != '\n');
                break;
            case 's':
                printf("Enter an offset value: ");
                scanf("%d", &offsetVal);
                printf("Enter a value for whence (third parameter): ");
                scanf("%d", &whence);
                lseek(file, offsetVal, whence);
                while (getchar() != '\n');
                break;
            case 'e':
            case 'E':
                return 0;
            default:
                while (getchar() != '\n');
        }
    }
    close(file);
    return 0;
}

如果您对代码无法正常运行的原因有任何了解,请告诉我们。我对这个问题非常困惑。谢谢你的时间和帮助!

编辑:此外,如果我检查日志,init和exit函数的kern警报会起作用,但其他任何kern警报都不会返回任何内容,这让我相信也许它们永远不会被输入,尽管我无法弄清楚为什么会这样。此外,由于这个问题,我的问题不是建议的帖子链接的重复。该解决方案已经实施,但问题仍然存在。

0 个答案:

没有答案