PDA

Tam Sürümünü Görmek İçin : signal.h


quasimodo
30/03/2007, 15:31
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <time.h>

void signal_handler( int );

int main()
{
int i, x;

signal( SIGINT, signal_handler ); /* Bu satir */
srand( clock() );

for ( i = 1; i <= 100; i++ ) {
x = 1 + rand() % 50;

if ( x == 25 )
raise( SIGINT );

printf( "%4d", i );

if ( i % 10 == 0 )
printf( "\n" );
}

return 0;
}

void signal_handler( int signalValue )
{
int response;

printf( "%s%d%s\n%s",
"\nInterrupt signal ( ", signalValue, " ) received.",
"Do you wish to continue ( 1 = yes or 2 = no )? " );

scanf( "%d", &response );

while ( response != 1 && response != 2 ) {
printf( "( 1 = yes or 2 = no )? " );
scanf( "%d", &response );
}

if ( response == 1 )
signal( SIGINT, signal_handler );
else
exit( EXIT_SUCCESS );
}


Buradaki signal() ve raise() fonksiyonlarinin gorevi ney?

Program calismaya basladiktan sonra bu satira geldiginde
ne yapiyor.


acehreli
04/04/2007, 21:41
Programlar birbirleriyle isletim sisteminin sagladigi isaretlerle (signal) anlasabilirler. Bir program bir isaret aldiginda, o anda yapmakta oldugu is durdurulur ve program o isaret geldiginde hangi ozel seyi yapmak istiyorsa o yapilir.

En cok kullanilan isaret herhalde SIGINT'tir. Biz disaridan Ctrl-C'ye bastigimizda programlara SIGINT isareti gonderilir.

signal: Bir programin "ben bu isaret geldiginde su islevin cagrilmasini istiyroum" demesidir.

raise: Bir programin "ben kendi kendime su isareti gonderiyorum" demesidir.

Senin ornegindeki

signal(SIGINT, signal_handler);

cagrisi, SIGINT isareti geldiginde (ornegin Ctrl-C'ye basildiginda) signal_handler adli islevin cagrilmasini saglar.

raise(SIGINT);

ise sanki disaridan birisi programi sonlandirmak istemis gibi, ama kendi kendisine, SIGINT isaretini gonderir.

Isaretlerle ilgili cok onemli ama fazla da bilinmeyen bir ayrinti var: Isaret geldiginde calistirilan o ozel islevin calismasi sirasinda yine bir isaret gelirse ne olur?

Cok kotu seyler olabilir. Ornegin o islevin icinden bazi kutuphane islevlerini cagiramayiz. Onun icin, isaretle ilgili olan o ozel islevde, guvenli olarak yapilabilecek tek sey, o isaretin alinmis oldugunu bir kenara not etmektir. Ondan sonra, programin ana dOngUsu sirasinda boyle bir isaret alinip alinmadigina bakilir ve asil is o ana dOngU sirasinda yapilir.

Ornegin printf'in o ozel islevden cagrilmasi yanlistir. Onun icin senin ornegin aslinda hatali. (Bir "signal handler" icerisinden hangi islevlerin cagrilabildiklerini gosteren sayfalar gormustum ama simdi bulamiyorum. :( )

Bu isin guzel yollarindan birisi sigset_t tUrUnu kullanan sigaddset ve arkadaslarini kullanmaktir. Onlar da sonucta su yonteme benzer sekilde calisirlar:


int g_SIGINT_alindi = 0;


int main()
{
// Islevi belirliyoruz
signal(SIGINT, ozel_islev);

/* ... */

// Programin ana dOngUsU
while(/* ... */)
{
if (g_SIGINT_alindi)
{
// Ctrl-C'ye basilmis; temizlik yapip cikalim...

// Gerekirse printf burada yapilabilir
}

/* ... */
}

/* ... */
}

void ozel_islev(int isaret_degeri)
{
// Burada hic kutuphane islevi cagirmiyoruz;
// yalnizca bu isareti aldigimizi not ediyoruz.
if (isaret_degeri == SIGINT)
{
g_SIGINT_alindi = 1;
}

/* ... */
}


Ali

quasimodo
05/04/2007, 21:34
if ( response == 1 )
signal( SIGINT, signal_handler );
else
exit( EXIT_SUCCESS );

o ozel islevin icinde yazilmis bu kodda eger yanit 1 olursa ne oluyor.
yani ozel islevin icinden tekrar cagirilan
signal(SIGINT, signal_hangdel)
islevinin gorevi nedir...?

acehreli
05/04/2007, 22:08
Bir yerde gozume carptigina gore, bazi isletim sistemlerinde o isleve bir kere girmek, o islevle SIGINT'in iliskisini unutturuyormus. Onun icin her giriste tekrar signal'i cagirmak gerekiyormus. Bazi ortamlarda oyleymis; tasinabilir olmak icin gerekliymis...

Ben daha karsilasmamistim, senin sorunu yanitlarken ogrendim.

Ali

quasimodo
05/04/2007, 22:17
iliskilendirip, yonetimi tekrar main() e mi veriyor ...

isleve girdikten sonra
yanit 1 dersek cikti

60
61 62 63 64 65 ......69
71 72 ... 79

diye devam ediyor...?

acehreli
05/04/2007, 23:24
Evet, isaret islevinden cikilinca isaretin geldigi andaki yere donuluyor. Ornegin hangi noktada Ctrl-C'ye basilmissa, program o noktadan devam ediyor.

Ali