SIGILL sinyallerini işleyen bir kitaplık geliştirdim. Ben libc bağımlılığını önlemek ve Linux syscalls doğrudan kullanmak istediğim için. Kütüphanemin bazı Linux sistemlerinde asılı olduğunu fark, ve hata ayıklama bir sürü sonra yerine sigaction
ait rt_sigaction
syscall kullanarak sorunu çözer bulundu. Ancak, iki syscalls arasındaki farkın bir açıklamasını bulamadım. SO'daki herkes temel bilgileri biliyor mu?Linux'ta sinyal ve rt_signal syscalls arasındaki fark nedir?
Güncelleme: Bazı ARM talimat uzantıları, örneğin CPU desteği algılamak için sinyal işleyici kullanın XScale talimatı MIATT
. Ben 4 bayt (bu talimat boyutu) tarafından PC
kayıt ilerlemek ve SIGILL işleyicisi çağrıldı belirtmek için kayıtlarından birini değiştirmek SIGILL işleyicisi
static uint32_t probe_xscale() {
register uint32_t retValue asm("r0") = 0;
asm volatile (
// Equivalent of the following code:
// ".arch xscale\n"
// "MIATT acc0, r0, r0;"
// If the next line raises SIGILL, the signal handle will change r0 to 1 and skip the instruction (4 bytes)
"MCR P0, 0x1, r0, c15, c0, 0;"
: "+r" (retValue)
:
:
);
return retValue;
}
: Burada talimat sondalama fonksiyonudur. İşte sinyal işleyici kodu. İşte
static void probe_signal_handler(int, siginfo_t *, void* ptr) {
ucontext_t* ctx = (ucontext_t*)ptr;
ctx->uc_mcontext.arm_pc += 4;
ctx->uc_mcontext.arm_r0 = 1;
}
(sigaction syscall başarısız olursa SIGILL işleyicisi çağrıldı eğer talimat SIGILL, 1 neden olmadı IF_FUNCTION 0 döner ve 2) sondalama yaparız: Burada
static uint32_t probeInstruction(uint32_t (*ProbeFunction)()) {
struct sigaction oldSigillAction;
struct sigaction probeSigillAction;
memset(&probeSigillAction, 0, sizeof(probeSigillAction));
probeSigillAction.sa_sigaction = &probe_signal_handler;
// Needs Linux >= 2.2
probeSigillAction.sa_flags = SA_ONSTACK | SA_RESTART | SA_SIGINFO;
int sigactionResult = _syscall_sigaction(SIGILL, &probeSigillAction, &oldSigillAction);
if (sigactionResult == 0) {
const uint32_t probeResult = ProbeFunction();
_syscall_sigaction(SIGILL, &oldSigillAction, NULL);
return probeResult;
} else {
return 2;
}
}
static int _syscall_sigaction(int signum, const struct sigaction *new_action, struct sigaction *old_action) __attribute__((noinline));
static int _syscall_sigaction(int signalNumberParameter, const struct sigaction *newActionParameter, struct sigaction *oldActionParameter) {
register int result asm ("r0");
register int signalNumber asm ("r0") = signalNumberParameter;
register const struct sigaction *newAction asm ("r1") = newActionParameter;
register struct sigaction *oldAction asm ("r2") = oldActionParameter;
register int syscallNumber asm ("r7") = __NR_rt_sigaction;
asm volatile (
"swi $0;"
: "=r" (result)
: "r" (signalNumber), "r" (newAction), "r" (oldAction), "r" (syscallNumber)
:
);
return result;
}
Ben Android SDK (qemu) den emülatörü Bu kodu test ve Pandaboard Ubuntu çalıştıran: sigaction syscall saplama fonksiyonunun benim uygulamasıdır. emülatörü olarak kod iyi çalışır (hem ARM9 ve Cortex-A8 işlemciler taklit edilirken), ama __NR_sigaction kullanırsanız Pandaboard üzerinde o MIATT talimatı üzerine asılı: sinyal işleyici sonra kod 4 bayt atlamak etmediğini görünüyor ama çalışır aynı talimat.
ben 'rt_sigaction' versiyonu "gerçek zamanlı" sürüm olduğunu tahmin ediyorum. Belirgin arama süresine sahip olması için tasarlandığı anlamına gelir. –
Bunlar hemen hemen aynı kodlardır, her ikisi de çekirdeğindeki do_sigaction() öğesinde. Eğer sorun yaşıyorsanız, muhtemelen onları detaylandırmaya yardımcı olur. –
Daha fazla ayrıntı ve kodumun ilgili bölümüne soruyu ekledim. –