【发布时间】:2023-03-23 01:45:01
【问题描述】:
我目前正在处理一个项目,该项目在经过大量修改的 Linux 版本上运行,该版本已修补以能够访问 VMEbus。大部分总线处理已经完成,我有一个 VMEAccess 类,它使用 mmap 写入 /dev/mem 的特定地址,以便驱动程序可以提取该数据并将其推送到总线上。
当程序启动时,它不知道它要查找的从板在总线上的位置,因此它必须四处寻找它:它会尝试一个一个地读取每个地址,如果一个设备连接在那里read 方法返回一些数据,但如果没有任何连接,则会向程序发送 SIGBUS 信号。
我尝试了几种解决方案(主要使用信号处理),但一段时间后,我决定使用跳转。第一次 longjmp() 调用工作正常,但对 VMEAccess::readWord() 的第二次调用给了我一个总线错误,即使我的处理程序应该防止程序崩溃。
这是我的代码:
#include <iostream>
#include <string>
#include <sstream>
#include <csignal>
#include <cstdlib>
#include <csignal>
#include <csetjmp>
#include "types.h"
#include "VME_access.h"
VMEAccess *busVME;
int main(int argc, char const *argv[]);
void catch_sigbus (int sig);
void exit_function(int sig);
volatile BOOL bus_error;
volatile UDWORD offset;
jmp_buf env;
int main(int argc, char const *argv[])
{
sigemptyset(&sigBusHandler.sa_mask);
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = exit_function;
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGINT, &sigIntHandler, NULL);
/* */
struct sigaction sigBusHandler;
sigBusHandler.sa_handler = catch_sigbus;
sigemptyset(&sigBusHandler.sa_mask);
sigBusHandler.sa_flags = 0;
sigaction(SIGBUS, &sigBusHandler, NULL);
busVME = new VMEAccess(VME_SHORT);
offset = 0x01FE;
setjmp(env);
printf("%d\n", sigismember(&sigBusHandler.sa_mask, SIGBUS));
busVME->readWord(offset);
sleep(1);
printf("%#08x\n", offset+0xC1000000);
return 0;
}
void catch_sigbus (int sig)
{
offset++;
printf("%#08x\n", offset);
longjmp(env, 1);
}
void exit_function(int sig)
{
delete busVME;
exit(0);
}
【问题讨论】:
-
不幸的是我不能,SIGBUS 是这种情况下定义的行为,因为我试图从不存在的板上读取我收到此错误,无法避免,至少在没有为 FPGA 创建我自己的驱动程序/内核的情况下是这样
-
Don't
longjmpout of a signal handler。而是使用sigsetjmp和siglongjmp。请参阅the manual page 了解更多信息。 -
哇!谢谢它的工作!其实很容易解决,非常感谢,你能用实际的答案按钮让我标记它已解决吗?