如何替换返回EOF和字节计数读取的procfs条目的读取函数?



我正在努力更新我们的内核驱动程序,以便在Ubuntu 16.0.4上使用linux内核4.4.0。驱动程序最后使用 linux 内核 3.9.2。 在其中一个模块中,我们创建了一个 procfs 条目来读取/写入板载风扇监控值。风扇监控用于读取/写入CPU或GPU温度/调制等值。

该模块使用以下 API 创建 procfs 条目:

struct proc_dir_entry *create_proc_entry(const char *name, umode_t
mode,struct proc_dir_entry *parent);

像这样:

struct proc_dir_entry * proc_entry = 
create_proc_entry("fmon_gpu_temp",0644,proc_dir);
proc_entry->read_proc = read_proc;
proc_entry->write_proc = write_proc;

现在,read_proc以这种方式实现:

static int read_value(char *buf, char **start, off_t offset, int count, int *eof, void *data) {
int len = 0;
int idx = (int)data;
if(idx == TEMP_FANCTL)
len = sprintf (buf, "%d.%02dn", fmon_readings[idx] / TEMP_SAMPLES, 
fmon_readings[idx] % TEMP_SAMPLES * 100 / TEMP_SAMPLES);
else if(idx == TEMP_CPU) {
int i;
len = sprintf (buf, "%d", fmon_readings[idx]);
for( i=0; i < FCTL_MAX_CPUS && fmon_cpu_temps[i]; i++ ) {
len += sprintf (buf+len, " CPU%d=%d",i,fmon_cpu_temps[i]);
}
len += sprintf (buf+len, "n");
}
else if(idx >= 0 && idx < READINGS_MAX)
len = sprintf (buf, "%dn", fmon_readings[idx]);
*eof = 1;
return len;
}

此读取函数明确假定用户已提供足够的缓冲区空间来存储温度值。这在用户空间程序中得到了正确的处理。此外,对于对此函数的每次调用,读取值都是完整的,因此不支持/不需要对相同的温度值进行后续读取。 另外,如果我在 shell 的这个 procfs 条目上使用"cat"程序,"cat"程序会正确显示值。我认为,通过将 EOF 设置为 true 并返回读取字节计数来支持这一点。

新的 Linux 内核不再支持此 API。

我的问题是:

如何将此 API 更改为新的 procfs API 结构,保持功能相同:每次读取都应返回值,程序"cat"也应该正常工作并且不会进入无限循环?

Linux 上读取文件的主要用户界面是 read(2)。它在内核空间中的对在结构file_operations中.read函数。

内核空间(read_procseq_file等)中读取文件的所有其他机制实际上是.read函数的(参数化)实现。

内核将 EOF 指示器返回到用户空间的唯一方法是返回 0 作为读取的字节数。

即使你对 3.9 内核read_proc实现实际上也实现了eof标志,即在下次调用时返回 0。cat实际上执行了read第二次调用以查找该文件是结束的。

(此外,cat执行2 次以上的读取调用:第一次调用 1 作为计数,第二次调用计数等于页面大小减 1,最后一次调用剩余计数

"一次性"读取实现的最简单方法是在single_open()模式下使用seq_file

最新更新