abclinuxu.cz AbcLinuxu.cz itbiz.cz ITBiz.cz HDmag.cz HDmag.cz abcprace.cz AbcPráce.cz
Inzerujte na AbcPráce.cz od 950 Kč
Rozšířené hledání
×
    dnes 04:00 | Nová verze

    Byla vydána (Mastodon, 𝕏) nová stabilní verze 2.10.38 svobodné aplikace pro úpravu a vytváření rastrové grafiky GIMP (GNU Image Manipulation Program). Přehled novinek v oznámení o vydání a v souboru NEWS na GitLabu. Nový GIMP je již k dispozici také na Flathubu.

    Ladislav Hagara | Komentářů: 0
    dnes 00:22 | Komunita

    Google zveřejnil seznam 1220 projektů od 195 organizací (Debian, GNU, openSUSE, Linux Foundation, Haiku, Python, …) přijatých do letošního, již dvacátého, Google Summer of Code.

    Ladislav Hagara | Komentářů: 1
    včera 22:22 | IT novinky

    Na základě DMCA požadavku bylo na konci dubna z GitHubu odstraněno 8535 repozitářů se zdrojovými kódy open source emulátoru přenosné herní konzole Nintendo Switch yuzu.

    Ladislav Hagara | Komentářů: 8
    včera 00:33 | Nová verze

    Webový prohlížeč Dillo (Wikipedie) byl vydán ve verzi 3.1.0. Po devíti letech od vydání předchozí verze 3.0.5. Doména dillo.org již nepatří vývojářům Dilla.

    Ladislav Hagara | Komentářů: 0
    4.5. 15:00 | Komunita

    O víkendu probíhá v Bostonu, a také virtuálně, konference LibrePlanet 2024 organizovaná nadací Free Software Foundation (FSF).

    Ladislav Hagara | Komentářů: 0
    4.5. 13:22 | Nová verze

    Nová vývojová verze Wine 9.8 řeší mimo jiné chybu #3689 při instalaci Microsoft Office 97 nahlášenou v roce 2005.

    Ladislav Hagara | Komentářů: 0
    3.5. 13:11 | Nová verze

    Coppwr, tj. GUI nástroj pro nízkoúrovňové ovládání PipeWire, byl vydán v nové verzi 1.6.0. Zdrojové kódy jsou k dispozici na GitHubu. Instalovat lze také z Flathubu.

    Ladislav Hagara | Komentářů: 0
    2.5. 22:33 | Nová verze

    Byla vydána dubnová aktualizace aneb nová verze 1.89 editoru zdrojových kódů Visual Studio Code (Wikipedie). Přehled novinek i s náhledy a animovanými gify v poznámkách k vydání. Vypíchnout lze, že v terminálu lze nově povolit vkládání kopírovaného textu stisknutím středního tlačítka myši. Ve verzi 1.89 vyjde také VSCodium, tj. komunitní sestavení Visual Studia Code bez telemetrie a licenčních podmínek Microsoftu.

    Ladislav Hagara | Komentářů: 36
    2.5. 21:22 | Nová verze

    Proton, tj. fork Wine integrovaný v Steam Play a umožňující v Linuxu přímo ze Steamu hrát hry určené pouze pro Windows, byl vydán ve verzi 9.0-1 (𝕏). Přehled novinek se seznamem nově podporovaných her na GitHubu. Aktuální přehled her pro Windows běžících díky Protonu také na Linuxu na stránkách ProtonDB.

    Ladislav Hagara | Komentářů: 2
    2.5. 19:33 | Nová verze

    Byla vydána verze 1.78.0 programovacího jazyka Rust (Wikipedie). Podrobnosti v poznámkách k vydání na GitHubu. Vyzkoušet Rust lze například na stránce Rust by Example.

    Ladislav Hagara | Komentářů: 0
    Podle hypotézy Mrtvý Internet mj. tvoří většinu online interakcí boti.
     (63%)
     (8%)
     (16%)
     (13%)
    Celkem 109 hlasů
     Komentářů: 8, poslední 4.5. 08:25
    Rozcestník

    Dotaz: daemon v c++

    20.2.2011 22:59 Pfemir | skóre: 5
    daemon v c++
    Přečteno: 1006×
    Dobrý den, napsal jsem si program v C++, který načítá data ze seriové linky, upravuje je a ukládá do souboru. Protože tento program poběží trvale, napadlo mě, že by bylo lepší udělat daemona. Protože o tomto typu programování moc nevím, našel jsem si na netu kuchařku viz. http://peterlombardo.wikidot.com/linux-daemon-in-c .Vypadá to jednoduše, ale i tak mi zřejmě unikají některé závislosti. Nevím jak tam spustím ten svůj kód. Když ho napíšu do oblasti TODO: Insert core of your daemon processing here tak se nic nestane, protože sem mi to ani nedojde. Celé to skončí o pár řádků výš na exit(EXIT_SUCCESS);. Můžete mě někdo nakopnout jak to dát dohromady?

    Díky.

    Odpovědi

    Luboš Doležel (Doli) avatar 20.2.2011 23:16 Luboš Doležel (Doli) | skóre: 98 | blog: Doliho blog | Kladensko
    Rozbalit Rozbalit vše Re: daemon v c++
    Démon se od běžného konzolového programu liší tím, že má init skript a možná volá daemon() (ale nemusí).
    21.2.2011 00:39 mich | skóre: 16
    Rozbalit Rozbalit vše Re: daemon v c++
    Pokud to z doliho odpovědi není jasné, tak doplním. Jestli nechápeš ten kód (fork, setsid), tak ho zahoď a normálně použij funkci daemon. Z manu vyčteš jak ji použít, pokud bys byl hodně zmatený, tak zavolej daemon(0, 0) a zkontroluj, že návratová hodnota je 0.
    je to teď v módě, na žive o tom furt píšou
    20.2.2011 23:51 Martin Tůma | skóre: 39 | blog: RTFM | Praha
    Rozbalit Rozbalit vše Re: daemon v c++

    Na EXIT_SUCCESS ti skončí rodičovskej process, forknutej child ti IMHO pokračuje dál.

    Každý má právo na můj názor!
    21.2.2011 08:16 Pfemir | skóre: 5
    Rozbalit Rozbalit vše Re: daemon v c++
    To Martin Tuma: Ano na pozadí tam furt něco běží. Ale stále nevím jak do toho dostat ten svůj kód.

    To Luboš Doležel (Doli), mich: Ano z toho jsem řádně zmatený. Zkusím něco vypátrat o tom daemon(), třeba se mi podaří něco více pochopit.
    21.2.2011 10:44 Sinuhet | skóre: 31
    Rozbalit Rozbalit vše Re: daemon v c++

    No normalne ten kod dejte za to TODO. Jestli vam jde o to ujistit se, ze na pozadi opravdu bezi vas kod, tak si treba zapiste nejakou hlasku do logu.

    Jinak muzete vyuzit bud uz zminene volani daemon(), nebo program daemon, ktery libovolny jiny program spusti na pozadi (dokaze ho taky znovu spustit, pokud chcipne, etc.).

    21.2.2011 12:01 Pfemir | skóre: 5
    Rozbalit Rozbalit vše Re: daemon v c++
    No to jsem vložil, ale nic to nedělá. Nedělal jsem tedy zápis do logu, ale v tom svém kódu zapisuji data do souboru, ale nic se neděje. Když nastavím daemonize = 0, tak se ten můj kod za TODO spustí, ale to už, samozřejmě není daemon. Když dám daemonize = 1, tak nic. I když jsem v editoru jel step by step tak to za to TODO vůbec nevběhlo. Ale možná je to tak správně, nevím, dělam něco takového poprvé.
    21.2.2011 12:05 Michal Kubeček | skóre: 72 | Luštěnice
    Rozbalit Rozbalit vše Re: daemon v c++
    Nedělal jsem tedy zápis do logu, ale v tom svém kódu zapisuji data do souboru, ale nic se neděje.

    Flushnul jste je po tom zápisu? Jinak se v souboru typicky nic neobjeví, dokud jich nezapíšete 4 KB nebo soubor nezavřete.

    21.2.2011 14:49 Pfemir | skóre: 5
    Rozbalit Rozbalit vše Re: daemon v c++
    Ano, soubor zavírám. Jak jsem psal, při daemonize = 0 to funguje, ale při daemonize = 1 ne. Ten samý kód, nijak ho neměním, jen tento parametr. Ani se ten soubor neotevře, resp. nevytvoří, prostě nic.
    21.2.2011 16:11 Michal Kubeček | skóre: 72 | Luštěnice
    Rozbalit Rozbalit vše Re: daemon v c++
    V tom případě je to divné. Ale asi bych musel vidět ten konkrétní zdroják, se kterým se vám to děje, jinak těžko hádat, kde je problém.
    21.2.2011 17:01 Martin Tůma | skóre: 39 | blog: RTFM | Praha
    Rozbalit Rozbalit vše Re: daemon v c++

    A jseš si vědomej toho, že ten kód mění aktuální pracovní adresář na "/", takže pokuď zadáváš do open/fopen relativní cestu, snaží se ten soubor vytvořit v "/"? Mimochodem, kontroluješ návratové kódy toho zápisu?

    Každý má právo na můj názor!
    Michy avatar 21.2.2011 17:05 Michy | skóre: 11 | Praha
    Rozbalit Rozbalit vše Re: daemon v c++
    Soubor se nevytvoří, protože při démonizaci se ještě volá chdir("/"), tedy aktuální adresář se nastaví na "/". Vytváříte-li soubor s relativní cestou a zmíněný proces neběží s právy roota, pak vytvoření souboru zákonitě selže.
    21.2.2011 17:35 Pfemir | skóre: 5
    Rozbalit Rozbalit vše Re: daemon v c++
    Nenašel jsem ten soubor nikde a vyjímky ohledně nevytvoření souboru mám ošetřené.
    21.2.2011 17:51 Martin Tůma | skóre: 39 | blog: RTFM | Praha
    Rozbalit Rozbalit vše Re: daemon v c++

    Takže všchny návratový hodnoty jsou ok, přesto se soubor nevytvoří, ano? To je nějaký divný, nemyslíš?! Bohužel nám začínají docházet věštecký koule, takže co kdyby si sem konečně nahrál ten tvůj kód. Uštří to čas tobě i nám...

    Každý má právo na můj názor!
    21.2.2011 18:49 Pfemir | skóre: 5
    Rozbalit Rozbalit vše Re: daemon v c++
    Takže se omlouvám, bylo to opravdu tou cestou. Takže mi teď vyvstala druhá otázka, proč mi to nic nezahlásilo. Když to pustím klasicky (daemonize = 0), tak mi to zařve 174:Permission denied. Při daemonize = 1 nic. Tady je testovací kód co tam momentálně pouštím.
        while(1)
        {
    
        fw1 = fopen("/home/pokus.txt", "a");
        if (fw1 == NULL)
        {
            fprintf(stderr, "%s %i:", __FILE__, __LINE__);
            perror(NULL);
            abort();
            return errno;
        }
        else
        {
            for (int i=1; i<10; i++)
            {
               fprintf(fw1, "%i ", i);
            }
            fprintf(fw1, "\n", "");
        }
        fclose(fw1);
        sleep(10);
        }
    21.2.2011 19:04 mich | skóre: 16
    Rozbalit Rozbalit vše Re: daemon v c++
    Prosímtě přečti si ten kód když ho kopíruješ...zavírá stdin, stdout i stderr.
    je to teď v módě, na žive o tom furt píšou
    21.2.2011 19:21 Pfemir | skóre: 5
    Rozbalit Rozbalit vše Re: daemon v c++
    Omlouvám se, ale teď jsi na mě promluvil cizí řečí. Jsem teprve začátečník.
    21.2.2011 19:27 Pfemir | skóre: 5
    Rozbalit Rozbalit vše Re: daemon v c++
    Už jsem to pochopil, jde o ten příkaz close(STDERR_FILENO);
    21.2.2011 19:48 mich | skóre: 16
    Rozbalit Rozbalit vše Re: daemon v c++

    Ok. Pokusím se ti popsat co dělá ten kód co kopíruješ odsuď v případě, že deamonize = 1 (respektive deamonize != NULL && deamonize != 0).

    • zavolá se fork() - vytvoří nový proces, a to tak, že vytvoří kopii původního procesu. Znamená to, že před voláním fork() máš jeden proces a po jeho zavolání máš dva, které provádějí ten stejný kód. Pokud chceš o fork vědět více, tak použij manuálové stránky. man fork
    • Kontrola pid - fork() vrací rodičovskému (původnímu) procesu pid (proces id) nově vytvořeného procesu. Právě tomu nově vytvořenému procesu vrací 0. Kód tady ukončí původní proces, ale ten nový běží dále.
    • volání umask() - nastaví masku, která bude použita při vytváření nových souborů. Zase man umask.
    • volání setsid() - vytvoří novou process grupu. man 3 setsid (Ano man je tvůj nejlepší kamarád).
    • chdir("/") - změní aktuální adresář na / - už se to tu řešilo.
    • volání close(STDIN_FILENO), close(STDOUT_FILENO), close(STDERR_FILENO) - Každý proces má tři základní deskriptory souboru. stdin = standard input = u tebe vstup z klávesnice. stdout = standard output = u tebe bufferovaný výstup na terminál. stderr = standard error = u tebe nebufferovaný výstup na terminál. Když například voláš ve svém kódu fprintf(stderr, "%s %i:", __FILE__, __LINE__), tak zapisuješ (překvapení) na stderr. Ta volání close() všechny tyto deskriptory zavřou, takže už je nemůžes použít.
    Ještě bych dodal, že volání daemon dělá uplně to samé a parametry toho volání můžeš nastavit, jestli se budou zavírat deskriptory a jestli se bude měnit adresář na /.
    je to teď v módě, na žive o tom furt píšou
    21.2.2011 20:14 Pfemir | skóre: 5
    Rozbalit Rozbalit vše Re: daemon v c++
    Velice děkuji za popis i ostatním za pomoc. Teď už to snad nějak spytlíkuji dohromady. A jestli ne, tak se určitě ozvu.

    Díky.
    1.3.2011 23:26 Pfemir | skóre: 5
    Rozbalit Rozbalit vše Re: daemon v c++
    Příloha:
    Tak bohužel mám ještě jeden problém. Program mám více méně hotový, teď dělám testy a zjistil jsem následující problém. Když program pustím ve standardním režimu, tak šlape bez chybičky. Když ho ale pustím jako daemon, tak se při načítání dat ze seriového portu občas ztrácí znaky. Co jsem vypozoroval, tak většinou když mi běží ještě něco jiného, např. když pustím rozbalování RARu. Přitom CPU mi nejede na 100%, aspoň správce úloh to tvrdí. Nevíte někdo proč k tomu dochází a co by se s tím dalo dělat? V příloze přikládám část programu, kde obsluhuji seriovou linku.

    Načítám sekvence 48 znaků a ukládám do inpPole, ale, jak jsem psal, když to běží jako daemon, tak mi tam občas nějaký znak chybí.

    Předem díky za pomoc.
    2.3.2011 10:00 frr | skóre: 34
    Rozbalit Rozbalit vše Re: daemon v c++

    Zdá se, že spoléháte na to, že alokovaný struct obsahuje samé nuly. Což obecně nemusí být pravda, a nemusí to být ani vhodné. Každopádně pokud začínáte s prázdnou "struct termios", tak se doporučuje napřed použít cfmakeraw(). V některých distrech (verzích glibc?) se nám dokonce osvědčilo ještě před cfmakeraw() strčit bzero(&moje_termios,sizeof(moje_termios)); tj. zaručeně ten struct dospod vynulovat.

    Takže vlastně ani není jisté, jestli máte zapnutý nebo vypnutý "canonical processing" (taková terminálová chytristika, která může žrát některé znaky).

    Taky tam nikde nevidím flow control (CRTSCTS), což bych doporučoval. Používáte na fyzickém portu flow control nebo ne? Aby tam náhodou nepřetékalo FIFO...

    S Vaším problémem to nesouvisí, ale taky není špatný nápad staré nastavení termios pro daný sériový port napřed zazálohovat, a při ukončení programu zase vrátit zpátky.

    Tady je útržek zdrojáku z nějakého mého projektu, kde používám sériový port pro "surová data":

     struct termios mine;
    
       line->saved = (struct termios*) malloc(sizeof(struct termios));
       result = tcgetattr(fd,line->saved);               // get the current serial line settings
    
       cfmakeraw(&mine);                                  // a combo (see man cfmakeraw)
       cfsetispeed(&mine,mogrify_baud(line->baud));       // input speed
       cfsetospeed(&mine,mogrify_baud(line->baud));       // output speed
       mine.c_cflag |= (CLOCAL | CREAD);                  // not an owner of the tty; receiver on
       mine.c_cflag &= ~CSIZE;                            // set data bits
       mine.c_cflag |= mogrify_bits(line->bits);          //     actual number of data bits
       // parity:
       if (mogrify_par(line->parity) == ~PARENB)
          mine.c_cflag &= ~PARENB;                        // no parity
       else
          mine.c_cflag |= mogrify_par(line->parity);      // some kinda parity is enabled
       // stop bits:
       if (mogrify_stopb(line->stopbits) == ~CSTOPB)
          mine.c_cflag &= ~CSTOPB;                        // only one stop bit, not two
       else
          mine.c_cflag |= CSTOPB;                         // two stop bits
       // flow control
       if (line->flow > 0)
          mine.c_cflag |= CRTSCTS;                        // hardware flow control
       else
          mine.c_cflag &= ~CRTSCTS;                       // no flow control
       //mine.c_cc[VMIN] = 10;                              // ? minimum volume (bytes)
       //mine.c_cc[VTIME] = 0;                              // ? timeout (if no data received)
      
       result = tcsetattr(fd,TCSANOW,&mine);                     // apply the settings
    

    V tom kódu jsou odkazy na další moje pomocné funkce mogrify_*() které přepracovávají moji "lidskou" konfiguraci na nelidské opšny termios :-) Celé to najdete tady, jmenuje se to "serial probes". Není to žádný výkvět programátorské čistoty a elegance... uvidíte sám.

    [:wq]
    2.3.2011 12:17 Pfemir | skóre: 5
    Rozbalit Rozbalit vše Re: daemon v c++
    Děkuji za odpověď, trošku v tom plavu takže postupně.

    Dívám se na ten Váš výpis a řekl bych, že to mám +/- stejné. Jediný rozdíl vidím v cfmakeraw(&mine);. CRTSCTS jsem zkoušel, ale nepozoroval jsem žádný rozdíl. Takže můžu zkusit tam šoupnout ten cfmakeraw(), ale nemyslím si, že to pomůže. Hlavně mi nejde do hlavy, proč to blbne pouze jako daemon.
    2.3.2011 12:41 frr | skóre: 34
    Rozbalit Rozbalit vše Re: daemon v c++
    Uvidíte, co případně udělá cfmakeraw.

    Ohledně rozdílu "démon vs. terminálová aplikace" : teoreticky by to mohlo znamenat, že démonizací se Váš proces octne mimo "control group" Vaší konzoly, která může mít v CPU schedulingu trochu vyšší prioritu. Ale spíš bych hledal nějaký problém v sériovém subsystému. Ohledně případného "nestíhání", mám pocit že linuxový TTY subsystém má v kernelových driverech docela velký buffer (stovky bajtů až jednotky kB) - takže nějaké vytížení user-space by nemělo mít velký vliv. Vlastní čtení z UARTu běhá na klasických PCI/ISA UARTech v hardwarovém interruptu - takže zdržující vliv by mohla mít jedině zátěž v jiných interruptech, případně veliká zátěž na PCI sběrnici resp. hublinku (co máte za systémový čipset?) - třeba nějaké přenosy na HDD po strop sekvenční kapacity. Popravdě řečeno, nejsem si jist, jak přesně vypadá řetěz událostí a bufferů na USB. Ale skoro bych řekl, že nakonec dost podobně, možná dokonce líp...

    CRTSCTS nezpůsobuje žádný rozdíl? To je zvláštní, neshodné nastavení flow control u dvou komunikujících zařízení typicky způsobuje naprostou nefunkčnost :-) S čím se to po sériové lince bavíte? Je to fakt RS232, není to 422/485? (Na half-duplexních sběrnicích nefunguje flow control.) Pokud je to RS232, které signály máte v kabelu zapojeny? Aha, vy ten device otvíráte read-only... tzn. nic neposíláte... čili tam možná flow control fyzicky není. A možná je kabel zadrátovaný tak, aby to fungovalo s i bez flow control (jenom klema v konektoru) - takže když UART přestane stíhat, tak "zdroj dat" stejně posílá dál. Ale že by počítač nestíhal 9600bps? Podivné...

    Koukám do Vašeho zdrojáku, že ten sériový port je nějaký USB dongle. Co je to konkrétně za kousek? Jaký to má čip? Nebyl by výstřižek z dmesg, kde je ten dongle detekován? Nebo výpis lsusb... Různé USB dongly by se mohly lišit hloubkou FIFO bufferu v UARTu.

    Hloupej nápad: nejede Vám několik zapomenutých instancí toho démona paralelně? :-)
    [:wq]
    2.3.2011 13:06 Pfemir | skóre: 5
    Rozbalit Rozbalit vše Re: daemon v c++
    Zkusím to trochu přiblížit.

    V USB mám převodník USB - RS485, pouze 2 dráty, nic víc. S ničím nekomunikuji jen čtu data co příjdou. Chodí sekvence 48 znaků rychlostí 9600baudu cca 3x za minutu (takže žádný kvapík).

    Výpis části dmesg:
    [362032.304531] ftdi_sio ttyUSB0: FTDI USB Serial Device converter now disconnected from ttyUSB0
    [362032.304587] ftdi_sio 3-2:1.0: device disconnected
    [362044.324454] usb 1-7: USB disconnect, address 5
    [362100.104117] usb 5-1: new full speed USB device using uhci_hcd and address 2
    [362100.302338] ftdi_sio 5-1:1.0: FTDI USB Serial Device converter detected
    [362100.302504] usb 5-1: Detected FT232BM
    [362100.302513] usb 5-1: Number of endpoints 2
    [362100.302521] usb 5-1: Endpoint 1 MaxPacketSize 64
    [362100.302529] usb 5-1: Endpoint 2 MaxPacketSize 64
    [362100.302536] usb 5-1: Setting MaxPacketSize 64
    [362100.303369] usb 5-1: FTDI USB Serial Device converter now attached to ttyUSB0
    [362182.533603] r8169 0000:01:00.0: eth1: link down
    [362189.364953] r8169 0000:01:00.0: eth1: link up
    [362396.131222] ttyUSB0: 6 input overrun(s)
    [363407.962925] ttyUSB0: 7 input overrun(s)
    [363719.626233] show_signal_msg: 12 callbacks suppressed
    
    Teď se dívám, že v dmesg je i toto:
    [363719.626245] monkotel-daemon[23575]: segfault at 1 ip 00799b33 sp bfdfc0ec error 4 in libc-2.12.1.so[759000+157000]
    [364095.010147] ttyUSB0: 7 input overrun(s)
    [364557.204599] ttyUSB0: 7 input overrun(s)
    To je ten můj daemon. Můžete mi někdo naznačit co mi to říka?

    Jinak běžím na ITX desce s Atomem N270, čipová sada je tam nějaká ta intel945, nevím teď přesně.
    2.3.2011 13:57 frr | skóre: 34
    Rozbalit Rozbalit vše Re: daemon v c++
    Jasně. Takže flow control tam reálně není. Čipset PC je relativně moderní, tam by snad hublink neměl být úzkým hrdlem.

    Input overruns? Zajímavé :-) Žeby malý buffer v hardwaru?

    http://www.ftdichip.com/Products/ICs/FT232BM.htm

    Žeby 384B bylo málo? Na 9.6kbps? To je nějaký blábol... Jinak FTDI je asi nejlepší značka USB/232 převodníků. Ty hlášky "input overrun(s)" jsou patrně z generického TTY subsystému, ovladač USB Serial podle mého jenom předá TTY subsystému informaci, že FT232 zahlásil overrun.

    http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/usb/serial/ftdi_sio.c (a hledejte "overrun".)

    Spíš mi to přijde, jako že démon se kdesi zamyslí/zacyklí/usne navždy, přitom má otevřené zařízení ttyUSB0. No a poté co se naplní kernelový buffer, pak i hardwarový buffer FT232, tak si FT232 začně stěžovat přes USB, že mu přetéká buffer - a ta hláška se dostane skrz TTY subsystém až do dmesg.

    Segfault v libc? To by ten démon měl především umřít :-) A jinak by to klidně mohl být důsledek neinicializovaných termios (no pod haubnou to neznám). Chtělo by to zjistit, kde to přesně chcíplo (pokud se to stává při každém spuštění) = pustit démona přes GDB a v momentě kdy chcípne, tak si udělat bt (=backtrace). Vypadne Vám z toho call stack funkcí, odkud se ten program dostal do místa, kde zhavaroval. Předpoklad je, že ten program máte zkompilovaný s g++ opšnou "-g". Něco málo by ukázal i strace (ukáže jenom syscally, nevidí jednotlivé "řádky programu" ani knihovní funkce).

    Žeby ten démon po pádu zůstal z nějakého důvodu ve stavu "zombie"? To je divné, na detached proces snad není potřeba explicitně čekat, jako u vláken. Přemejšlím, jestli se do toho stavu nemůže dostat vlastním přičiněním, třeba vymaskováním nějakého signálu potřebného k nanebevzetí... ale moc tomu nevěřím.

    Koukejte, jestli ty hlášky v logu přibývají, jestli to není jenom historický pozůstatek nějakých předchozích pokusů. Pokud přibývají, tak to ten démon dělá pořád a máte na co se zaměřit.

    Nechodivým IRQčkem USB OHCI to nebude - to by kromě dat nechodily ani ty varovné URBy že overrun.
    [:wq]
    2.3.2011 15:29 Pfemir | skóre: 5
    Rozbalit Rozbalit vše Re: daemon v c++
    Díky za obsáhlou odpověď, ale abych se přiznal 3/4 textu vůbec nerozumím, je to na mě moc technické.

    Nicméně daemon mi neusne ani nezhavaruje. Vypisuji ty příchozí znaky do souboru a píše to stále. Akorát tam občas nějaký znak chybí.

    Co tedy můžu udělat, abych poskytl více informací? Nevím co je GDB ani g++ a -g. Kompiloval jsem to v Code::Blocks IDE.

    Co se týká logu, tak nevím kde je hledat. Měl jsem za to, že budou ve /var/logs , ale tam jsem nic takového nenašel.

    Díky za trpělivost.
    4.3.2011 18:30 Pfemir | skóre: 5
    Rozbalit Rozbalit vše Re: daemon v c++
    Takže stále testuji. Dělal jsem nějaký update linuxu a hlavně jsem do kodu vrazil ten cfmakeraw(); Teď mi to běží už asi 30hodin a bez chyby. Ani v dmesg už nejsou ty overrun chyby, takže to vypadá na úspěch.

    Jestli můžu, tak bych měl ještě nějaké drobné dotazy:

    1) Když mám ten dongle připojený a nemám spuštěného daemona, tak zřejmě začne přetíkat buffer a když daemona pak spustím, tak mi to vyplivne X znaků a mě to pak dělá chyby při jejich dekodování. Dá se na začátku, při spuštění, nějak ten buffer vymazat a začít s čistým?

    2) Dal jsem si v linuxu v Startup Applications spouštění toho daemona příkazem /home/pfemir/Applications/monkotel-daemon. Sice se spustí, i funguje, ale všiml jsem si, že žere 50% CPU. Když ho ale spustím z terminálu přes ./monkotel-daemon tak nežere nic. Čím to může být?

    3) Když daemona spustím a podívám se do webminu a spuštěné procesy, tak tam má přiřazenu střední prioritu (4). Ale po nějaké době se změní na vysokou (0). Může mi někdo vysvětlit kdo a na základě čeho tu prioritu přiděluje?

    Děkuji všem za pomoc.
    7.3.2011 09:30 frr | skóre: 34
    Rozbalit Rozbalit vše Re: daemon v c++
    1) po otevření zařízení zavolat tcflush(fd, TCIFLUSH); // nebo TCIOFLUSH, asi ne TCOFLUSH

    2) a kolikajádrový máte procesor? Dvoujádro? Pokud dvoujádro, tak to znamená, že ten proces sežral celé jedno jádro = jede v nějaké nebržděné smyčce. Těžko říct, proč vlastně.

    3) ohledně priorit procesů netuším. Možná to scheduler upravuje nějakou heuristikou. Popravdě netuším, o jakou prioritu se vlastně jedná (nice? asi sotva) - těmito věcmi jsem se nikdy moc nezabýval.
    [:wq]
    7.3.2011 12:20 Pfemir | skóre: 5
    Rozbalit Rozbalit vše Re: daemon v c++
    1) V programu mám tcflush(port, TCIFLUSH); ale nepomáhá.

    2) Psal jsem, že mám Atom N270, čož je jednojádro. Ale furt nechápu proč když to spustím automaticky po startu systému tak to žere 50% a když ručně z terminálu tak nic. Počet jader na to snad nemá vliv.
    7.3.2011 19:21 frr | skóre: 34
    Rozbalit Rozbalit vše Re: daemon v c++
    tcflush nezabral? Máte napřed open() a až pak tcflush()? Ještě jsem vygooglil zmínky, že není špatné vložit mezi open() a tcflush() ještě krátký delay, např. usleep(200000).

    Atom N270 má HT, takže se tváří jako dvě logická jádra. Viz dmesg a /proc/cpuinfo. Takže 50% CPU skutečně znamená jedno celé jádro.

    Kde a proč je tam nebržděná smyčka, a proč jenom při startu přímo z initu? Tak to Vám opravdu neporadím :-) Mrkněte se, kde voláte jaké syscally ve smyčce, možná předpokládáte, že ten syscall bude blokovat, a on se přitom okamžitě vrátí s nějakou chybovou hláškou... atp. Nejjednodušší způsob, jak to nalézt, je možná tento: přidejte si na pár míst v programu jednoduché hlášky typu syslog(LOG_INFO,"checkpoint 123") a pomocí "tail -f /var/log/messages" sledujte, kudy program běží. Viz též "man syslog". Já obvykle dávám tyhle hlášky na začátek zajímavých funkcí a cyklů, případně před a za podezřelé syscally - dám jich tam třeba 4-5 ks a pak postupně zužuji oblast, kde se program zasekne. Používat takovouhle instrumentaci moc nejde v časově kritických cyklech, ale to nebude Váš problém...

    V kernelu je jeden vtipný způsob, jak se dostat do podobné situace "mimo hlavní stezku programu", a to je špatně napsaná obsluha level-triggered interruptu (takže se obsluha volá pořád dokola) - ale v user space k tomu těžko hledám analogii, například špatnou prací se signály si program spíš odříznete od signálů, než zacyklíte... V user space je taky humorné naběhnout si na nekonečnou autorekurzi :-) ale to poznáte, program během pár vteřin sežere celou volnou RAMku. Aby se Vám interně zacyklil syscall nebo knihovní funkce libc, to se stává opravdu vyjímečně.
    [:wq]
    7.3.2011 20:31 Pfemir | skóre: 5
    Rozbalit Rozbalit vše Re: daemon v c++
    Ano, nejdříve mám open a až pak tcflush. 1.3. jsem v příloze serial.txt posílal část svého programu ohledně seriové linky, tam to je vidět. Zkusím ještě tu prodlevu.

    S těma výpisama do logů jsem to už částečně zkoušel, ale na nic moc jsem nepřišel. I když to žere to celé jádro, tak ten program normálně funguje. Ve výstupních souborech mám všechny znaky, už se mi ani žádné neztrácí. Zkusím ještě pátrat dále.
    7.3.2011 22:15 frr | skóre: 34
    Rozbalit Rozbalit vše Re: daemon v c++
    No... ještě mě napadá, že pokud by ten otevřený file descriptor (int port) se nějak magicky dostal do "nonblocking" režimu, tak by se read(port,...) vracel hned, ať už nějaká data načetl nebo ne. Mrkněte do manuálu / zagooglete ohledně fcntl() a O_NONBLOCK, a zkuste testnout, jestli Vám ta pracovní smyčka nejede nějak moc rychle :-)

    A ještě mě napadá, pokud vidíte příliš velkou spotřebu CPU za celý proces, není ten proces náhodou "rozvlákněný"? Třeba já když píšu vícevláknového démona, tak si ve funkci main() spustím pár vláken-pracantů, a prvotní rodičovské vlákno se třeba jenom zasekne ve věčném sleep() uvnitř "while (true)" smyčky a víceméně čeká na signál k ukončení... Nemohlo se stát, že Vám bůhvíproč cyklí nějaké další vlákno, vedle Vašeho "pracanta", který se chová normálně? Ještě mě napadá, že "top -H" by mohl ukázat jednotlivá vlákna...
    [:wq]
    21.2.2011 20:12 qazasd
    Rozbalit Rozbalit vše Re: daemon v c++
    Jenom bych pro uplnost dodal, ze pro spusteni procesu na pozadi (deamona) neni nezbytne nutne forkovat atd. Lze vyuzit napr. sluzeb programu nohup.

    Program se napise jako normalni aplikace a pak se spousti pomoci
    nohup /bin/program > /dev/null  2>&1 &
    napr. z /etc/rc.local

    Vysledek je stejny a clovek usetri dle meho nazoru zbytecnou praci. Tot jenom pro uplnost tematu.

    Jeste lepsi je mozna pouzit start-stop-deamon
    start-stop-daemon --pidfile /var/run/mujprogram.pid --start --background --exec /bin/sleep -- 10
    
    ... kde jako bonus ziskame pidfile, a je tak otazka scriptu na 5 radku implementovat standardni /etc/init.d/mujprogram start, /etc/init.d/mujprogram restart ... atd ...
    21.2.2011 23:19 Michal Kubeček | skóre: 72 | Luštěnice
    Rozbalit Rozbalit vše Re: daemon v c++
    Příkaz nohup nemá se spuštěním na pozadí nic společného, to má na starosti ten ampersand na konci. Stejně tak se nestará ani o další opatření, která jsou u démonů běžná. Příkaz nohup je jen wrapper, který zajistí, že váš program nebude ukončen signálem HUP.
    22.2.2011 01:37 Sten
    Rozbalit Rozbalit vše Re: daemon v c++
    nohup pro démony určitě není.

    start-stop-daemon je lepší, ale buď ten program už musí být démon anebo se to start-stop-daemon snaží oberličkovat (více či méně úspěšně).

    Nejlepší řešení je daemontools, to se stará i o restarty a logování stderr :-)

    Založit nové vláknoNahoru

    Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

    ISSN 1214-1267   www.czech-server.cz
    © 1999-2015 Nitemedia s. r. o. Všechna práva vyhrazena.