Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
这些参数在scull'中的含义是什么;s进程读取实现?_C_Linux_Linux Kernel_Linux Device Driver_Kernel Module - Fatal编程技术网

这些参数在scull'中的含义是什么;s进程读取实现?

这些参数在scull'中的含义是什么;s进程读取实现?,c,linux,linux-kernel,linux-device-driver,kernel-module,C,Linux,Linux Kernel,Linux Device Driver,Kernel Module,在LDD3(Linux设备驱动程序第三版手册)sculpipe中,静态int-scul\u-read\u-p\u-mem(char*buf,char**start,off\u-t offset,int-count,int*eof,void*data)中的参数是什么意思?具体来说,我不理解开始、页面和偏移量之间的区别 关于实际实施本身,我有很多问题(可以在下面找到): struct scull\u管道{ 等待队列\u头\u t inq,outq;/*读写队列*/ 字符*缓冲区,*结束;/*buf的

在LDD3(Linux设备驱动程序第三版手册)
sculpipe
中,静态int-scul\u-read\u-p\u-mem(char*buf,char**start,off\u-t offset,int-count,int*eof,void*data)中的参数是什么意思?具体来说,我不理解
开始
页面
偏移量
之间的区别

关于实际实施本身,我有很多问题(可以在下面找到):

struct scull\u管道{
等待队列\u头\u t inq,outq;/*读写队列*/
字符*缓冲区,*结束;/*buf的开始,buf的结束*/
int buffersize;/*用于指针算术*/
char*rp,*wp;/*在哪里读,在哪里写*/
int nreaders,nWriter;/*r/w开口数量*/
struct fasync_struct*异步_队列;/*异步读卡器*/
结构信号量sem;/*互斥信号量*/
struct cdev cdev;/*Char设备结构*/
};
国际船员协会排水管装置的数量*/
划船管道*划船设备;/*拟安装的排水管装置*/
/* ...... */
/*我们的proc-read实现*/
静态整数存储读取内存(char*buf,char**start,off\t offset,int count,
int*eof,void*data)
{
int i,len;
结构排水管*p;
#定义限制(页面大小-200)/*此大小后不再打印*/
*开始=buf;
len=sprintf(buf,“默认缓冲区大小为%i\n”,scull\u p\u buffer);
对于(i=0;ibuffer,p->end,p->buffersize);
len+=sprintf(buf+len,“rp%p wp%p\n”,p->rp,p->wp);
len+=sprintf(buf+len,“读卡器%i写卡器%i\n”,
p->nreaders,p->nWriter);
向上(&p->sem);
划船程序偏移(buf、start、offset和len);
}
*eof=(len=*len){
*偏移量-=*len;/*问题:这是为了什么*/
*len=0;
}
否则{
*start=buf+*偏移量;/*问题:为什么需要更改“start”*/
*偏移量=0;
}
}
该函数用于使用函数创建过程条目。谷歌搜索了5分钟,解释了传递给
create\u proc\u read\u entry
函数的函数指针中的参数。具有固定格式的是sais:

参数:
*buf:内核将一页内存分配给任何试图读取proc条目的进程。页面指针指向该缓冲区 写入数据的存储器。
**开始:当读取proc文件不应从文件的开头开始,而是从某个偏移量开始时,使用此指针。对于较小的读取,这通常设置为空。
off:从文件指针当前指向的文件开始的偏移量
计数:要读取的数据字节数
数据:从create_read_proc_entry函数调用传递的数据。
eof:设置为1表示文件结束

但过了一段时间,我也在网上找到了一些文档。它有点长,但我认为它是总结
start
参数的唯一来源:

        /*
         * How to be a proc read function
         * ------------------------------
         * Prototype:
         *    int f(char *buffer, char **start, off_t offset,
         *          int count, int *peof, void *dat)
         *
         * Assume that the buffer is "count" bytes in size.
         *
         * If you know you have supplied all the data you
         * have, set *peof.
         *
         * You have three ways to return data:
         * 0) Leave *start = NULL.  (This is the default.)
         *    Put the data of the requested offset at that
         *    offset within the buffer.  Return the number (n)
         *    of bytes there are from the beginning of the
         *    buffer up to the last byte of data.  If the
         *    number of supplied bytes (= n - offset) is 
         *    greater than zero and you didn't signal eof
         *    and the reader is prepared to take more data
         *    you will be called again with the requested
         *    offset advanced by the number of bytes 
         *    absorbed.  This interface is useful for files
         *    no larger than the buffer.
         * 1) Set *start = an unsigned long value less than
         *    the buffer address but greater than zero.
         *    Put the data of the requested offset at the
         *    beginning of the buffer.  Return the number of
         *    bytes of data placed there.  If this number is
         *    greater than zero and you didn't signal eof
         *    and the reader is prepared to take more data
         *    you will be called again with the requested
         *    offset advanced by *start.  This interface is
         *    useful when you have a large file consisting
         *    of a series of blocks which you want to count
         *    and return as wholes.
         *    (Hack by Paul.Russell@rustcorp.com.au)
         * 2) Set *start = an address within the buffer.
         *    Put the data of the requested offset at *start.
         *    Return the number of bytes of data placed there.
         *    If this number is greater than zero and you
         *    didn't signal eof and the reader is prepared to
         *    take more data you will be called again with the
         *    requested offset advanced by the number of bytes
         *    absorbed.
         */
