Update: http://hup.hu/node/106017#comment-1338790
Kedves Fórumtársak!
Egy programot igyekszem írni, aminek lényege az, hogy egy adott kernelben lakó driverhez (ez a rész adott/gyártói hákmány) beregisztrálja (elküldi a folyamat PID-jét és egy timeout értéket) magát (ioctl/karakteres eszközfájl segítségével).
A kernel driver pedig egy-egy szignált (SIGUSR1/SIGUSR2) küld a korábban regiszrált PID-re, ha az adott hardvereszközök inaktivitása túllépi a korábban beállított timeout-ot.
Ekkor a programom lehetőséget ad egy előre beállított program futtatására (nem muszáj használni, de lehetőséget nyújt rá.)
A programom először forkol, majd démonként fut tovább, és a démon jelentkezik be a szignálok kezelésére.
Ezt a lépést a sigwait függvény segítségével próbáltam megoldani, de eddig úgy tűnik, hogy nem működik. A sigwait()-es ciklusig eljut a program, ellenben ha SIGUSR1/SIGUSR2-t küldök neki, akkor rögtön meghal a démon, a szignálkezelő nem fut le, annal ellenére, hogy a példáknak megfelelően írtam meg a kódot:
...
//register listeners for signals from the kernel
sigemptyset(&listen_set);
sigaddset(&listen_set, SIGUSR1);
sigaddset(&listen_set, SIGUSR2);
sigaddset(&listen_set, SIGTERM);
sigaddset(&listen_set, SIGQUIT);
if (sigprocmask(SIG_UNBLOCK, &listen_set, NULL) != 0) {
syslog(LOG_ERR, "sigwait() failed: %s\n", strerror(errno));
cleanup_daemon();
exit(ERR_SIGPROCMASK_FAIL);
}
/*
The SIGUSR1 and SIGUSR2 signals are set aside for you to use any way you want.
They're useful for interprocess communication. Since these signals are normally fatal,
you should write a signal handler for them in the program that receives he signal.
*/
if (pm0_conf.m_verbose == true) {
syslog(LOG_INFO, "Starting signal processing loop.\n");
}
while (true) {
if (sigwait(&listen_set, &sig) == 0) {
if (pm0_conf.m_verbose == true) {
syslog(LOG_INFO, "Got a signal: %d.\n", sig);
}
switch (sig) {
case SIGUSR1:
syslog(LOG_NOTICE, "SATA HDD-1 standby initiated...\n");
if (pm0_conf.m_suspend_exec != NULL) exec_suspend(1);
break;
case SIGUSR2:
syslog(LOG_NOTICE, "SATA HDD-0 standby initiated...\n");
if (pm0_conf.m_suspend_exec != NULL) exec_suspend(0);
break;
case SIGQUIT:
case SIGKILL:
case SIGTERM:
if (pm0_conf.m_verbose == true) {
syslog(LOG_INFO, "Caught SIGKILL/SIGTERM/SIGQUIT, now exiting...\n");
}
cleanup_daemon();
exit(ALL_OK);
break;
default:
break;
}
}
else {
syslog(LOG_ERR, "sigwait() failed: %s\n", strerror(errno));
cleanup_daemon();
exit(ERR_SIGWAIT_FAIL);
}
}
...
UI: Igen, tudom, hülyeség diszkek elalvásakor programot futtatni, mert akkor a diszk felébred, de ettől függetlenül a programban biztosítani akarom a lehetőséget erre.
Hozzászólások
tipp: SIG_UNBLOCK -> SIG_SETMASK.
+1, mert ezeket blokkolni kell!
Igen, rendben. Blokkolni kellene, de már csak a sigwait hívás után. (Azért, hogy a jelzést kezelő kódrészt egy újabb jelzés ne szakíthassa meg. (Ha minden igaz.))
Ettől függetlenül a sigwait() hívás utáni kód a tapasztalataim szerint már nem is kerül végrehajtásra, tehát nem ez a fő probléma itt.
Ettől függetlenül köszönöm az észrevételt. Jogos.
-------------------------------------------------------------------------------
Az életben csak egy dolog a szép, de az épp nem jut eszembe.
Slackware Linux 13.37 | 2.6.39.3-janos
Lásd itt: http://szabilinux.hu/nyilt_rendszerek/node43.html
Blokkolni kell, még sigwait előtt! Ne félj a megszakítástól, ez nem interrupt.. Szépen pendingel míg nem kéred le.
Ok, a blokkolás lényege most már világos. Köszi, sokat segített.
-------------------------------------------------------------------------------
Az életben csak egy dolog a szép, de az épp nem jut eszembe.
Slackware Linux 13.37 | 2.6.39.3-janos
nade hol mondod meg, hogy melyik signalra milyen függvényt hajtson végre?
man sigaction
int sigwait(const sigset_t *set, int *sig);
The sigwait() function suspends execution of the calling thread until the delivery of one of the signals specified in the signal set set. The function accepts the signal (removes it from the pending list of signals), and returns the signal number in sig.
--
Amennyire én értem, ilyenkor nem kell sigaction-nal regisztrálni a jelzést kezelő függvényt, mert a sigwait feleslegessé teszi. Addig blokkolja a hívó folyamatot, amíg nem érkezik egy - a paraméterben átadott jelzéscsoportba tartozó - jelzés.
-------------------------------------------------------------------------------
Az életben csak egy dolog a szép, de az épp nem jut eszembe.
Slackware Linux 13.37 | 2.6.39.3-janos
Valahogy így:
Köszi! Most már megy a jelzéskezelés!
-------------------------------------------------------------------------------
Az életben csak egy dolog a szép, de az épp nem jut eszembe.
Slackware Linux 13.37 | 2.6.39.3-janos
Egy érdekességre lettem figyelmes a programomban.
Konkrétan arról van szó, hogy van egy függvény ami meghív egy előre beállított programot (exec_suspend), a megadott paraméterekkel.
Mielőtt azonban ész nélkül nekiesne, megnézi, hogy végrehajtható-e az adott parancs (check_exec), a programot futtató felhasználó számára.
A probléma abban áll, hogy a check_exec függvénynek egy stat struktúrára mutató pointert adok át, amit az exec_suspend függvényben töltök fel, és a stack-en kap helyet (nem dinamikusan foglalt memóriában.) A stat struktúrából akarom kiolvasni, hogy a programot futtató felhasználónak van-e futtatási joga.
A check_exec függvényen belül viszont már valamiért "elromlik" a stat strukturában tárolt információ.
A program kimenetén ez látszik:
Nem tudom mi lehet a gond...
Lehet, hogy a függvényhívás során felülíródik a stack-en tárolt struktúra?
Másra nem tudok gondolni, mert a struktúrát nem módosítom.
Itt a releváns kódrészlet:
-------------------------------------------------------------------------------
Az életben csak egy dolog a szép, de az épp nem jut eszembe.
Slackware Linux 13.37 | 2.6.39.3-janos
Böki a szemem:
syslog(LOG_INFO, " %d (%s) %d (%s).\n", EXEC_NAME, filestat->st_uid, usr_str, filestat->st_gid, grp_str);
Jaj, köszi!
Több szem többet lát. :)
Nem is gondoltam, hogy minden OK, csak eggyel több paramétert kap a kiíratás, és ezért borul látszólag minden.
A copy-paste átka...
-------------------------------------------------------------------------------
Az életben csak egy dolog a szép, de az épp nem jut eszembe.
Slackware Linux 13.37 | 2.6.39.3-janos