signal kezelés

 ( zamek | 2011. november 16., szerda - 16:21 )

Hello,

Linux alatt C-ben és nem C++-ban kell megoldanom a következőt:

Legyen egy aszinkron io esemény kezelő modul, ami tetszőleges számú pl. soros portról érkező aszinkron karaktereket queue-ba gyűjtöget, amelyeket később processzek lekérhetnek.

A szokásos signalkezeléssel fordítási időben megy a dolog, de hogy tudok futásidőben az egyes signalokhoz különböző handler függvényeket "gyártani".

Vagyis egy process futásidőben bejelenti, hogy x portra szeretné a gyűjtögetést elindítani. Megnyitom a portot, majd be kell regisztrálnom a portra egy aszinkron signalkezelőt, amely kér egy signalhandler függvény címet. Na ezt hogy tudom C-ben futásidőben létrehozni?

Ha ez nem megy -gyanítom, hogy nem fog-, akkor hogy tudnám megoldani, hogy egy signalhandlert hív minden esemény, de valahogy szét tudnám választani, hogy melyik port váltotta ki? A signalhandler létrehozáskor nincs egy user_defined érték, amit feltöltve a meghívott signalhandler-ben visszakapnám és tudnék ez alapján választani?

Nézegettem a dokumentációt, de nem találtam olyant, amiből kiderülne ez.

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

Rövid és tömör válaszom van a felvetésedre: ha nem akarsz szopni, akkor NE akarjál aszinkron signalokkal i/o-t kezelni.

Vannak más, teljesen atombiztosan működő, és semmivel nem bonyolultabb technológiák a feladatra (alapvetően a non-blocking i/o, select, poll kulcsszavakat javaslom a figyelmedbe), amik hatalmas előnye ráadásul, hogy sokkal jobban szabványosítottak.

A signal kezelés tele van versenyhelyzetekkel (aknákkal), amiket sok esetben nagyon nehéz eliminálni, és biztos, hogy robbanni fog az egyik alattad. Ha nem most, akkor majd később, amikor egy gyorsabb gépre rakod.

+sok a select(), poll() es hasonlokra,
-sok a signal()-ra (bar persze vannak olyan helyzetek - child processz leallasa, interaktiv vezerles: ctrl+c lekezelese - ahol nem kerulhetjuk ezeket meg, de itt nem errol van szo').

ok, koszonon a linkeket, megprobalom a select-et.

Illetve van me'g egy 3ik iranyvonal amit hasznalhatsz: a nonblock-u"zemmod (lasd peldaul: google://O_NONBLOCK). Az open()-nel illetve az fcntl()-lel is beallithatod. Ez is inkabb a "nem javasolt" kategoria (pl konnyen vezethet "busy wait" jellegu ciklusokhoz, 100% prociterheltseg mellett) -- de erdemes megnezni az elonyeit is, hogy hatha az esetedben jo szolgalatot tehet.

Ezeken felul, ha soros portos dolgokkal bibelo"dsz, akkor nezz korul a tcdrain() ill tcflush() fuggvenyek kornyeken is. Noha kozvetlenul nem kapcsolodik az "olvassunk egyszerre tobb portrol" temahoz, de ha nagyon precizen kell hardver-kozeli protokollokkal jatszani, ezek is hasznosak lehetnek neha.

> egy signalhandlert hív minden esemény, de valahogy szét tudnám választani, hogy melyik port váltotta ki?

http://linux.die.net/man/2/sigaction (sa_flags, SA_SIGINFO, si_fd)

http://www.faqs.org/docs/Linux-HOWTO/Serial-Programming-HOWTO.html#AEN144

Ha jól értem, az a gond, hogy csak egy signal-kezelő lehet, de több handle-t kell kezelni... egyszer én is gányoltam valami ilyesmit, ez a programocska fakadt belőle:
sigiohnd.h
sigiohnd.c