我们可以在
copy_to_user
中使用
start
——该参数用于优化biiiig文件上的
proc
条目读取。用户可以传递非常小的
count
变量,但您需要读取biig文件。因此,您从proc read函数返回该文件的大小,并带有一个
*start
参数,该参数表示要读取的字节数。这样内核甚至可以传递
count=0
,但是proc\u read函数可以返回像
5000
一样的有效
*start
地址,稍后将在
copy\u to\u user
调用中使用它来加速读取

因此:

静态int scull_read_p_mem(char*buf,char**start,off\t offset,int count,int*eof,void*data)中的参数是什么意思

  • buf
    -将结果复制到的目标缓冲区
  • start
    -上面注释中解释的魔法指针用于加速过程读取
  • 偏移量
    -要读取的文件中的偏移量
  • 计数
    -要读取的字节计数
  • eof
    -指向int的指针,需要设置为非零,以防读取整个文件
  • data
    -用户上下文,作为
    create\u proc\u entry
    函数中的最后一个参数传递
关于实际实施本身,我有很多问题(可以在下面找到):

scullp\u proc\u offset
操作
buf
缓冲区内的
len
偏移量。如果<代码>偏移量!=0,则
scull\u read\u p\u mem
不需要从第一个字节读取,而是从某个字节的偏移量读取。因为它是惰性编写的,然后
snprintf
调用无论如何都会执行,所以需要对缓冲区进行“某种移位”

这个函数做什么?
-事实上,我认为这是一种有趣的方法,可以计算用户需要复制多少字节

这样做的目的是什么?
-不知道。看起来有问题,因为偏移量将变为负值。函数
/*FIXME this should use seq_file*/
上方的注释表示还有一些问题需要解决。我认为IDE可以在一次调用中准确地返回有关一个
scull\u p\u设备[I]
的信息

为什么您需要更改“开始”?
-这就是问题所在。如果*偏移量不同,则为0,如果我们有一些字节要重新计算
        /*
         * How to be a proc read function
         * ------------------------------
         * Prototype:
         *    int f(char *buffer, char **start, off_t offset,
         *          int count, int *peof, void *dat)
         *
         * Assume that the buffer is "count" bytes in size.
         *
         * If you know you have supplied all the data you
         * have, set *peof.
         *
         * You have three ways to return data:
         * 0) Leave *start = NULL.  (This is the default.)
         *    Put the data of the requested offset at that
         *    offset within the buffer.  Return the number (n)
         *    of bytes there are from the beginning of the
         *    buffer up to the last byte of data.  If the
         *    number of supplied bytes (= n - offset) is 
         *    greater than zero and you didn't signal eof
         *    and the reader is prepared to take more data
         *    you will be called again with the requested
         *    offset advanced by the number of bytes 
         *    absorbed.  This interface is useful for files
         *    no larger than the buffer.
         * 1) Set *start = an unsigned long value less than
         *    the buffer address but greater than zero.
         *    Put the data of the requested offset at the
         *    beginning of the buffer.  Return the number of
         *    bytes of data placed there.  If this number is
         *    greater than zero and you didn't signal eof
         *    and the reader is prepared to take more data
         *    you will be called again with the requested
         *    offset advanced by *start.  This interface is
         *    useful when you have a large file consisting
         *    of a series of blocks which you want to count
         *    and return as wholes.
         *    (Hack by Paul.Russell@rustcorp.com.au)
         * 2) Set *start = an address within the buffer.
         *    Put the data of the requested offset at *start.
         *    Return the number of bytes of data placed there.
         *    If this number is greater than zero and you
         *    didn't signal eof and the reader is prepared to
         *    take more data you will be called again with the
         *    requested offset advanced by the number of bytes
         *    absorbed.
         */
// context:
// 1. We have set start to be the beginning of buf
//     *start = buf;
// 2. We have fill some string into the buf and increment len
static void scullp_proc_offset(char *buf, char **start, off_t *offset, int *len)
{
    // If offset is zero, we are filling a new buf.
    // (Or we have finished catching up as shown below)
    // We can continue to do so until we reach buf size
    if (*offset == 0)
        return;

    // Otherwise, we have some offset to catch up to.
    if (*offset >= *len) {
        // The offset might be still ahead given we have filled len.
        // So, we reduce offset(meaning that we have done some catch up)
        // and reset len(because we are still working on old data)
        *offset -= *len;
        *len = 0;
    }
    else {
        // Or, the offset might be already behind us
        // So, we set start to indicate that the write starts from this address
        // (case 2 in fs/proc/generic.c#L76)
        // and reset offset (meaning that we are done with catching up)
        *start = buf + *offset;
        *offset = 0;
        // this part might lack the handling of len
        // but it might be true if the structure is the same between two calls.
    }
}