Jump to content
em

Semnale in POSIX - Intro

Recommended Posts

Acest thread f?r? cap ?i coad? încearc? s? v? introduc? în lumea semnalelor în linux.

Poate unii din voi v-a?i gândit vreodat? cum s? face?i ca s? rula?i o dat? la X secunde o secven?? de cod în C.

Cea mai naiv? din solu?ii ar fi aceasta


#include <stdio.h>
void functie() {
printf("lel\n");
}
int main() {
int i = 0;
while(1) {
if(i++ == 100000000) {
functie();
i = 0;
}
}
return 0;
}

Dup? cum vede?i în comanda de mai sus se itereaz? prin i, ?i o dat? la 100mil se ruleaz? func?ia. Sun? bine, eh? Mhm, no. Pentru c? CPU-ul st? aproape mereu ocupat.

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND

4323 vilie 20 0 4200 628 548 R 99.4 0.3 0:08.94 b

O parte din voi poate c? a?i mai auzit de apelul sleep, un cod echivalent este cam a?a.


#include <stdio.h>
void functie() {
printf("lel\n");
}
int main() {
while(1) {
sleep(10); // hai s? dormim o dat? la 10 secunde ;-)
functie();
}
return 0;
}

Dac? sunte?i curio?i s? v? uita?i în top, observa?i c? CPU-ul nu mai este utilizat la 100%, ci procesul nu mai consum? nimic, de?i este într-un while(1). Aici intr? în joc semnalele. Semnalele sunt mesaje trimise de c?tre sistemul de operare c?tre procese pentru a semnala o situa?ie excep?ional? la care ele trebuie s? reac?ioneaze.

To?i am folosit semnale pân? acum. S? v? dau un exemplu.


vilie@em-vm:/tmp$ wget http://www.google.com/
--2015-02-19 01:41:42-- http://www.google.com/
Resolving www.google.com (www.google.com)^C
vilie@em-vm:/tmp$

În exemplul de mai sus am oprit procesul wget printr-un semnal generat de combina?ia de taste "CTRL+C" (SIGINT). Procesul a primit semnalul CTRL+C si a efectuat ac?iunea implicit?. (a murit)

În general procesele pot trata, bloca sau ignora semnalele primite. Ac?iunea implicit? la primirea unui semnal este omorârea procesului. În cazul în care procesul îl ignor?, sistemul de operare nu îi va mai trimite acel semnal. Hai s? observ?m câteva din semnale.


vilie@em-vm:/tmp$ kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX

În acest moment oamenii care d?deau f?r? mil? cu "kill -9" f?r? s? ?tie de ce, au aflat c? comanda este echivalent? cu kill -SIGKILL. SIGKILL este un semnal care nu poate fi blocat/mascat/ignorat de un proces -> procesul este omorât.

Hai s? vedem un exemplu mai interesant. Poate unii din voi ?tiu c? de obicei un proces care blocheaz? terminalul poate fi omorât cu CTRL+C sau CTRL+\. Mai jos e un exemplu de program care trateaz? acele semnale (?i nu moare).


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>

#include <signal.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>

#define MY_MAX 32
#define TIMEOUT 1

static void print_next(void)
{
static int n = 1;

printf("n = %d\n", n);

n = (n + 1) % MY_MAX;
}

/* signal handler */
static void ask_handler(int signo)
{
char buffer[128];

printf("Got %d - Opresc programul boss? [Y/n] ", signo);
fflush(stdout);
fgets(buffer, 128, stdin);
buffer[strlen(buffer)-1] = '\0';

if (buffer[0] == 'y' || buffer[0] == 'Y')
exit(EXIT_SUCCESS);
}

/* configure handlers */
static void set_signals(void)
{
struct sigaction sa;

memset(&sa, 0, sizeof(struct sigaction));
sa.sa_handler = ask_handler;

sigaction(SIGINT, &sa, NULL);


sigaction(SIGQUIT, &sa, NULL);;
}

int main(void)
{
set_signals();

while (1) {
print_next();
sleep(TIMEOUT);
}

return 0;
}

vilie@em-vm:/tmp$ gcc semn.c -o semn

vilie@em-vm:/tmp$ ./semn

n = 1

n = 2

^CGot 2 - Opresc programul boss? [Y/n] n

n = 3

n = 4

^\Got 3 - Opresc programul boss? [Y/n] n

Dup? cum vede?i programul ajunge în ask_handler dup? ce prime?te CTRL+C sau CTRL+\

Un ultim exemplu v? dau un cod care ruleaz? un handler o dat? la 2 secunde. Procesul seteaza un timer cu SIGALRM o dat? la 2 secunde ?i îl trateaz? în timer_handler. Adic? procesul î?i trimite sie?i semnale o dat? la dou? secunde, în rest se suspend? (sigsuspend).


#include <assert.h>
#include <time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


#include <signal.h>
#include <sys/time.h>


#define TIMEOUT 2 // Aici seta?i o dat? la câte secunde s? ruleze comanda


static void timer_handler(int signo)
{
time_t curr_time;

curr_time = time(NULL);

printf("time is: %s", ctime(&curr_time));
}

static void set_signals(void)
{
struct sigaction sa;

memset(&sa, 0, sizeof(sa));

sa.sa_handler = timer_handler;
sigaction(SIGALRM, &sa, NULL);
}

static void set_timer(void)
{
timer_t timerid;
struct sigevent sev;
struct itimerspec its;

sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIGALRM;
sev.sigev_value.sival_ptr = &timerid;
timer_create(CLOCK_REALTIME, &sev, &timerid);

/* Start the timer */
its.it_value.tv_sec = TIMEOUT;
its.it_value.tv_nsec = 0;
its.it_interval.tv_sec = its.it_value.tv_sec;
its.it_interval.tv_nsec = its.it_value.tv_nsec;

timer_settime(timerid, 0, &its, NULL);
}


static void wait_for_signal(void)
{
sigset_t old_mask;

sigprocmask(SIG_SETMASK, NULL, &old_mask);

sigsuspend(&old_mask);
}

int main(void)
{
set_signals();
set_timer();

while (1) {
wait_for_signal();
}

return 0;
}

vilie@em-vm:/tmp$ gcc a.c -lrt -o a

vilie@em-vm:/tmp$ ./a

time is: Thu Feb 19 01:21:49 2015

time is: Thu Feb 19 01:21:51 2015

time is: Thu Feb 19 01:21:53 2015

^C

# Ii pot trimite si eu SIGALRM manual, si va intra in timer_handler instant

kill -SIGALRM `pidof a`

vilie@em-vm:/tmp$ time is: Thu Feb 19 01:22:37 2015

kill -SIGALRM `pidof a`

vilie@em-vm:/tmp$ time is: Thu Feb 19 01:22:37 2015

kill -SIGALRM `pidof a`

vilie@em-vm:/tmp$ time is: Thu Feb 19 01:22:37 2015

time is: Thu Feb 19 01:22:38 2015

În continuare o s? postez un program care atunci când ap?sa?i CTRL+C v? d? impresia c? el a fost omorât ?i v? afiseaz? un prompt identic cu bashul vostru. ?i atunci cel care a f?cut programul r?u inten?ionat poate vedea/interpreta/trimite toate comenzile date de voi c?tre un ter?. Poate face vreunu din voi asta (pornind de la semn.c)

  • Upvote 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...