अपने खुद के async-signal-safe snprintf("%d
और उपयोग को लागू करेंwrite
यह उतना बुरा नहीं है जितना मैंने सोचा था, सी में एक इंट को स्ट्रिंग में कैसे परिवर्तित किया जाए? कई कार्यान्वयन हैं।
चूंकि केवल दो दिलचस्प प्रकार के डेटा हैं जो सिग्नल हैंडलर एक्सेस कर सकते हैं:
sig_atomic_t
वैश्विक
int
संकेत तर्क
यह मूल रूप से सभी दिलचस्प उपयोग मामलों को कवर करता है।
तथ्य यह strcpy
है कि सिग्नल सुरक्षित भी चीजों को और बेहतर बनाता है।
अब तक जितनी बार SIGINT मिली Ctrl + C
, उसे और सिग्नल आईडी को ट्रिगर करने के लिए प्रिंट के नीचे POSIX प्रोग्राम ।
आप Ctrl + \
(SIGQUIT) के साथ कार्यक्रम से बाहर निकल सकते हैं ।
main.c:
#define _XOPEN_SOURCE 700
#include <assert.h>
#include <limits.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#define ITOA_SAFE_STRLEN(type) sizeof(type) * CHAR_BIT + 2
char *itoa_safe(intmax_t value, char *result, int base) {
intmax_t tmp_value;
char *ptr, *ptr2, tmp_char;
if (base < 2 || base > 36) {
return NULL;
}
ptr = result;
do {
tmp_value = value;
value /= base;
*ptr++ = "ZYXWVUTSRQPONMLKJIHGFEDCBA9876543210123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[35 + (tmp_value - value * base)];
} while (value);
if (tmp_value < 0)
*ptr++ = '-';
ptr2 = result;
result = ptr;
*ptr-- = '\0';
while (ptr2 < ptr) {
tmp_char = *ptr;
*ptr--= *ptr2;
*ptr2++ = tmp_char;
}
return result;
}
volatile sig_atomic_t global = 0;
void signal_handler(int sig) {
char key_str[] = "count, sigid: ";
char buf[2 * ITOA_SAFE_STRLEN(sig_atomic_t) + sizeof(key_str)];
enum { base = 10 };
char *end;
end = buf;
strcpy(end, key_str);
end += sizeof(key_str);
end = itoa_safe(global, end, base);
*end++ = ' ';
end = itoa_safe(sig, end, base);
*end++ = '\n';
write(STDOUT_FILENO, buf, end - buf);
global += 1;
signal(sig, signal_handler);
}
int main(int argc, char **argv) {
{
typedef struct {
intmax_t n;
int base;
char out[1024];
} InOut;
char result[1024];
size_t i;
InOut io;
InOut ios[] = {
{0, 10, "0"},
{1, 10, "1"},
{9, 10, "9"},
{10, 10, "10"},
{100, 10, "100"},
{-1, 10, "-1"},
{-9, 10, "-9"},
{-10, 10, "-10"},
{-100, 10, "-100"},
{0, 2, "0"},
{1, 2, "1"},
{10, 2, "1010"},
{100, 2, "1100100"},
{-1, 2, "-1"},
{-100, 2, "-1100100"},
{0, 35, "0"},
{1, 35, "1"},
{34, 35, "Y"},
{35, 35, "10"},
{100, 35, "2U"},
{-1, 35, "-1"},
{-34, 35, "-Y"},
{-35, 35, "-10"},
{-100, 35, "-2U"},
};
for (i = 0; i < sizeof(ios)/sizeof(ios[0]); ++i) {
io = ios[i];
itoa_safe(io.n, result, io.base);
if (strcmp(result, io.out)) {
printf("%ju %d %s\n", io.n, io.base, io.out);
assert(0);
}
}
}
if (argc > 1 && !strcmp(argv[1], "1")) {
signal(SIGINT, signal_handler);
while(1);
}
return EXIT_SUCCESS;
}
संकलित करें और चलाएं:
gcc -std=c99 -Wall -Wextra -o main main.c
./main 1
Ctrl + C पंद्रह बार दबाने के बाद, टर्मिनल दिखाता है:
^Ccount, sigid: 0 2
^Ccount, sigid: 1 2
^Ccount, sigid: 2 2
^Ccount, sigid: 3 2
^Ccount, sigid: 4 2
^Ccount, sigid: 5 2
^Ccount, sigid: 6 2
^Ccount, sigid: 7 2
^Ccount, sigid: 8 2
^Ccount, sigid: 9 2
^Ccount, sigid: 10 2
^Ccount, sigid: 11 2
^Ccount, sigid: 12 2
^Ccount, sigid: 13 2
^Ccount, sigid: 14 2
के 2
लिए सिग्नल नंबर कहां है SIGINT
।
उबुन्टु 18.04 पर परीक्षण किया गया। गिटहब ऊपर ।
printf
उस सिग्नल हैंडर में उस कॉल को देखें ? इसे मिटाओ।