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

时间:2016-06-21 04:30:26

标签: linux-kernel kernel-module

我正在努力更新我们的内核驱动程序,以便在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.%02d\n", 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, "%d\n", fmon_readings[idx]);
    *eof = 1;
    return len;
}

此读取功能肯定假定用户已提供足够的缓冲空间来存储温度值。这在用户空间程序中正确处理。此外,对于对此函数的每次调用,读取值都是完整的,因此对于相同温度值的后续读取不存在支持/需要。 另外,如果我使用&#34; cat&#34;来自shell的这个procfs条目的程序,&#39; cat&#39;程序正确显示值。我认为,这可以通过将EOF设置为true并返回读取字节数来支持。

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

我的问题是:

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

1 个答案:

答案 0 :(得分:1)

Linux上读取文件的主要用户界面http://twig.sensiolabs.org/doc/tags/macro.html。它在内核空间中的对是{em> struct file_operations 中的.read函数。

内核空间中读取文件的所有其他机制 read_proc seq_file 等)实际上是{的参数化)实现{ {1}}功能。

  

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

对3.9内核实现的.read实现实际上将read_proc标志实现为在下次调用时返回0。并且eof实际执行了cat第二次调用以查找该文件已结束。

(此外,read执行两次以上的读取调用:首先执行计数,其次是计数等等页面大小减1,最后一个剩余计数。)

“一次性”读取实现的最简单方法是在cat模式下使用 seq_file