简体   繁体   English

如何在Linux中将/dev文件作为内核模块来解决读写操作?

[英]How to resolve reading and writing operations with /dev file as a kernel module in Linux?

Obviuosly, it's a unsuprising newbie's question after a lot of troubles with kernel programming.显然,在内核编程遇到很多麻烦之后,这是一个不足为奇的新手问题。 I try to launch a program that gets driver file in /dev folder available for some reading and writing (indeed, I realize it's rather unsafe idea, but I need strongly going ahead with all that experience).我尝试启动一个程序,让 /dev 文件夹中的驱动程序文件可用于一些读写(实际上,我意识到这是相当不安全的想法,但我需要强烈地继续所有这些经验)。 Let's look at a module source code:让我们看一个模块源代码:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <asm/uaccess.h>

MODULE_LICENSE("GPL");

int init_module(void); // driver file initialization as opening it
void cleanup_module(void); // exec files removal ahead of shutting driver file
static int device_open(struct inode *, struct file *); // driver file opening
static int device_release(struct inode *, struct file *); // return of system resource control
static ssize_t device_read(struct file *, char *, size_t, loff_t *); // reading from driver file
static ssize_t device_write(struct file *, const char *, size_t, loff_t *); // writing into driver file

#define SUCCESS 1
#define DEVICE_NAME "sample device"
#define BUF_LEN 80

static int Major; // device's major number
static int Device_Open = 0; // device access counter
static char message[BUF_LEN]; // buffer for both read and write operations
static char *message_ptr;

// list of basic operations executable by driver
static struct file_operations ops = {
        .read = device_read,
        .write = device_write,
        .open = device_open,
        .release = device_release
};

int init_module(void)
{
    Major = register_chrdev(0, DEVICE_NAME, &ops); // major number assignment

    // evaluate whether driver file is accessible
    if(Major < 0) {
        printk(KERN_ALERT "Device registration attempt failed\n");
        return Major;
    }

    return SUCCESS;
}

void cleanup_module(void)
{
    unregister_chrdev(Major, DEVICE_NAME); // cancelling driver registration in file system before exit
    printk(KERN_ALERT "Driver file of /dev/%s c %d 0 has been destroyed\n", DEVICE_NAME, Major);
    return;
}

static int device_open(struct inode * node, struct file * file)
{
    printk(KERN_INFO "Trying access /dev/%s c %d 0\n", DEVICE_NAME, Major);
    static int counter = 0; // access counter initializing

    // file control evaluation
    if(Device_Open)
        return -EBUSY;

    Device_Open++; // increment counter to avert driver's immanent running
    sprintf(message, "This sentence displayed %d times\n", counter++);
    message_ptr = message;

    try_module_get(THIS_MODULE);

    return SUCCESS;
}

static int device_release(struct inode * node, struct file * file)
{
    printk(KERN_INFO "Trying closure of /dev/%s c %d 0\n", DEVICE_NAME, Major);
    Device_Open--; // decrement counter to keep driver file removable as well
    module_put(THIS_MODULE);

    return SUCCESS;
}

static ssize_t device_read(struct file * file, char * ch, size_t num, loff_t * off)
{
    int read_bytes = 0; // output size
    printk(KERN_INFO "Trying read from /dev/%s c %d 0\n", DEVICE_NAME, Major);
    if(*message_ptr == 0)
        return 0;

    // loop-executed reading from file
    while(num && *message_ptr) {
        put_user(*(message_ptr++), ch++);
        num--;
        read_bytes++;
    }

    printk("%d bytes read, %d bytes to be handled", read_bytes, num);

    return read_bytes;
}


// updated stuff    
static ssize_t device_write(struct file *filp, const char *buff, size_t len, loff_t * off) 
{
    char message_from_user[BUF_LEN];    
    if(copy_from_user(message_from_user, buff, len)) return -EINVAL;
    printk(KERN_INFO "length of message:%d message:'%s'", (int)len,   message_from_user);
    return len; 
}

To test reading/writing, I use this code:为了测试读/写,我使用以下代码:

#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <linux/unistd.h>

extern int errno;

int main()
{
    int fd; // file descriptor id
    size_t cnt = 0; // input / output number of bytes
    size_t cnt_2 = 0;
    char inputBuffer[30] = "Device file is open"; // write operation buffer
    char outputBuffer[50]; // read operation buffer

    printf("Continuing with basics of Linux drivers...\n");

    // evaluate accessibility of driver file
    fd = open("/dev/dev", O_RDWR);
    if(fd == -1) {
        close(fd);
        printf("File opening isn't completed\n");
        return 1;
    }

    printf("Driver file is open now\n");

    // writing from file
    cnt = write(fd, inputBuffer, sizeof(inputBuffer));
    printf("Driver got written %d bytes\n", cnt);

    // read into file
    cnt = read(fd, outputBuffer, sizeof(outputBuffer));
    printf("Driver received %d bytes\n", cnt);

    int i = 0;

    // display an input message
    while(i < cnt) {
        printf("%c", outputBuffer[i]);
        printf("%s", "\n");
        i++;
    }

    close(fd); // wrap up driver connection and clear memory
    printf("Driver file is close\n");
    return 0;
}         

Altough the module was built in as well as dev file was made by mknod (I run it on Ubuntu 18.04), I'm stuck at write operation due to some miscomprehension of driver calls in user/kernel spaces.尽管模块是内置的,并且开发文件是由 mknod 制作的(我在 Ubuntu 18.04 上运行它),但由于对用户/内核空间中的驱动程序调用的一些误解,我被困在写操作上。 Once I start my program, outputs are here as follows:一旦我开始我的程序,输出如下:

Continuing with basics of Linux drivers...继续 Linux 驱动程序的基础知识...
Driver file is open now驱动程序文件现已打开
Driver got written -1 bytes驱动程序被写入 -1 字节

Followed by last line output, the system becomes inoperable (no response until I make off PC).紧接着是最后一行输出,系统无法运行(直到我关闭 PC 才响应)。 That's a case I think of like a matter of memory control or, most probably, some driver file properties.我认为这种情况与内存控制有关,或者很可能与某些驱动程序文件属性有关。 However, user rights have been granted to reading / writing / executing, no access restrictions are inferable indeed.但是,用户权限已被授予读/写/执行,确实没有任何访问限制。 Hopefully, it's possible to point out to what's wrongness in the code posted here.希望可以指出此处发布的代码中的错误。

Seeing your code you don't handle the writing part.看到你的代码你不处理写作部分。

static ssize_t device_write(struct file * file, const char * ch, size_t num, loff_t * off)
{
    printk(KERN_ALERT "Operation denied\n");
    return -EINVAL;
} 

Thus there is no way your module can possibly work.因此,您的模块不可能工作。

But your crash comes from memory accesses in your reading function (check this with strace ).但是您的崩溃来自阅读功能中的内存访问(请使用strace检查)。 I let you understand your issue.我让你明白你的问题。 dmesg should help (or in the case your system panics you can make the log persistant to debug it after rebooting your system). dmesg应该会有所帮助(或者在您的系统出现混乱的情况下,您可以在重新启动系统后使日志持久化以调试它)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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