Linux 简单字符设备未按预期工作

Linux 简单字符设备未按预期工作,linux,module,linux-kernel,operating-system,kernel-module,Linux,Module,Linux Kernel,Operating System,Kernel Module,我一直在为一个简单的字符设备和测试脚本编写代码。每样东西都编译得很好。字符设备有一个设备文件、make命令、insmod和rmmod命令等。所有这些命令都可以正常工作,并且在检查/var/log/syslog时具有预期的输出。此外,测试脚本编译和运行时不会返回killed或其他任何内容-除了以下问题之外,它具有预期的行为 组装模块时似乎没有任何问题。但是,当我运行测试脚本来评估我的设备/它的功能时,没有返回任何内容。例如,当我运行write并键入“helloworld”时,它不会返回任何类型的错

我一直在为一个简单的字符设备和测试脚本编写代码。每样东西都编译得很好。字符设备有一个设备文件、make命令、insmod和rmmod命令等。所有这些命令都可以正常工作,并且在检查/var/log/syslog时具有预期的输出。此外,测试脚本编译和运行时不会返回killed或其他任何内容-除了以下问题之外,它具有预期的行为

组装模块时似乎没有任何问题。但是,当我运行测试脚本来评估我的设备/它的功能时,没有返回任何内容。例如,当我运行write并键入“helloworld”时,它不会返回任何类型的错误。然而,若我运行seek并将whence和offset设置为0,然后使用read,它不会输出任何内容。但是,我在代码中找不到任何可以解释这种行为的问题Edited(另外,如果我检查日志,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);
#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;
}
#包括
#包括
#include//获取设备驱动程序编码的函数
#包括
#包括//移动数据b/t用户空间和内核
#定义缓冲区大小1024
#定义主要单元编号240
#定义设备名称“简单字符设备”
字符设备缓冲区[缓冲区大小];
int-openNum=0;
int closeNum=0;
字符*缓冲区;
简单字符驱动程序读取(结构文件*pfile,字符用户*buffer,大小长度,loff*t偏移量){
int字节读取=0;
如果(*偏移量>=缓冲区大小){
字节读取=0;
返回字节读取;
}
如果(*偏移+长度>缓冲区大小){
长度=缓冲区大小-*偏移量;
}
printk(内核信息“从设备读取”);
如果(复制到用户(缓冲区、设备缓冲区+*偏移量、长度)!=0){
返回-默认值;
}
复制到用户(缓冲区、设备缓冲区+*偏移量、长度);
*偏移量+=长度;
printk(内核警报“读取:%s”,缓冲区);
printk(内核警报“%d字节读取”,字节读取);
返回0;
}
简单字符驱动程序写入(结构文件*pfile,常量字符*user*缓冲区,大小长度,loff*t偏移量){
printk(内核信息“写入设备”\n);
从用户处复制用户(设备缓冲区+*偏移量、缓冲区、长度);
*偏移量=strlen(设备缓冲区);
printk(内核警报“%zu字节写入”,strlen(缓冲区));
printk(内核警报“%s”,设备缓冲区);
返回长度;
}
int simple_char_driver_open(结构索引节点*pinode,结构文件*pfile){
openNum++;
printk(内核警报“设备已打开%d次”,openNum);
返回0;
}
int simple\u char\u driver\u close(结构索引节点*pinode,结构文件*pfile){
closeNum++;
printk(KERN_警报“设备关闭%d次”,closeNum);
返回0;
}
loff\u t simple\u char\u driver\u seek(结构文件*pfile,loff\u t位置,int where){
printk(内核警报“!!!!!!!!!%llx”,位置);
开关(从何处){
案例集:
如果(位置<0 | |位置>=缓冲区大小){
返回-1;
}
pfile->f_位置=位置;
打破
个案查询:
pfile->f_位置+=位置;
打破
案件结束:
pfile->f_pos=缓冲区大小-位置;
打破
}
返回0;
}
结构文件\u操作简单\u字符\u驱动程序\u文件\u操作={
.owner=此_模块,
.read=简单字符驱动程序读取,
.write=simple\u char\u driver\u write,
.open=(*简单字符驱动程序打开),
.release=simple\u char\u driver\u close,
.llseek=simple\u char\u driver\u seek,
};
静态int简单字符驱动程序初始化(void){
printk(KERN_INFO“初始化/注册设备”);
buffer=kmalloc(缓冲区大小,GFP内核);
寄存器chrdev(主设备号、设备名和简单字符驱动程序文件操作);
返回0;
}
静态无效简单字符驱动程序退出(无效){
printk(KERN_INFO“拒绝/取消注册设备”);
if(缓冲区)
kfree(缓冲区);
注销chrdev(主要设备编号、设备名称);
}
模块初始化(简单字符驱动初始化);
模块退出(简单字符驱动程序退出);
如上所示,我有初始化和退出方法、读取设备文件的方法、写入设备文件的方法和查找文件中特定位置的查找方法。 在下面的测试文件中,read方法获取一个参数,即您希望读取的字节数。seek方法接受一个whence和一个offset。write方法接收您要写入的字符串

我的测试文件如下所示:

#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);
#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;
}
#包括
#包括
#包括
#包括
#定义设备“/dev/simple\u character\u设备”
#定义缓冲区大小1024
int main(){
char命令;
字符缓冲区[缓冲区大小];
整数长度,偏移值,从何处;
int文件=打开(设备,O_RDWR);
而(1){
printf(“\nr)从设备读取\nw)写入设备\ns)查找\ne)退出设备\n任何其他操作以继续读取和写入\n\n输入命令:”;
scanf(“%c”,命令(&c));
开关(命令){
案例“w”:
案例“W”:
printf(“输入要写入设备的数据:”;
scanf(“%s”,缓冲区);
写入(文件、缓冲区、缓冲区大小);
而(getchar()!='\n');
打破
案例“r”:
案例“R”:
printf(“输入要读取的字节数:”;
扫描频率(“%d”和长度);
char*buffer=(char*)malloc(sizeof(char)*长度);
读取(文件、缓冲区、长度);
printf(“设备输出:%s\n”,缓冲区);
而(getchar()!='\n');
打破
案例s:
printf(“输入偏移值:”);
scanf(“%d”和offsetVal);
printf(“输入