How to copy_to_user a string and use offp in a Linux Kernel read function

醉酒当歌 提交于 2020-01-03 03:05:34

问题


Declared:

static char status[128] = "off\0";

and implemented a read function:

static ssize_t read_proc(struct file *filep, char __user *buf,
                    size_t len, loff_t *offp)
{
    ssize_t cnt = strlen(status), ret;

    ret = copy_to_user(buf, status, cnt);
    *offp += cnt;
    return cnt;
}
  • How do I take into account the offp?
  • currently it prints endless the status to screen

回答1:


Thanks the guys comments here I came up with the following implementation, which I believe is the right way to use offp:

static ssize_t read_proc(struct file *filep, char __user *buf,
                    size_t len, loff_t *offp)
{

    ssize_t cnt = strlen(status), ret;

    /* ret contains the amount of chare wasn't successfully written to `buf` */
    ret = copy_to_user(buf, status, cnt);
    *offp += cnt - ret;

    /* Making sure there are no left bytes of data to send user */
    if (*offp > cnt)
         return 0;
    else
         return cnt;
}



回答2:


your read_proc() will not stop reading until the function returns "0" or error. I believe you need to modify your read_proc to have this logic.




回答3:


To understand the return value from read let me quote from Linux Device Drivers 3rd edition:

The return value for read is interpreted by the calling application program:

    If the value equals the count argument passed to the read system call, the requested number of bytes has been transferred. This is the optimal case.

    If the value is positive, but smaller than count, only part of the data has been transferred. This may happen for a number of reasons, depending on the device. Most often, the application program retries the read. For instance, if you read using the fread function, the library function reissues the system call until completion of the requested data transfer.

    If the value is 0, end-of-file was reached (and no data was read).

    A negative value means there was an error. The value specifies what the error was, according to <linux/errno.h>. Typical values returned on error include -EINTR (interrupted system call) or -EFAULT (bad address).

So in short You need to always update offp and check on it's value before you start reading, and return 0 if it already passed your data length, and in case of partial reads return the number of bytes read, you will update the offp in this case so the next call to read will result to returning 0 if you passed the length of data.

static ssize_t read_proc(struct file *filep, char __user *buf,
                size_t len, loff_t *offp)
{
    size_t count = len, status_length = strlen(status);
    ssize_t retval = 0;
    unsigned long ret = 0;

    if (*offp >= status_length)
        goto out;
    if (*offp + len > status_length)
        count = status_length - *offp;

    /* ret contains the amount of chars wasn't successfully written to `buf` */
    ret = copy_to_user(buf, status, count);
    *offp += count - ret;
    retval = count - ret;

out:
    return retval;
}

References:

  • Linux Device Drivers 3rd edition - Chapter 3


来源:https://stackoverflow.com/questions/21032073/how-to-copy-to-user-a-string-and-use-offp-in-a-linux-kernel-read-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!