如何通过/ proc文件解析传递给内核模块的大量数据?

前端之家收集整理的这篇文章主要介绍了如何通过/ proc文件解析传递给内核模块的大量数据?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
编辑:我发现seq_file简化了许多从内核到用户空间的数据.我正在寻找的是相反的一个API,可以从用户空间中读取大量数据(多个页面).

编辑2:我正在实现< stdio.h>作为能够打开/ proc(以及其他虚拟文件系统)的内核模块,类似于FILE并处理类似于< stdio.h>的输入和输出.你可以找到项目here.

我发现了很多关于内核如何将大量数据写入/ proc(用户空间程序)的问题,但是没有什么可以相反的.让我详细说明一下:

这个问题基本上是关于输入被标记化的算法(例如,int或int和string的混合等),因为数据可能在多个缓冲区之间被破坏.

例如,假设以下数据被发送到内核模块:

12345678 81234567 78123456 67812345 5678 1234 45678123 3456 7812 23456781

为了这个例子,我们假设Linux提供/ proc处理程序的页面大小是20字节(与真正的4KB相比).

从/ proc(在内核模块中)读取数据的功能然后可以看到数据:

call 1:
"12345678 81234567 78"
call 2:
"123456 67812345 5678"
call 3:
" 1234 45678123 3456 "
call 4:
"7812 23456781"

正如你可以看到的,当第一次通话中读取78时,它不应该被处理,直到下一个帧决定是78是整数还是一帧之间.

现在我发现seq_files显然只有当内核想要将数据写入用户而不是读取时(或者可能是HOWTO写得很糟糕).

我做了什么

到目前为止,我已经提供了以下解决方案(我正在从内存写入,所以我可能会错过一些错误检查,但是与我无关):

在初始化阶段(如init_module):

initialize mutex1 to 1 and mutex2 to 0
create /proc entry
call data_processor

/ proc读者:

1. down(mutex1)    /* down_interruptible of course,but let's not get into details */

2. copy_from_user to an internal buffer
   buffer_index = 0
   data_length = whatever the size is

3. strip spaces from end of buffer (except if all left from buffer is 1 space)
   if so,there_was_space_after = 1 else 0

4. up(mutex2)

我会解释为什么我稍后放空

get_int函数

wait_for_next = 0
number_was_cut = 0
last_number = 0

do
{
    1. down(mutex2)

    2. if (number_was_cut && !isdigit(buffer[buffer_index]))
           break     /* turns out it wasn't really cut
                        as beginning of next buffer is ' ' */
       number_was_cut = 0
       wait_for_next = 0

    3. while (buffer_index < data_length && !isdigit(buffer_index[buffer_index]))
           ++buffer_index;    /* skip white space */

    4. while (buffer_index < data_length && isdigit(buffer[buffer_index]))
           last_number = last_number * 10 + buffer[buffer_index++] - '0';

    5. if (buffer_index >= data_length && !there_was_space_after)
           number_was_cut = 1
           wait_for_next = 1
           up(mutex1)         /* let more data come in */
       else
           up(mutex2)         /* let get_int continue */
           break
} while (wait_for_next)

return last_number

data_processor函数(例如):

int first_num = get_int()
int sencod_num = get_int()
for i = first_num to second_num
    do_whatever(get_int())

说明:首先,参见data_processor.它不会涉及到如何读取数据的复杂性,所以它只是获得整数,并做任何它想要的.现在看看/ proc读者.它基本上等待data_processor调用get_int足够的时间来消耗所有当前数据(步骤1),然后将下一个缓冲区复制到内部存储器中,从而允许data_processor继续(步骤2).然后,需要删除尾随空格,以便get_int可以被简化(步骤3).最后,它向get_int发出信号,它可以开始读取数据(步骤4).

get_int函数首先等待数据到达(步骤1)(忽略现在的步骤2),它跳过任何不需要的字符(步骤3),然后开始读取数字(步骤4).阅读数字的结尾是两种可能性:达到缓冲区的结束(在这种情况下,如果/ proc读取器没有剥离任何空格,则可以在帧之间剪切数字)或满足白色空间.在前一种情况下,需要通知/ proc读取器读取更多的数据,并等待另一个周期将剩余的数字附加到当前数据,而在后一种情况下,它返回数字(步骤5).如果从最后一帧继续,请检查新帧是否以数字开头.如果没有,那么以前的号码实际上是一个整数,应该被返回.否则,需要继续将数字追加到最后一个号码(步骤2).

问题

这种方法的主要问题是过于复杂.当get_string被添加或读取整数可以是十六进制时,它变得复杂得多.基本上,你必须重新创建sscanf!请注意,在这个简单的例子中,sscanf可以在get_int的第4步而不是while循环中使用(或者也可以使用get_string,但是当十六进制输入也是可能的时候会变得更棘手)(想象十进制数在0和x0212ae4之间切换)即使如此,它只是取代了get_int的第四步,其余的东西仍然保留下来.

它实际上让我有很多错误和沉重的测试来完善所有的特殊情况.这就是为什么它看起来不优雅的另一个原因.

问题

我想知道是否有更好的方法来处理这个问题.我知道使用共享内存可能是一个选择,但是我正在寻找一个这个任务的算法(更多的好奇心,因为我已经有我的工作解决方案).进一步来说:

>在Linux内核中是否有一个已经实现的方法,可以像普通的C FILE那样对待,您可以从中获取数据,并将数据分解成页面本身?
>如果没有,我是否过度复杂的事情,我是否缺少一个明显的简单解决方案?
>我相信fscanf面临着类似的问题.这是如何处理的?

侧面的问题:这是一个可怕的事情,我阻止/ proc读取器上的互斥体?我的意思是,写数据可能是阻塞的,但我不知道通常是在用户空间还是内核空间中发生.

解决方法

request_firmware()接口可能是您感兴趣的;在将内容交给你之前,整个事情被内核缓冲.

否则,也许sysfs二进制属性接口比proc更有用?

猜你在找的C&C++相关文章