从内核空间执行用户空间函数

Posted

技术标签:

【中文标题】从内核空间执行用户空间函数【英文标题】:Executing a user-space function from the kernel space 【发布时间】:2011-07-11 22:10:51 【问题描述】:

我在 linux 中编写了一个自定义设备驱动程序,它必须能够非常快速地响应中断。处理这个问题的代码已经存在于用户空间实现中,但是太慢了,因为它依赖于软件不断检查中断线的状态。经过一番研究,我发现您可以从内核模块注册这些中断线,并执行函数指针给出的函数。但是我们要执行的代码是在用户空间,有没有办法从内核空间模块调用用户空间的函数?

【问题讨论】:

【参考方案1】:

从内核调用用户空间函数很不走运,因为内核不知道也不应该知道单个用户空间应用程序的功能和逻辑,更不用说每个用户空间应用程序都有它自己的内存布局,不允许其他进程或内核以这种方式入侵(共享对象是这里的例外,但您仍然不能从内核空间利用它)。那么安全模型呢,你不应该首先在内核上下文中运行用户空间代码(在内核上下文中自动被认为是不安全的代码),因为这会破坏内核的安全模型。那一刻。现在考虑到上述所有内容,以及许多其他动机,您可能需要重新考虑您的方法并专注于内核 用户空间 IPC and Interfaces、文件系统或用户模式帮助程序 API(阅读下文)。

不过,您可以使用usermode-helper API 从内核调用用户空间应用程序。以下 IBM DeveloperWorks 文章将帮助您开始使用 usermode-helper Linux 内核 API:

Kernel APIs, Part 1: Invoking user-space applications from the kernel

【讨论】:

不推荐从内核调用用户空间应用程序来处理中断。它仅用于非常特殊的情况。 @kauppi - 你是对的,在我读到你的评论的那一刻,我已经经历了几个噩梦般的场景……也许对操作的唯一解决方案是将用户空间代码移植到内核编码或集成适当的内核用户空间 IPC/接口,以实现用户空间和内核空间通信,如果前者是不可能的。 从内核调用用户空间代码听起来像是恶意软件的终极攻击媒介。 您确定,内核模式无权访问用户模式内存空间吗?我相信内核模式没有限制,它可以访问一切。【参考方案2】:

我认为最简单的方法是注册一个字符设备,当设备有一些数据时它就准备好了。

任何尝试从此设备读取数据的进程,然后进入睡眠状态,直到设备准备好,然后被唤醒,此时它可以执行适当的操作。

如果您只是想表示准备就绪,阅读器可以只读取一个空字节。

然后用户空间程序只需要执行一个阻塞的 read() 调用,并且会被适当地阻塞,直到你唤醒它。

您需要了解内核调度程序的等待队列机制才能使用它。

【讨论】:

【参考方案3】:

听起来你的中断线已经通过 gpiolib 提供给用户空间了? (/sys/class/gpio/...)

如果 gpio 边缘触发和 poll() 对您来说足够快,您是否进行了基准测试?这样您就不必从用户空间应用程序轮询状态,但边缘触发将通过 poll() 报告它。请参阅内核源代码中的 Documentation/gpio.txt。

如果通过 sysfs 的边缘触发不够好,那么正确的方法是开发一个内核驱动程序来处理时间关键部分并通过 API(sysfs、设备节点等)将结果导出到用户空间。

【讨论】:

【参考方案4】:

我也面临同样的问题,我看了这个文档http://people.ee.ethz.ch/~arkeller/linux/multi/kernel_user_space_howto-6.html,所以打算使用信号。就我而言,没有机会丢失信号,因为 1. 系统是闭环的,信号执行后只有我会得到另一个信号。 2. 我使用的是 POSIX 实时信号。

【讨论】:

链接已损坏仅供参考

以上是关于从内核空间执行用户空间函数的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法从linux内核模块调用用户空间函数?

mmap() 在内核空间和用户空间中是不是相同?

从没有关联 memcpy 的套接字从内核空间读取到用户空间

6 io

Linux时间子系统之四:Timer在用户和内核空间流程

如何从内核向用户空间发送信号