मैंने एक पुस्तकालय विकसित किया जो सिगिल सिग्नल को संभालता है। चूंकि मैं libc निर्भरता से बचना चाहता हूं, और सीधे लिनक्स सिस्कोल का उपयोग करना चाहता हूं। मैंने देखा कि मेरी लाइब्रेरी कुछ लिनक्स सिस्टम पर लटकती है, और बहुत सारे डिबगिंग के बाद मैंने पाया कि सिस्कोल sigaction
की बजाय समस्या हल करती है। हालांकि, मुझे दो सिस्को के बीच अंतर का विवरण नहीं मिला। क्या किसी को भी अंतर्निहित विवरण पता है?लिनक्स में सिग्नल और rt_signal syscalls के बीच क्या अंतर है?
अद्यतन: मैं कुछ एआरएम निर्देश एक्सटेंशन के लिए सीपीयू समर्थन का पता लगाने के लिए सिग्नल हैंडलर का उपयोग करता हूं, उदा। एक्सएसकेले निर्देश MIATT
।
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;
}
SIGILL हैंडलर में मैं 4 बाइट (इस शिक्षा का आकार) द्वारा PC
रजिस्टर अग्रिम, और रजिस्टरों में से एक को बदलने के संकेत मिलता है कि SIGILL हैंडलर बुलाया गया था: यहाँ अनुदेश जांच कार्य है। सिग्नल हैंडलर कोड यहां है।
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;
}
यहाँ कैसे मैं जांच (फ़ंक्शन 0 अगर अनुदेश SIGILL, 1 का कारण नहीं करता है, तो SIGILL हैंडलर बुलाया गया था, और 2 यदि sigaction syscall विफल) करना है:
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;
}
मैं एंड्रॉयड एसडीके (qemu) से एमुलेटर में इस कोड का परीक्षण किया है, और Pandaboard चल Ubuntu पर: sigaction syscall ठूंठ समारोह के अपने कार्यान्वयन है। एम्यूलेटर में कोड अच्छी तरह से चलता है (एआरएम 9 और कॉर्टेक्स-ए 8 सीपीयू को अनुकरण करते समय), लेकिन पांडबार्ड पर यह एमआईएटीटी निर्देश पर लटकता है अगर मैं __NR_sigaction का उपयोग करता हूं: ऐसा लगता है कि सिग्नल हैंडलर के बाद कोड 4 बाइट्स को नहीं छोड़ता है, लेकिन रन एक ही निर्देश।
मुझे लगता है कि 'rt_sigaction' संस्करण एक "वास्तविक समय" संस्करण है। मतलब यह है कि यह निर्धारित समय कॉल करने के लिए डिज़ाइन किया गया है। –
ये लगभग उसी कोड हैं, दोनों कर्नेल में do_sigaction() पर जमीन। यदि आपको समस्याएं आ रही हैं, तो शायद यह उन्हें विस्तारित करने में मदद करेगी। –
मैंने प्रश्न में मेरे कोड का अधिक विवरण और प्रासंगिक हिस्सा जोड़ा। –