从Linux内核模块中调用用户空间函数

我正在编写一个简单的Linux字符设备驱动程序,通过I / O端口将数据输出到一个硬件.我有一个函数执行浮点运算来计算硬件的正确输出;不幸的是,这意味着我需要在用户空间中保留此功能,因为Linux内核不能很好地处理浮点运算.

这是设置的伪表示(请注意,此代码不执行任何特定操作,它只显示我的代码的相对布局):

用户空间功能:

char calculate_output(char x){
    double y = 2.5*x;
    double z = sqrt(y);

    char output = 0xA3;

    if(z > 35.67){
        output = 0xC0;
    }

    return output;
}

内核空间代码:

unsigned i;
for(i = 0; i < 300; i++){
    if(inb(INPUT_PORT) & NEED_DATA){
        char seed = inb(SEED_PORT);
        char output = calculate_output(seed);
        outb(output,OUTPUT_PORT);
    }

    /* do some random stuff here */
}

我想过使用ioctl传递来自userspace函数的数据,但是我不知道如何处理函数调用处于循环中并且在下一次调用calculate_output之前执行更多代码的事实.

我设想这个工作的方式是:

>主用户空间程序将启动内核空间代码(可能通过ioctl)
> userspace程序块并等待内核空间代码

> kernelspace程序向用户空间程序询问输出数据,并阻塞等待
> userspace program解锁,计算和发送数据(ioctl?),然后再次阻塞
> kernelspace程序解除阻塞并继续

> kernelspace程序完成并通知用户空间
> userspace解除阻止并继续执行下一个任务

那么我如何在内核空间和用户空间之间进行通信,并且还具有阻塞功能,以便我不会让用户空间不断轮询设备文件以查看是否需要发送数据?

需要注意的是:虽然定点算法在我的示例代码中可以很好地工作,但它不是实际代码中的一个选项;我需要浮点提供的大范围 – 即使不是 – 我害怕重写代码以使用定点算法会混淆未来维护者的算法.

最佳答案
我认为最简单的解决方案是在内核驱动程序中创建一个字符设备,使用您自己的虚拟文件文件操作.然后用户空间可以打开此设备O_RDWR.您必须实现两个主要文件操作:

> read – 这是内核将数据传递回用户空间的方式.此函数在调用read()系统调用的用户空间线程的上下文中运行,在您的情况下,它应该阻塞,直到内核具有需要知道输出的另一个种子值.
> write–这是用户空间将数据传递到内核的方式.在您的情况下,内核只会对先前的读取进行响应并将其传递给硬件.

然后你最终在用户空间中使用一个简单的循环:

while (1) {
    read(fd,buf,sizeof buf);
    calculate_output(buf,output);
    write(fd,output,sizeof output);
}

内核中根本没有循环 – 一切都在驱动事物的用户空间进程的上下文中运行,而内核驱动程序只负责将数据移入/移出硬件.

根据你在内核方面的“做一些随机的东西”,你可能不可能这么简单.如果你真的需要内核循环,那么你需要创建一个内核线程来运行该循环,然后在input_data,input_ready,output_data和output_ready的行中包含一些变量,以及一些等待和你需要的任何锁定.

当内核线程读取数据时,将数据放入input_ready并设置input_ready标志并发出输入waitqueue信号,然后执行wait_event(< output_ready设置>).读取文件操作将执行wait_event(< input_ready已设置>)并在数据准备就绪时将数据返回给用户空间.类似地,写文件操作会将从用户空间获取的数据放入output_data并设置output_ready并向输出waitqueue发出信号.

另一种(更丑陋,更不便携)的方法是使用像ioperm,iopl或/ dev / port这样的东西来完成用户空间中的所有操作,包括低级硬件访问.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


查找全部容器的日志文件 $ sudo find /var/lib/docker/containers -name *.log 查看日志位置 $ docker inspect --format=&#39;{{.LogPath}}&#39; &lt;container_name&gt; 实时查询内容 $
Linux日志文件中列属性的详细解析
在Linux系统中没有duf命令,如何有效地管理磁盘空间?
深入探讨EncryptPad在Linux操作系统中的功能和优势
原理和应用场景:Linux中ttyload工具的工作原理和实际用途
深度解析SELinux的三种策略类型
评估Linux系统性能的ttyload工具使用效果
分享在Linux系统中检测SSH版本的方法
介绍Linux平台上的数据加密工具EncryptPad
在Linux系统中,如何查看和诊断块设备信息?
在Linux环境下如何查看块设备信息?
探索Linux操作系统下的数据加密工具EncryptPad
学会在Linux系统中查看硬盘信息
分析SELinux:原理与实践
掌握SELinux策略类别
技巧:有效解读和管理Linux日志文件
查看Linux系统中的所有用户
了解Linux系统中各种不同类型的日志文件
深入理解Linux PS命令
方法:在Linux操作系统中查看用户