使用用户空间中的常规文件模仿 Linux 设备模型

Posted

技术标签:

【中文标题】使用用户空间中的常规文件模仿 Linux 设备模型【英文标题】:Mimicing the Linux device model with regular files in userspace 【发布时间】:2016-01-13 21:15:37 【问题描述】:

我想通过带有文件的目录结构来表示守护程序的状态。守护进程负责提供一个外壳接口来控制传感器。类似于 Linux 设备模型或 GPIO 控制台接口的实现方式,只是使用普通文件,在用户空间中用 Python 编写:)。

例子:

守护程序运行并创建列出可用传感器的目录结构。目录结构的外观示例:

sensors
`-- sensor1
    `-- sensor-ouput

sensor-ouput 只是一个普通文件,用作当前传感器值的抽象。

这是创建示例结构的代码:

import time,os

    if not os.path.exists('sensors/sensor1'):
        os.makedirs('sensors/sensor1')
    f = open('sensors/sensor1/sensor-ouput','w+')
    for i in range(100):
        time.sleep(1)
        f.seek(0)
        f.write(str(i))
        f.flush()
    f.close()

问题:

为什么我可以在守护进程运行时写入文件? echo 1 > sensor-ouput 不会报错。 只有一个进程写入文件并可能同时读取多个进程。在这些情况下,我是否遗漏了一些同步问题? 鉴于文件是在 ramfs 分区上打开的,这种方法是否落后于使用命名管道?

【问题讨论】:

因为你不能做内核能做的事情。绝对地;内核从不真正写入文件。命名管道是一个完全不同的问题的解决方案。 kernel never actually writes files 如果我将它们写入内存,它们也不会出现在这个解决方案中 如果您将文件写入 ramdisk,您仍在写入文件。 IMO 一种更好的方法是像内核那样做,即创建一个虚拟文件系统;使用保险丝很容易做到。当其他应用程序尝试读取(或执行其他操作)您公开的“假文件”时,fuse 会调用您的函数,而不是不断地向文件写入(可能无用的)内容(也会让您自己暴露于竞争条件等)。跨度> 【参考方案1】:

您可以写入文件,因为默认情况下文件未锁定。你需要用 os.lockf() 锁定它。

您的多个读者可能会在您期望相同的地方读取不同的值。考虑以下场景

作家写 10 阅读器 #1 读取 10 阅读器 #2 读取 10 作家写 11 阅读器 #3 读取 11

此时阅读器#3 与阅读器#1 和#2 相比处于不同的状态。

命名管道是 FIFO 结构,它们确保消息的顺序,而文件没有。另一方面,管道不是持久的,一旦消息被读取,它就会消失。

编辑:实际上 fcntl.flock() 可能是您想要锁定的,而不是 os.lockf()

【讨论】:

以上是关于使用用户空间中的常规文件模仿 Linux 设备模型的主要内容,如果未能解决你的问题,请参考以下文章

LDD-The Linux Device Model

Linux 的 IO 模型

linux设备模型与sys文件系统

聊聊Linux 五种IO模型

Linux设备模型_Uevent

嵌入式Linux设备驱动程序:用户空间中的设备驱动程序