Příklady ze zkoušek

Zde je na ukázku několik zadání ze zkoušek. Čas na vypracování je 120 minut.

Způsob hodnocení je na hlavní stránce, základní podmínka je však jednoduchá - příklad musí fungovat, jinak je termín automaticky neúspěšný.

Síťové programování, signály

Napište dva programy, klient a server. Komunikace probíhá přes TCP na lokálním stroji, přes sockety typu AF_INET. Klient přijme jako parametr z příkazové řádky číslo signálu a volitelně i port, připojí se na server na daný port (pokud není zadán, použije se default) a serveru sdělí svůj PID a číslo signálu.

Server následně pošle příslušný signál na zadaný PID, vypíše o tom hlášení. Klient musí daný signál zachytit, vypíše zprávu o zachycení a skončí. Server je jednovláknový, po načtení dat a poslání signálu se znovu uspí ve volání accept().

Modifikace pro jiný předtermín bylo použití UDP místo TCP.

Tento příklad považuju za středně těžký.

Vlákna a jejich synchronizace

Hlavní vlákno vytvoří počet vláken zadaný jako parametr příkazové řádky. Každé vlákno simuluje činnost pomocí sleep() na náhodnou dobu, 1 až 10 sekund. Po vykonání činnosti, tj. po ukočení funkce sleep(), vlákno zahlásí hlavnímu vláknu, že skončilo. Hlavní vlákno okamžitě vytvoří další vlákno.

Cílem je tedy udržovat stále stejný počet vláken v běhu. Každé vlákno má navíc svoje pořadové číslo, při vytvoření a zániku vlákna se vypíše na termínál hlášení o této skutečnosti, s použitím pořadového čísla.

Pro synchronizaci použijte mutexy a podmínkové proměnné. Aktivní čekání je nepřípustné. Velký důraz je kladen na korektnost použití synchronizačních primitiv.

Tento příklad považuju za lehký.

Simulace shellových příkazů

Pomocí volání pro práci se soubory (open, read, write, close) si do aktuálního adresáře zkopírujte soubor /etc/services. Poté nasimulujte příkaz cat services | grep tcp | wc -l.

Simulace musí proběhnout tak, že každý z daných tří příkazů provedete vlastním voláním exec z vlastního procesu, použití způsobu typu "sh -c 'cat services | grep...'" není korektní řešení. Procesy pospojujte rourami a v hlavním procesu pak počkejte na dokončení. Hlavní proces tedy nepoužívá volání exec a je proto nutné použít volání fork třikrát. Příkaz wc nemusí data předat hlavnímu procesu, může je vypsat rovnou na terminál.

Všechny deskriptory které nejsou používané je nutné zavřít.

Tento příklad považuju za středně těžký.

inetd

Napište jednoduchý inetd server pro TCP služby, konfigurace je obsažena v textovém konfiguračním souboru. Formát konfiguračního souboru je jasný z tohoto příkladu:

2222
/bin/cat
3331
/bin/sed
3332
...
...
...

Server poslouchá na všech zadaných portech najednou, pomocí pasívního čekání (= pomocí select nebo poll). Po akceptování spojení na některý z portů vytvoří nový proces, jeho deskriptory 0, 1 a 2 na napojí na nově vytvořený socket a nakonec zavolá exec() na daný program. Tyto procesy tedy již dál běží paralelně vůči serveru.

Pro jednoduchost uvažujte, že program již nemá další parametry. Po každém akceptování připojení na jakýkoli z portů se zbavte zombie procesů, pokud existují.

Zpracování konfiguračního souboru je povoleno pouze pomocí volání open, read, close.

Ověření funkčnosti je jednoduché, pomocí telnetu. V případě /bin/cat se stačí připojit na příslušný port a telnet relace se musí chovat jako echo - co napíšete se vám musí vypsat zpátky nezměněno.

telnet localhost 2222
...

Tento příklad považuji za těžší.