我正在编写一个简单的 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
从用户空间函数传入数据,但我不确定如何处理函数调用处于循环中并且在下一次调用calculate_output
发生之前执行更多代码的事实。
我设想这项工作的方式是:
- 主用户空间程序将启动内核空间代码(可能通过
ioctl
) - 用户空间程序阻塞并等待内核空间代码
- 内核空间程序向用户空间程序询问输出数据,并阻塞等待
- 用户空间程序解除阻塞、计算和发送数据(
ioctl
?),然后再次阻塞 - 内核空间程序解除阻塞并继续
- 内核空间程序完成并通知用户空间
- 用户空间解除阻塞并继续下一个任务
那么我如何在内核空间和用户空间之间进行通信,并且还具有阻塞,以便我没有用户空间不断轮询设备文件以查看它是否需要发送数据?
一个警告:虽然定点算术在我的示例代码中可以很好地工作,但在实际代码中它不是一个选项;我需要浮点提供的大范围,而且——即使没有——我担心重写代码以使用定点算术会混淆未来维护者的算法。