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

2023-11-26

Edit:我已经发现seq_file这简化了将大量数据从内核写入用户空间的过程。我正在寻找的是相反的;一种有助于从用户空间读取大量数据(多于一页)的 API。

Edit 2:我正在实施一个端口<stdio.h>作为能够打开的内核模块/proc(以及后来的其他虚拟文件系统)类似于FILEs 并处理输入和输出类似于<stdio.h>。你可以找到该项目here.


我发现了很多关于内核如何将大量数据写入 /proc(供用户空间程序使用)的问题,但没有找到相反的方法。让我详细说明一下:

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

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

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_file显然仅适用于内核想要的情况write数据给用户而不是read(或者可能是 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)。

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

Problem

这种方法的主要问题是过于复杂。当情况变得更加复杂时get_string添加,或者读取的整数可能是十六进制等。基本上,你必须重新发明sscanf!注意,sscanf可以在这个简单示例的步骤 4 中使用get_int而不是while循环(或也与get_string,但是当也可以输入十六进制时,情况会变得更加棘手(想象一下十六进制数字在 0 和 x0212ae4 之间被切割)。即便如此,它也只是取代了第 4 步get_int其余的东西应该仍然保留。

实际上,它给我带来了很多错误和大量测试来完善所有特殊情况。这是它在我看来不优雅的另一个原因。

问题

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

  • Linux内核中是否有一个已经实现的方法可以像普通的C一样对待FILE您可以从中获取数据并处理将数据分解为页面本身?
  • 如果不是,我是否让事情变得过于复杂并且我是否错过了一个明显的简单解决方案?
  • 我相信fscanf面临着类似的问题。这件事是如何处理的呢?

附带问题:我在互斥锁上阻止 /proc 读取器是一件可怕的事情吗?我的意思是,写入数据可能会阻塞,但我不确定这通常发生在用户空间还是内核空间。


您可能对 request_firmware() 接口感兴趣;整个事情在交给你之前都会被内核缓冲。

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • 在 2 个 .c 文件之间共享函数

    dir1有dir2 file1 c和file1 h dir2 有 file2 c 现在 如果我想在 file2 c 中访问 file1 c 中定义的函数 我需要在 file1 h 中声明它并在 file2 c 中包含 file1 h 这是一
  • 在子目录中构建共享库

    我正在尝试构建一个使用一些 C 代码的 R 包 我有一个编译为可执行文件的 C 库 可以从命令行调用 有一个与之关联的 Makefile 我正在尝试获取信息here http cran r project org doc manuals R
  • 多态性中基类缺少虚拟析构函数 = 资源泄漏?

    我们知道 如果要多态地使用基类 则需要将基类的析构函数指定为 virtual 否则程序中可能会出现资源泄漏 因为只会调用基类析构函数 而不会调用派生对象析构函数 我们还知道构造函数 析构函数纯粹是初始化 未初始化构造 而operator n
  • 错误 C2065:'cout':未声明的标识符

    我正在处理我的编程作业的 驱动程序 部分 但我不断收到这个荒谬的错误 错误 C2065 cout 未声明的标识符 我什至尝试过使用std cout但我收到另一个错误 IntelliSense 命名空间 std 没有成员 cout 当我宣布u
  • 将标准库添加到C++ eclipse项目中

    一个 非常 新手 C 问题 有没有办法自动将标准库添加到 C eclipse 项目中 我安装了 CDT 主要功能插件 您可以手动添加 STL 标头的路径路径和符号 gt 包含选项卡 http help eclipse org galileo
  • 在 Windows 服务中使用 OleDb 从 Excel 读取数据?

    免责声明 我知道这是一种不好的做事方式 这是我们与客户的唯一选择 Problem 我们需要每隔 x 时间从 Excel 文件读取数据 数据通过第三方 Excel 插件不断变化 应用程序的环境是 Windows XP SP1 和 Net 2
  • VS2010中VSHost.exe不断启动

    我正在 VS2010 中使用一个包含大量项目的解决方案 但它不断变得无响应 我注意到的一件事可能是一条线索 尽管我尚未开始任何调试 但 MyApplicationName vshost exe 不断出现在进程列表中 也许每当构建发生时它就会
  • ASP.NET 中的 thread.sleep

    我正在为我的网站模拟彗星实时馈送协议 因此在我的控制器中我添加 while nothing new before timeout Thread Sleep 1000 但我注意到添加此功能后整个网站变慢了 调试后我得出结论 当我打电话时Thr
  • 持续运行的 C# 代码 - 服务还是单独的线程?

    我有一个 NET 4 Web 应用程序 它有 3 个关联的独立项目 DAL BAL 和 UI 我正在使用实体框架进行数据库交互 我有代码循环遍历一堆数据库数据 根据找到的内容调用方法 然后更新数据库 我希望这段代码一直运行 同时 我希望用户
  • Excel 2007 中的数值 - 底层 xml 文件中的表示与存储

    这个问题与 NET和OpenXml有关 我已经阅读了以下文章 它有很好的解释 但没有回答我的问题 Excel 2007 中数值的可视化与底层 xml 文件不一致 https stackoverflow com questions 58594
  • 内存不足异常

    我正在使用 C 和 asp net 开发一个网络应用程序 我一直收到内存不足的异常 该应用程序的作用是从数据源读取一堆记录 产品 可能是数百 数千 通过向导中的设置处理这些记录 然后使用处理的产品信息更新不同的数据源 虽然有多个 DB 类
  • 嘲笑会员用户

    我目前正在开发一个 asp net mvc 2 应用程序 它使用默认的 SqlMembershipProvider 进行身份验证 我已经实现了一个控制器方法 通过调用读取当前用户的 ProviderUserKeyMembership Get
  • 如何在Windows Azure上调用ffmpeg.exe转换音频文件?

    我在 Windows Azure 上运行 Web 角色来接收 AAC 音频文件 通过 base64 字符串上传 并将它们存储到 blob 中 现在效果很好 接下来 我还必须将它们转换为 MP3 并将 MP3 存储到 blob 中 我决定使用
  • 剥离 OLE 标头信息 (MS Access / SQL Server)

    我有一个 C 应用程序需要支持二进制数据库内容 图像等 当使用 MS Access 或 MS SQL Server 时 此数据被包装在 OLE 对象内 如何去除此 OLE 标头信息 请注意 我不能只查找特定标签的开头 因为内容可以是 png
  • Subsonic 3 ActiveRecord 嵌套选择导致 NotIn 错误?

    我有以下 Subsonic 3 0 查询 其中包含嵌套的 NotIn 查询 public List
  • 在 C# 中为 ListBox 分配数据源时,如何从 ListBox 中删除所选项目?

    在 C 中为 ListBox 分配数据源时 如何从 ListBox 中删除所选项目 尝试删除时出现错误 设置 DataSource 属性后 无法修改项目集合 但是当我尝试从数据源 数据表 中删除项目时 它会抛出错误 因为 数据行不在当前行集
  • PC 上 XNA 中的信箱和缩放

    有没有一种方法可以让我基本上以 1080p 或 720p 作为默认分辨率来开发 XNA 游戏 然后根据设置的分辨率将游戏中的所有内容缩放到适当的大小 而不必在每个 Sprite 中设置缩放因子Draw 方法 我的想法是 我可以基于 1080
  • 具有可导出私钥的证书的“错误密钥”例外

    我正在尝试使用非对称加密来加密然后解密文件 我已经使用 makecert 创建了一个测试证书并将其安装到我的个人本地计算机存储中 将来我必须在多个服务器上安装此证书 这就是为什么我使用 pe 标志创建它 即使用可导出的私钥 证书已成功创建并
  • 如何以一对一/零关系更新员工和身份用户

    我正在尝试更新员工记录 也想更新身份用户 如果我先单独更新身份用户 例如 UserManager Update user Context Entry employee State System Data Entity EntityState
  • 有关 Endian 性和 .Net 的详细信息?

    我有几个关于字节顺序的问题 这些问题足够相关 我保证将它们作为一个问题提出 1 字节顺序是由 Net还是由硬件决定的 2 如果是由硬件决定的 我怎样才能在C 中找出硬件的字节序 3 字节序是否影响二进制交互 例如 OR AND OR 或移位

随机推荐