这些参数在scull'中的含义是什么;s进程读取实现?
在LDD3(Linux设备驱动程序第三版手册)这些参数在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的
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
-要读取的文件中的偏移量偏移量
-要读取的字节计数计数
-指向int的指针,需要设置为非零,以防读取整个文件eof
-用户上下文,作为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.
}
}