В настоящее время я работаю над проектом, работающим на сильно модифицированной версии Linux, исправленной для доступа к VMEbus. Большая часть обработки шины выполнена, у меня есть класс VMEAccess, который использует mmap для записи по определенному адресу /dev/mem, чтобы драйвер мог получить эти данные и передать их на шину.
Когда программа запускается, она понятия не имеет, где находится искомая ведомая плата на шине, поэтому она должна найти ее, ковыряясь: она пытается прочитать каждый адрес один за другим, если там подключено устройство, метод чтения возвращает некоторые данные, но если ничего не подключено, в программу будет отправлен сигнал 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);
}
longjmp
из обработчика сигнала. Вместо этого используйтеsigsetjmp
иsiglongjmp
. См. страницу руководства для получения дополнительной информации. - person Some programmer dude   schedule 18.12.2017