在字符设备驱动程序中,打印语句在读取方法中执行无限时间

In Character Device Driver print statement executing infinite time in read method

我正在为字符设备驱动程序编写基本设备驱动程序模块。 我想要以下行为:当我使用 cat /dev/scull 从设备文件中读取时,我应该得到设备打开的次数。 为此,我使用变量 count 并在调用我的 open 函数时增加它。我将这个变量存储在私有结构中。 我遇到的问题是读取函数

struct scull_dev{
    int x;              /*Private data members*/
    struct cdev cdev;   /*This is character device structure*/
};

ssize_t scull_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
    struct scull_dev *dev = filp->private_data;

    pr_info("You have opened device %d times\n",dev->x);
    return sizeof(dev->x);
}

打印语句 "You have read device %d times" 正在打印无限次。我必须按 Ctr+D 才能停止它。

我希望输出到 cat 以及日志文件中。

注意:您获得无限输出是因为您总是返回 sizeof。而且,您没有将数据复制到 cat.

的代码

好的,我已经编写了我认为您需要的代码[请原谅一些无偿的样式清理]。注意:我没有构建它。我已经对其进行了一些注释,所以这应该可以帮助您入门:

struct scull_dev {
    int x;                              /*Private data members*/

    int rdpend;                         // 1=partial read in progress
    int bufoff;                         // current offset within buffer
    int buflen;                         // remaining length to transfer
    char buf[100];                      // buffer with text to output

    struct cdev cdev;                   /*This is character device structure*/
};

ssize_t scull_read(struct file *filp, char __user *buf, size_t count,
    loff_t *f_pos)
{
    struct scull_dev *dev = filp->private_data;
    ssize_t curlen;
    long err;

    // NOTES:
    // (1) rdpend _must_ be cleared in the device close (and/or) device
    //     open -- we only want _one_ output line per invocation
    // (2) _after_ you get this working, you might move _this_ code block
    //     to the open routine (i.e. the rdpend would not be necessary)
    // (3) leaving it here makes the pr_info and cat output appear closer in
    //     time
    do {
        // only output a single line per open
        if (dev->rdpend)
            break;
        dev->rdpend = 1;

        dev->buflen = snprintf(dev->buf,sizeof(dev->buf),
            "You have opened device %d times\n",dev->x);
        pr_info("%s",dev->buf);

        dev->bufoff = 0;
    } while (0);

    // get length and handle user short read
    // [possibly less than we have--(e.g.) caller's count could be (say) 10
    curlen = dev->buflen;
    if (curlen > count)
        curlen = count;

    do {
        // nothing left to output
        if (curlen <= 0)
            break;

        err = copy_to_user(buf,dev->buf + dev->bufoff,curlen);

        // probably an access violation or segmentation fault, etc.
        if (err < 0) {
            curlen = err;
            break;
        }

        // creep through the buffer
        dev->buflen -= curlen;
        dev->bufoff += curlen;
    } while (0);

    return curlen;
}

提醒:不要忘记在打开 and/or 关闭时清除 rdpend