在用户空间中实现Linux字符驱动程序

时间:2012-12-27 07:46:13

标签: linux input kernel drivers

我正在尝试为嵌入式Linux系统构建自定义操纵杆/游戏手柄设备。我正在寻找一个库或系统API,它允许我在用户空间代码的/ dev / input中创建一个节点。

我想这样做是因为:

  • 自定义硬件可以使用现有的SPI或I2C驱动程序与系统进行通信(这是我的硬件设计,因此我可以做任何最具技术意义的事情)

  • 内核模块不能使用其他驱动程序,只能从其他模块中导出符号

我理解制作内核模块的唯一方法是使用内核代码并将其编译为内核模块。我不是要尝试使用用户空间代码来实现内核模块。

我正在寻找一个允许我创建文件的API,当读取或写入该文件时,会调用函数。这是字符驱动程序的一般概念。我不需要内核提供或强加的特权或限制。

必须有一些方法来模拟不涉及编写全新内核模块的文件I / O.

谢谢!

6 个答案:

答案 0 :(得分:5)

您可以使用用户空间输入子系统执行您想要的操作,请参阅:

http://thiemonge.org/getting-started-with-uinput

以及示例用法:

http://pingus.seul.org/~grumbel/xboxdrv/

答案 1 :(得分:5)

老问题,但我想我会添加一个小插曲,所以看着这个的人不会得到错误的想法。大约在过去的3到4年里,出现了这个小框架,它被添加到扩展FUSE文件系统边缘,提供沙盒解决方案,以准确地完成提问者的要求。

它被称为CUSE,它允许字符驱动程序由在内核中打开FUSE和CUSE的系统上属于FUSE组的人实例化。所需要的只是一个合适的应用程序(您的发行版上的OSS适配守护程序只是一个这样的应用程序,FWIW ...)

当时的“你不能”之类的答案根本没有帮助,实际上没有考虑到这个问题,并且......嘿......非常错误整体......即便如此。

CUSE没有像FUSE那样多的吸收,所以用漂亮的易于使用的绑定形式做事情的帮助较少,但它仍然存在。让我参与这个主题的是我在寻找一个“更好”的答案,如果有一个关于这个主题。回答那里的结果是“是的,如果你可以做Python ...”(pycuse) - 如果你不能在那里做Python,你就是自己的。好吧......我从来没有接受过这样的事情......所以我将学习pycuse并制作一个C ++ / Go /等等。当我到达他们并且需要一个新的语言时,我需要它时我正在使用它。

至于剩下的......嘿......下次你的鸭子连续多了。你当然没有这个。

答案 2 :(得分:1)

尝试创建自己的char设备,然后编写一个与驱动程序通信的用户空间应用程序(我建议在这种情况下使用netlink,因为当其他驱动程序不导出符号时它可能用作后门,但它们打开用户空间的功能,在这种情况下,netlink帮助的用户空间可以作为网关)。

在您的自定义字符设备中,您可以让用户告诉您要创建的设备的路径。即char设备创建具有固定名称的初始char设备,然后用户app可以使用netlink(或ioctl)告诉此char设备创建具有自定义名称的另一个char设备。

希望这会有所帮助

答案 3 :(得分:1)

您正在描述viewos虚拟机

http://wiki.virtualsquare.org/wiki/index.php/Main_Page

http://wiki.virtualsquare.org/wiki/index.php/UMview#Modules

这个虚拟机可以劫持每个指向你内核的系统调用到你的用户空间模块(它被认为使linux变得不那么单一)

你用它启动一个umview实例 $umview xterm命令

所以在新生成的xterm中运行的每个程序都会被跟踪

现在你可以简单地(在umview实例中)一个

$um_add_service umdev
$mount -t umdevJoystick none <your file, for example /dev/virtualJoystick>

所以你可以编写一个模块来拦截你的/dev/virtualJoystick文件中的每个读/写/ ...并做你想做的事

(模块语法非常简单)

static int joystick_read(char type, dev_t device, struct dev_info *di){
    /*my operation...probably a XTestEvent() or something like that*/
}
static int joystick_write(char type, dev_t device, struct dev_info *di){
    /*my operation...probably a XTestEvent() or something like that*/
}
/*...*/
struct umdev_operations umdev_ops={
    /*hijacking table*/
    .read=joystick_read,
    .write=joystick_write,
};

(umview源代码中的umdev_testmodules dir作为一个小教程非常有用!;))

答案 4 :(得分:1)

由于存在一些限制,您可以使用LD_PRELOAD和库来考虑可以覆盖对设备的公共调用的应用程序。

see here for more details

答案 5 :(得分:-3)

你不能。

“字符设备”是指内核中面向字符的接口。

你可以做LIUB的建议,并创建一个类似融合的界面,将类似内核的API重新编入用户空间,如果你绝对需要HID风格,你将需要做这样的事情在/dev/input生成的设备。

然而,如果您实际上并不需要HID设备,并且因为它仅适用于您的硬件, ,您“不需要内核访问”,因为您实际上可以与用户空间中的低级硬件通信,您可以考虑其他一些选项:

  • 您可以使用XSendEventXTEST协议来合成本地事件。
  • 您可以构建一个网络服务器(或使用multicast unix-domain socket来有效分发数据的服务器),以便客户端进行连接。
  • 如果您希望客户真的只是read(),您可以使用fifo。当您的程序write()的数据包可以被PIPE_BUF(512字节)整除时,您可以guaranteed,它们不会在另一个数据包中意外交错。
相关问题