gpt4 book ai didi

linux-kernel - 将旧设备文件用于 char 设备驱动程序

转载 作者:行者123 更新时间:2023-12-04 04:54:39 25 4
gpt4 key购买 nike

当我作为初学者尝试设备驱动程序时,我有两个问题。

  • 我创建了一个模块,加载了它,它动态地占用了主编号 251。次要设备的数量仅保留 1,即次要编号 0。为了进行测试,我在设备文件(使用 mknod 创建)上尝试了 echo 和 cat,它按预期工作。现在,如果我卸载模块但不删除/dev 条目并再次加载具有相同主编号的模块并尝试写入/读取之前使用的相同设备文件,内核崩溃。我知道我们不应该这样做,只是想了解在这种情况下会发生什么导致这次崩溃。我认为 VFS 可以做到这一点。
  • 当我在设备文件上执行 cat 时,读取会无限期地继续发生。为什么?要停止需要使用偏移操作。这看起来是因为默认读取的缓冲区长度为 32768?

  • 编辑:在此我进一步添加了一个 ioctl 函数,如下所示,然后我收到有关 init 和 cleanup 函数的存储类的错误,如果没有定义 ioctl,它们会很好地工作。没有得到 ioctl 和 init/cleanup 函数的存储类之间的链接。更新的代码已发布。错误如下:
        /home/diwakar/Documents/my_modules/first_test_module/flowTest.c:95:12: error: invalid storage class for function ‘flow_init’
    /home/diwakar/Documents/my_modules/first_test_module/flowTest.c: In function ‘flow_init’:
    /home/diwakar/Documents/my_modules/first_test_module/flowTest.c:98:2: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
    /home/diwakar/Documents/my_modules/first_test_module/flowTest.c: In function ‘flow_ioctl’:
    /home/diwakar/Documents/my_modules/first_test_module/flowTest.c:112:13: error: invalid storage class for function ‘flow_terminate’
    /home/diwakar/Documents/my_modules/first_test_module/flowTest.c:119:1: error: invalid storage class for function ‘__inittest’
    /home/diwakar/Documents/my_modules/first_test_module/flowTest.c:119:1: warning: ‘alias’ attribute ignored [-Wattributes]
    /home/diwakar/Documents/my_modules/first_test_module/flowTest.c:120:1: error: invalid storage class for function ‘__exittest’
    /home/diwakar/Documents/my_modules/first_test_module/flowTest.c:120:1: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
    /home/diwakar/Documents/my_modules/first_test_module/flowTest.c:120:1: warning: ‘alias’ attribute ignored [-Wattributes]
    /home/diwakar/Documents/my_modules/first_test_module/flowTest.c:120:1: error: expected declaration or statement at end of input
    /home/diwakar/Documents/my_modules/first_test_module/flowTest.c: At top level:
    /home/diwakar/Documents/my_modules/first_test_module/flowTest.c:73:13: warning: ‘flow_ioctl’ defined but not used [-Wunused-function]

    下面是代码:
    #include <linux/init.h>
    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/fs.h>
    #include <asm/uaccess.h>
    #include <linux/cdev.h>
    #include <linux/kdev_t.h>
    #include <linux/errno.h>
    #include <linux/ioctl.h>

    #define SUCCESS 0
    #define BUF_LEN 80

    #define FLOWTEST_MAGIC 'f'
    #define FLOW_QUERY _IOR(FLOWTEST_MAGIC,1,int)

    MODULE_LICENSE("GPL");
    int minor_num=0,i;
    int num_devices=1;
    int fopen=0,counter=0,ioctl_test;

    static struct cdev ms_flow_cd;
    static char c;

    ///// Open , close and rest of the things

    static int flow_open(struct inode *f_inode, struct file *f_file)
    {
    printk(KERN_ALERT "flowtest device: OPEN\n");
    return SUCCESS;
    }

    static ssize_t flow_read(struct file *f_file, char __user *buf, size_t
    len, loff_t *off)
    {
    printk(KERN_INFO "flowtest Driver: READ()\nlength len=%d, Offset = %d\n",len,*off);

    /* Check to avoid the infinitely printing on screen. Return 1 on first read, and 0 on subsequent read */
    if(*off==1)
    return 0;

    printk(KERN_INFO "Copying...\n");
    copy_to_user(buf,&c,1);
    printk(KERN_INFO "Copied : %s\n",buf);

    *off = *off+1;
    return 1; // Return 1 on first read


    }

    static ssize_t flow_write(struct file *f_file, const char __user *buf,
    size_t len, loff_t *off)
    {
    printk(KERN_INFO "flowtest Driver: WRITE()\n");
    if (copy_from_user(&c,buf+len-2,1) != 0)
    return -EFAULT;
    else
    {
    printk(KERN_INFO "Length len = %d\n\nLast character written is - %c\n",len,*(buf+len-2));
    return len;
    }
    }

    static int flow_close(struct inode *i, struct file *f)
    {
    printk(KERN_INFO "ms_tty Device: CLOSE()\n");
    return 0;
    }

    ///* ioctl commands *///

    static long flow_ioctl (struct file *filp,unsigned int cmd, unsigned long arg)
    {
    switch(cmd) {
    case FLOW_QUERY:
    ioctl_test=51;
    return ioctl_test;
    default:
    return -ENOTTY;
    }
    ///////////////////File operations structure below/////////////////////////

    struct file_operations flow_fops = {
    .owner = THIS_MODULE,
    .llseek = NULL,
    .read = flow_read,
    .write = flow_write,
    .unlocked_ioctl = flow_ioctl,
    .open = flow_open,
    .release = flow_close
    };


    static int flow_init(void)
    {
    printk(KERN_ALERT "Here with flowTest module ... loading...\n");
    int result=0;
    dev_t dev=0;
    result = alloc_chrdev_region(&dev, minor_num,
    num_devices,"mod_flowtest"); // allocate major number dynamically.

    i=MAJOR(dev);
    printk(KERN_ALERT "Major allocated = %d",i);

    cdev_init(&ms_flow_cd,&flow_fops);
    cdev_add(&ms_flow_cd,dev,1);

    return 0;
    }

    static void flow_terminate(void)
    {
    dev_t devno=MKDEV(i,0); // wrap major/minor numbers in a dev_t structure , to pass for deassigning.
    printk(KERN_ALERT "Going out... exiting...\n");
    unregister_chrdev_region(devno,num_devices); //remove entry from the /proc/devices
    }

    module_init(flow_init);
    module_exit(flow_terminate);

    最佳答案

    1- 你错过了cdev_del()在您的清理功能中。这意味着设备保持注册状态,但处理它的功能被卸载,因此崩溃。此外,cdev_add 可能在下一次加载时失败,但您不知道,因为您没有检查返回值。

    2-看起来没问题...您修改偏移量,返回正确的字节数,然后如果偏移量为1则返回0,表示EOF。但是你真的应该检查 *off >= 1。

    编辑-
    传递给您的读取处理函数的长度一直来自用户空间 read() .如果用户打开设备文件并调用 read(fd, buf, 32768); ,这只是意味着用户想要读取多达 32768 字节的数据。该长度一直传递给您的读取处理程序。如果你没有 32768 字节的数据要提供,你提供你所拥有的,并返回长度。现在,用户代码不确定这是否是文件的结尾,因此它会尝试再次读取 32768。你现在真的没有数据,所以你返回 0,它告诉用户代码它已经到达 EOF,所以它停止了。

    总之,您在读取处理程序中看到的某种默认值只是实用程序 cat 的 block 大小。用来阅读任何东西。如果您想在读取函数中看到不同的数字,请尝试使用 dd相反,因为它允许您指定 block 大小。

    dd if=/dev/flowtest of=/dev/null bs=512 count=1

    此外,这应该读取一个 block 并停止,因为您指定 count=1。如果省略 count=1,它将看起来更像 cat ,并尝试阅读直到 EOF。

    关于linux-kernel - 将旧设备文件用于 char 设备驱动程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16933015/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com