FAQ ku C a sluzbam Unix-u Flashcards

1
Q

Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)

Čo znamená v zadaniach spomínaný termín “plná cesta” ?
Je to cesta z aktuálneho, alebo koreňového adresára ?

A

Čo je absolútna a relatívna cesta, je asi jasné.
Plnou cestou je myslená celá cesta od zadaného adresára až po nájdený súbor (teda môže to byt aj relatívna aj absolútna cesta - podľa toho, ako je zadaný adresár).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)

Pod pojmom obyčajný súbor si mam predstaviť iba txt alebo aj bin ?

A

Obyčajný súbor = regular file, t.j. nie adresár, nie sym. linka, nie device, …

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)

V ukážkovom príklade Listdir.c sa robí s funkciou readdir. Tá je síce popísaná aj v manuáli aj na školskom webe (dokumentácia ku knižnici libc) no z toho som nepochopil napríklad čo je to d_namlen a d_name, pripadne či sú nejaké ďalšie premenné, ktoré by mi mohli pomôcť. Môžem dostať nejaké vysvetlenie?

Existuje niekde lepší popis tejto a ostatných funkcii, ktoré potrebujeme?

A

Keď si pozriete man readdir, tak na konci je sekcia “SEE ALSO”, teda odkazy na manuály, ktoré Vám môžu tiež pomôcť. Medzi nimi je aj odkaz na man dir - je tam celkom slušne popísaná štruktúra adresára.
Ďalšie zaujímavé informácie môžete nájsť aj v hlavičkových súboroch. Na tie Vás zase odporúča sekcia “SYNOPSIS” na začiatku manuálovej stránky.
Príslušné súbory nájdete v adresári /usr/include .

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)

Kde nájdem popis štruktúry direct ?

(nenašiel som ani v dirent.h, ani v sys/types.h)

A

Keby ste urobili grep -w direct /usr/include/*/*.h ,
zistili by ste, že v sys/dir.h je:
#define direct dirent

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)

Čo je to d_ino ?
while ((dir = readdir(dp)) != NULL) {if (dir->d_ino == 0) continue; … }

A

Je to položka, obsahujúca číslo i-uzlu, na ktorý odkazuje príslušná položka adresára.
Ak je nulová, znamená to, že príslušná položka adresára nie je použitá.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)

Prečo mi stat(….) a S_ISREG(..) berie symbolické linky ako regulárne súbory ? Dá sa to nejako spraviť aby ich bral ako linky ?

A

Ide o to, že keď urobíte stat na symbolickú linku, vráti Vám informácie u súbore, na ktorý daná linka ukazuje. Keď chcete informácie o linke samotnej, použite lstat.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)

Ako sa pomocou readdir dozviem, či vypisovaný súbor je súbor, adresár, link a podobne?

A

Cez readdir sa to nedá spraviť. Treba sa pozrieť na funkciu stat (a lstat, pozrite si “man lstat”) a použiť makro S_IFDIR().

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)

Aký je rozdiel medzi položkou st_mode v struct stat so statusom S_IFREG a položkou d_type v struct dirent so statusom DT_CHR ?

A

Položka stat.st_mode obsahuje typ súboru, tak ako ho zistí funkcia stat. Položka dirent.d_type tiež zrejme obsahuje typ súboru a predpokladám, že readdir po načítaní urobí príslušný stat a naplní položku.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)

Ako sa dá zistiť, na aký súbor ukazuje daný symbolický link ?

A

Skúste sa pozrieť na systémové volanie readlink.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)

Dá sa nejako zadať veľkosť súboru ? Prípadne, aby sa dynamicky zväčšil súbor a podobne ?

A

Keď otvoríte súbor a zapisujete doň, tak sa veľkosť automaticky zväčšuje, teda koľko zapíšete, taký je veľký. Keď už súbor existuje a chcete ho zväčšiť, musíte sa buď pred zápisom presunúť na koniec súboru (lseek a potom write) alebo otvoriť súbor na pridávanie (fopen(…, “a”)).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)

Prečo mi volanie readlink vždy vráti errno == 0 aj v prípade, že zruším cieľový súbor (kam daná linka ukazuje) ?

A

Nuž je to veľmi jednoduché, pretože volanie readlink Vám vráti obsah linky, teda konkrétne tu cestu, kam symbolická linka ukazuje (teda nie obsah toho súboru - na to stačí obyčajný read). No a samozrejme keď cieľový súbor zrušíte, tak linka stále existuje a môžete zistiť cestu kam ukazuje.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)

Ako mám rekurzívne prehľadávať adresáre, mám ich prehľadávať tak, že budem nasledovať aj linky ? (teda, čí mam použiť stat alebo lstat.)

A

Je symbolická linka adresár ?

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)

Ako sa dá predísť (vyhnúť) chybe “Too many open files” pri použití funkcie opendir ?

A

Tato chyba vzniká, keď vyčerpáte limit na počet súčasne otvorených súborov na proces. Vyhnete sa jej jednoducho - všetky už nepotrebné otvorené súbory (aj adresáre) zatvárajte.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)

Robím rekurzívne prehľadávanie adresárov. Inkludujem súbor dir.h a mám s tým problémy. Čo s tým ?

A

Pri rekurzii treba inkludovať novší súbor dirent.h a nie dir.h. Pozor - súbor dirent.h sa na ose nachádza dva krát. Treba ho inkludnuť zo štandartnej c-čkovskej knižnice, teda:
#include
a nie #include .
Týmto vlastne zamedzíme varovným hláškam pri kompilácii. Ešte jedna zmena pri novom spôsobe: definujeme
“struct dirent *dir”;
a nie
“struct direct *dir”;
ako pri starom.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)

Pri rekurzívnom prehľadávaní veľkého adresára (napr. /) mi fork vypisuje chybu, errno = 35, (niekde mi to funguje bez problémov).
Z manuálu som vyčítal, že tento error je “temporary” a že nové volanie forku môže byť úspešné. (Na nájdené súbory ďalej púšťam grep.)

A

Chyba je asi spôsobená tým, že ste počas behu programu vyčerpali kvótu na počet procesov (32 na ose, 2048 na linux-e). A zrejme sa to stalo tak, že na každý nájdený súbor spúšťate grep, ale zabúdate počkať na jeho ukončenie a prevziať status cez volanie wait. Tak sa stane, že sa Vám nazbiera veľa skončených grep-ov, ktoré už len čakajú na to, aby si ich exit status prevzal ich rodič (sú z nich zombie - živé mŕtvoly - po exit-e).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)

int fdr; FILE* fr; …. fdr=open(… fr=fdopen(fdr,… fclose(fr);
Budem mat v tomto okamihu closnuty aj fdr alebo ho mozem dalej pouzivat ?? Predpokladam prvu moznost len si chcem byt na istom

A

Funkcia fdopen len “prilepi” vrstvu nad deskriptor, takze fclose sa sprava tak, ako keby to bolo otvorene cez fopen (takze zavrie aj deskriptor - urobi close).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)

Da sa nejako zistit, ci dany subor existuje bez toho, aby som sa ho pokusal otvarat? WIN/DOS mal findfirst/findnext, ale na ose som zatial ziadny ekvivalent nenasiel.

A

V Unix-e mate k dispozicii opendir, readdir a closedir. To Vam uplne staci ;-).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)

Vo FAQ je otazka ci sa da pomocou funkcie readdir zistit ci vypisovany subor je subor,adresar,link a podobne. Odpoved je ze nie treba pouzit stat.
Lenze: readdir nam vracia pointer na strukturu direct co je ale vlastne struktura dirent:

struct dirent { __uint32_t d_fileno; /* file number of entry */ __uint16_t d_reclen; /* length of this record */ __uint8_t d_type; /* –> file type, see below o trosku dalej su definovane konstanty pre d_type:
/* * File types */ #define DT_UNKNOWN 0 #define DT_FIFO 1 #define DT_CHR 2 #define DT_DIR 4 #define DT_BLK 6 #define DT_REG 8 #define DT_LNK 10 #define DT_SOCK 12 #define DT_WHT 14
ked som to vyskusal funguje to, je chyba vo faq ?

A

Nie. Nie je to chyba.
Ide o to, ze suborovy system v BSD sa snazi optimalizovat pristup k informaciam o suboroch a preto ma typ suboru skopirovany aj do polozky adresara - tym vlastne odstranuje jedno citanie z disku. Ked sa ale pozriete na strukturu dirent napr. v Linux-e, tak tam polozka d_type nie je (resp. v strukture je, ale nehovori sa o nej v manuali). V Solarise (system zalozeny na System V vetve Unix-ov) nie je ani v strukture. Preto Vam teda odporucam vyhnut sa jej pouzivaniu.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
19
Q

Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)

Ako sa da zistit, ze ci dany spusteny program ma pravo citat/zapisovat/spustat iny subor bez toho aby to skusil a cakal na chybove hlasenie?

A

Sluzi na to systemove volanie access(const char *path, int mode).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
20
Q

Práca s adresárovou štruktúrou a súbormi( readdir, stat, …)

Vytvorenie suboru s pravami.

fd=open(“aaa.aaa”,O_CREAT|O_WRONLY,0666);
mi vytvori subor s divnymi pravami rw-r–r–
a ja som cakal rw-rw-rw-
Neviete v com to moze byt?

A

Program zdedil masku nedovolujucu zapisat vacsie prava,
default je S_IWGRP|S_IWOTH (022) (takze write pre grupu a svet urcite nepovoli)
preto najprv pouzi umask:

umask(0);
v tomto pripade by vsak stacilo:
umask(S_IXOTH|S_IXGRP|S_IXUSR);

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
21
Q

Volania exec, execlp - spúšťanie externých programov

Môžem používať v C-čkovskom programe awk ? Napríklad potrebujem sa hrať s nejakými stĺpcami a pošlem na ne cez execlp awk.

A

Pokiaľ to nie je v zadaní explicitne povolené, tak nie.

Systémové volanie exec môžete použiť len v tých zadaniach, v ktorých sa vyžaduje spúšťanie programov. V žiadnom prípade nemôžete časť problému riešiť v C-shelli alebo awk.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
22
Q

Volania exec, execlp - spúšťanie externých programov

Chcel by som spustiť program find pomocou execl, ale neviem nájsť cestu, kde sa find nachádza (v /bin to nie je). Dá sa takto find vôbec spustiť ?

A

Okrem execl existuje aj volanie execlp, ktoré sa pokúsi vyhľadať spúšťaný program v adresároch uvedených v premennej path.

Keď chcete zistiť, kde sa spúšťaný program nachádza, skúste príkazy whereis, which.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
23
Q

Volania exec, execlp - spúšťanie externých programov

Ako sa v príkazoch execv a execvp zadávajú argumenty programu ?

A

int execv(const char *path, char *const argv[])

  1. argument execv je vlastne presne to, čo dostane funkcia main ako 2. argument (argv). Čiže treba vytvoriť pole pointrov na jednotlivé parametre a ukončiť ho nulovým pointrom. (Mimochodom je to veľmi elegantné na riešenie zadaní, kde máte spúšťať programy s parametrami oddelenými bodkočiarkou.)
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
24
Q

Volania exec, execlp - spúšťanie externých programov

Treba pri zadaniach, kde sa volá externý program, ošetrovať aj jeho chybový výstup ?

(t.j. či treba jeho chybový výstup vypisovať vo formáte Error:’…’)

A

Pokiaľ to nie je v zadaní explicitne uvedené, tak nie. Formátovať musíte len svoje vlastné chybové výpisy.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
25
Q

Volania exec, execlp - spúšťanie externých programov

execl(“/bin/ls”, “ls”, “-al”);

Ak tomu správne rozumiem, tento riadok by mal urobiť to isté, ako keď v shelli zadám
> ls -al
Ale neurobí to nič. Prečo?

A

Prepínače musia byť ukončené znakom NULL. Správne to má byť takto:
execl(“/bin/ls”, “ls”, “-al”,0);

26
Q

Volania exec, execlp - spúšťanie externých programov

Nasledujúci riadok:
execlp(“ls”, “-al”, 0);
by mal robiť to isté čo v shelli
>ls –al

Ale v skutočnosti to robí iba
>ls
Kde je chyba?

A

Chyba je v tom, že prvý argument (1. v poli argv) tzn. 2. argument pre funkciu execlp) má byť meno programu, ktorý chcete spustiť. (viď. manuál k exec) Čiže: execlp(“ls”,”ls”,”-al”,0);

27
Q

Volania exec, execlp - spúšťanie externých programov

Mám problém: Grep vypíše pri prehľadávaní veľa riadkov tohto typu: >grep : ‘/home/clovekxy/súbor’ permission denied

A

Ide o to, že by ste grep na taký súbor ani nemali pustiť. Teda by ste si mali už vo vašom programe ošetriť, či môžete alebo nie. V princípe je to veľmi jednoduché: súbor otvoríte a potom ho presmerujete na štandardný vstup grep-u, no a keď sa Vám ten súbor ani nepodarí otvoriť, nastala chyba.

28
Q

Volania exec, execlp - spúšťanie externých programov

Ak spustím pomocou volania exec program, ako zistím v rodičovi jeho exit status ?

A

Pozrite si systémové volanie wait, jeho parameter a príslušné makrá.

29
Q

Volania exec, execlp - spúšťanie externých programov

Skúšal som execlp(“who”, “who”, “|”, “cut”, “-c1-8”, “|”, “grep”, “-c”, user, NULL); a nezjedol mi to :-( . Dá sa to len cez viac forkov ?

A

Keď si uvedomíte, že za “|” je zodpovedný shell, musí Vám byť jasné, čo za nezmysel ste sa pokúšali robiť. (Spustili ste program “who”, ktorému ste ako argumenty dali VŠETKY zvyšné reťazce). Takže aby to fungovalo, rúry si musíte vyrobiť sami. Teda musíte spustiť 3 procesy a vhodne ich pospájať rúrami. (Dá sa to cez jeden fork tak, že sa v dcérskom procese spustí who a v rodičovi načíta vždy z každého riadku prvý reťazec a ten porovná s tým, čo chcete.)

30
Q

Práca s rúrami(pipes)

Chcem sa opýtať, či treba tvoriť rúru cez pipe a potom cez fork. V niektorých prípadoch sa dá použiť pekne popen(). Môžem ho použiť?

A

Súbor /home/OS/Pri.pocitaci: - v programe nesmú byť použité funkcie system a popen.

31
Q

Práca s rúrami(pipes)

Pri akej chybe mi vznikne chybové hlásenie “broken pipe” ?

A

Pokiaľ ide o chybu “Broken pipe”, tak tá sa vyskytne, keď chcete zapisovať do rúry, ktorú nemá nikto otvorenú na čítanie. (Zatvorený read-end)

32
Q

Práca s rúrami(pipes)

Kedy ma význam presmerovanie rúry na stdin, stdout ?

A

Presmerovavanie rúry na stdin, stdout má väčšinou význam v prípade, keď následne exec-ujete nejaký program, ktorý používa len štandardný vstup a výstup a chcete zabezpečiť, aby čítal (zapisoval), práve to, čo chcete. Teda mu jeho štandardný vstup (výstup) presmerujete … Pokiaľ v programe (procese) len čítate z deskriptorov, tak presmerovanie nemá význam, pretože môžete čítať z takého deskriptoru, z akého chcete (Vy predsa píšete príslušný kód.).

33
Q

Práca s rúrami(pipes)

Vytvorím child proces a jeho výstup presmerujem na rúru. V deskriptor table parent procesu zase vstup stdin presmerujem na výstup z rúry. To všetko je ok, a krásne to funguje. Lenže čo ak chcem zase použiť stdin v parent procese? (napríklad chcel by som načítať nejaký text z klávesnice). Dá sa nejakým spôsobom uchovať adresu stdin?

A

Nevidím dôvod presmerovavať rúru na stdin, veď v rodičovskom procese môžete čítať priamo z rúry - a stdin Vám zostane. Pokiaľ by ste ale naozaj chceli znova získať stdin, môžete to urobiť napr. tak, že ho na začiatku zduplikujete na nejaký iný deskriptor …

34
Q

Práca s rúrami(pipes)

Mam situáciu keď jeden proces zapisuje obsah nejakého súboru do rúry a druhý z nej v cykle číta pomocou read, v manuáli som sa dočítal, že jediný spôsob, ako čítajúcemu procesu oznámiť, že nastal koniec súboru, je zavrieť vstup rúry (urobil som cez close), a potom pri ďalšom pokuse o čítanie z rúry by sa mal vygenerovať signál SIGPIPE.

A

Čo sa týka oznámenia konca a uzavretia rúry máte pravdu. Čo sa však týka signálu SIGPIPE, tak ten príde procesu, ktorý sa snaží ZAPISOVAŤ do rúry, ktorú nemá nikto otvorenú na čítanie (teda presne opačný prípad).

35
Q

Práca s rúrami(pipes)

Ako by sa dalo čítať naraz z dvoch rúr, pripadne ako by sa dalo obísť stratu dát, keď musím prijímať informácie z dvoch rúr ?

A

Z dvoch rúr naraz čítať nemôžete. Musíte robiť read na každú z nich zvlášť. Keďže ale jeden read môže ostať zablokovaný pri čítaní z rúry, musíte to nejako obísť. Jedna (menej elegantná) možnosť je, urobiť na čítanie z každej rúry samostatný proces. Je aj iná možnosť, elegantnejšia, ale aj zložitejšia a asi aj nad rámec tohto predmetu - použiť systémové volanie select a čítať len z tej rúry, ktorá je pripravená.

36
Q

Práca s rúrami(pipes)

Ako pracuje funkcia pipe()?

A

Pipe vytvori ruru a nasmeruje na nu deskriptory.
Tie deskriptory tam su aj pred tym pipe()-om, ale su volne. pipe() ich iba obsadi a nie vytvori. Pomocou close sa zas uvolnia, a je to tam kde to bolo pred tym.
Rura sa zrusi ked nikto nema otvoreny ani jeden koniec tejto rury. To znamena ked vsetci co ju mali niekedy otvorenu (napriklad parent a child po forku) uz zavolali close na oba konce rury (alebo uz proces skoncil - vtedy sa zatvaraju vsetky otvorene subory).

37
Q

Práca s rúrami(pipes)

Mam problemik so zadanim:
Ked zadam: pripravne_03c subor prog pricom prog neexistuje, tak potomok (ktory sa snazi spustit prog pomocou exec) vypise chybovu spravu a skonci. Ale rodic o tom nevie a pise si veselo do rury, ktoru ale nikto necita - vysledok je hlaska Broken pipe. Zistovat, ci prog existuje a ci sa da spustat nestaci, lebo problemom moze byt aj velkost pamate. Totizto po forku bezia uz 2 samostatne procesy a zislo by sa rodicovi nejako oznamit, ze potomok je v poriadku a ze sa moze zapisovat do rury, inak by mal rodic skoncit. Ako to spravit? Alebo ta hlaska nevadi?

A

Normalne sa to robi tak, ze proces, ktory do rury zapisuje, nastavi vlastnu reakciu na signal SIGPIPE, v ramci ktorej vykona prislusne opatrenia. Ina moznost je signal ignorovat - potom ale musite testovat navratovu hodnotu write. Signaly su vsak mimo rozsah cviceni OS.
V ramci cviceni OS tato hlaska nevadi.

38
Q

Prihlásení používatelia(/var/run/utmp)

Ako zistím počet práve prihlásených užívateľov ? V Linux-e to je who -q, ale to v Unixe nefunguje. Dá sa to jedným príkazom ?

A

Nuž tu sú 2 možnosti: 1. nasimulovať v programe spustenie who | wc -l (==> treba napísať veľa kódu) 2. priamo čítať obsah súboru utmp (man utmp) (==> rýchle, elegantné, odporúčané)

39
Q

Prihlásení používatelia(/var/run/utmp)

Donieslo sa mi do uší niečo o /var/run/utmp, ale z manuálu som nepochopil, ako z daného súboru dostanem nejaké informácie.

A

Súbor je obrazom informácii o užívateľoch prihlásených v systéme. Musíte postupne čítať položky súboru utmp (sú definované v utmp.h) a keď sa dostanete na koniec súboru, zistíte, koľko položiek ste prečítali a toľko je aj prihlásených používateľov. V súbore nie je priamo uvedené, koľko užívateľov je prihlásených.

40
Q

Prihlásení používatelia(/var/run/utmp)

Definoval som štruktúru: struct utmp muser; Pri čítaní zo súboru utmp: fread(&muser,sizeof(muser),1,infofile); prekladač vypíše chybu, že nepozná veľkosť štruktúry muser.

A

Chyba môže byt v tom, že ste neinkludovali súbor utmp.h a teda prekladač nepozná štruktúru utmp a tým pádom nevie akú ma muser veľkosť. Nezabudnite inkludovať aj súbor /sys/types.h, inak vám prekladač vypíše “Parse error”. (utmp.h potrebuje mať najskôr inkludovaný /sys/types.h)

41
Q

Prihlásení používatelia(/var/run/utmp)

Existuje na FreeBSD nejaká obdoba Linuxových príkazov pre prácu so súborom ‘utmp’ (ako sú napríklad setutent() alebo getutent() )

A

Pokiaľ viem, tak neexistuje.

42
Q

Prihlásení používatelia(/var/run/utmp)

Je obmedzeny pocet prihlasenych uzivatelov na server?

A

Ak myslite na osu, tak tam je pocet prihlasenych obmedzeny poctom pseudo terminalov a to je 192.

43
Q

Procesy a fork.

Pokial to dobre chapem tak ked fork rozdvoji proces tak pre decko spravy novy datovy priestor a zasobnik ale kod maju spolocny. Ak spustime exec v childe tak by mal nahradit jeho kod s datami, teda jeho celkovy adresny priestor s novym programom, ale predsa kod maju spolocny(child a parent) a teda ho nemoze nahradit, co teda spravi, alokuje uplne novy adresny priestor a tam ho pusti a childa kompletne dealokuje? Ak je to tak, tak je z hladiska vyuzitia pamete lepsie ak sa najprv forkneme, potom v childe spustime dany program a parenta ukoncime, moze sa to zist ak nas program zabera viac pamate ako ten execnuty lebo pren sa alokuje iba tolko co potrebuje….

A

Pri volani exec sa najprv uvolnia vsetky regiony procesu (teda kod, data aj zasobnik) a potom sa vytvoria nove a nainicializuju sa podla obsahu spustaneho programu.

44
Q

Procesy a fork.

Kedy sa fork() moze pokazit (vratit -1)?
Mam fork v cykle,par krat to zbehne bez problemov a potom zrazu vrati -1… v com moze byt problem?

A

Skuste man fork a v casti ERRORS najdete popis situacii, v ktorych fork zlyha. Mimochodom v externej premennej errno najdete kod chyby.
Napr. obmedzeny pocet beziacich procesov. Na OSE ma kazdy pouzivatel len obmedzeny pocet spustenych procesov.
Systemove limity su taketo (sysctl kern.maxproc kern.maxprocperuid):
kern.maxproc: 2068
kern.maxprocperuid: 2067
Okrem toho existuju limity na vyuzivanie roznych prostriedkov v systeme nastavitelne individualne na urovni skupin (resp. tried) pouzivatelov.
Konkretne to zistite prikazom limits.
Pre bezneho pouzivatela na ose je to:
maxprocesses 32

45
Q

Procesy a fork.

Ak chcem spustit 2 procesy, ktore spolu komunikuju rurou, tak musim z rodicovskeho “vyklonovat” decko, pricom, ak som to spravne pochopil, tak to decko zdedi po rodicovi cely kod. To znamena, ze rodic bude mat po forknuti aj nepotrebny kod decka a decko bude mat zase navyse kod rodica. Nie je to neefektivne?

A

Je to tak. Akurat presnejsie by bolo povedat, ze adresny priestor potomka je kopiou adresneho priestoru rodica. Z hladiska operacneho systemu to urcite nie je neefektivne. Pri fork-u sa kopiruju len data a zasobnik, kod zostava spolocny. Existuje aj volanie vfork (v BSD, v Linux-e takto funguje priamo fork), ktore odlozi kopirovanie adresneho priestoru az do casu keby to bolo potrebne (teda az ked dojde k zapisu do adresneho priestoru). V pripade, ze robite vfork a potom exec, nic sa nekopiruje. A samozrejme existuju aj thready, ktore adresny priestor zdielaju.

46
Q

Procesy a fork.

Moze proces potomka pristupovat k pamati rodicovskeho procesu alebo nie?

A

Samozrejme ze nie. V Unixe maju procesy oddelene adresne priestory.

47
Q

Procesy a fork.

Mam takuto otazku: viem ze pri forknuti procesu sa “skopiruju” hodnoty vsetkych premennych do identickeho detskeho procesu, vyskusal som urobit fork procesu ktory pouzival pointer (dirent*) a potom som z child-processu tento pointer pouzil a fungoval. Vnutorne som ocakaval ze to nepojde, teda ze nebudem moct pristupovat k pameti ktoru vlastni rodic, no teraz vlastne neviem, ci si to pametove miesto neskopiroval tiez.

A

Systemove volanie urobi uplnu kopiu celeho adresneho priestoru rodica ako aj ostatnych informacii o procese. Jedine, cim sa potom a rodic lisia je ich pid, ppid a nejake pocitadla.
Preto bol pointer samozrejme rovnaky, ale ukazoval do vlastneho adresneho priestoru.

48
Q

Procesy a fork.

Mam takyto program:

Normalne ho skompilujem cez cc, a potom to zacne:
ak ho spustim: ./program.o
vypise:
Ahoj Ja som 0 Ja som 1 Ja som 2 Ja som 9 Ja som 8 Ja som 7 Ja som 6 Ja som 5 Ja som 4 Ja som 3 Cau
ale ak ho spustim
./program.o | more
alebo presmerujem stdout do suboru
tak vypise:
Ahoj Ja som 0 Ahoj Ja som 1 Ahoj Ja som 2 Ahoj Ja som 9 Ahoj Ja som 8 Ahoj Ja som 7 Ahoj Ja som 6 Ahoj Ja som 5 Ahoj Ja som 4 Ahoj Ja som 3 Ahoj Cau
Preco sa to deje?

A

Je to sposobene tym, ako pracuju kniznicne funkcie printf.
Vsetky kniznicne funkcie na pracu so subormi (funkcie vacsinou zacinaju na f) maju bufferovany vystup, to znamena, ze vystup sa vypise az ked je to nevyhnutne potrebne. Ked je vystupnym suborom terminal, vystup je bufferovany po riadkoch (teda k skutocnemu vypisaniu pride az po vypisani znaku ‘\n’). Ked je vystupnym suborom subor alebo rura, vystup je bufferovany po blokoch (napr. velkosti 1024 znakov) a k skutocnemu zapisaniu pride az po naplneni buffera, uzavreti vystupu (fclose) alebo po zavolani funkcie fflush().
No a tu je pricina rozneho vystupu. Po systemovom volani fork dostanete uplnu kopiu rodicovskeho procesu (samozrejme aj so stavom kniznicnych volani a teda aj bufferov). No a kedze v prvom pripade je vystup bufferovany po riadkoch (vystup je na terminal), k vypisaniu “Ahoj” pride este v rodicovkom procese. V druhom pripade je vystup bufferovany po blokoch (vystup je do rury) a k vypisaniu “Ahoj” a dalsich veci, ktore za nazbierali v bufferi (ktory bol pri fork-u skopirovany do potomka) pride az po skonceni potomka - ked sa urobi implicitne close (pripadne skor, ked by ste toho vypisovali vela).
Riesenie spociva bud v nastaveni bufferovania vystupu na riadkovy alebo ziadny (kniznicna funkcia setbuf) alebo zavolani kniznicnej funkcie fflush() na vhodnych miestach. Mimochodom, v zadaniach mate pouzivat volania jadra (t.j. write, read), u ktorych tento problem nenastane, pretoze napr. systemove volanie write Vam vrati riadenie az ked su pozadovane udaje naozaj zapisane. Ked ale potrebujete formatovany vystup z viacerych procesov (rodica a potomka) naraz, mozete to urobit kombinaciou sprintf a write (alebo uz spominany fflush). To co potrebujete je vlastne atomicky synchronny write - inak budete mat problemy s premiesavanim vystupu z roznych procesov, pripadne ine (napr. ako ten co ste prave spomenuli). Vitajte vo svete paralelneho programovania :)

49
Q

Ostatné otázky

Ako prevediem reťazec predstavujúci číslo na číslo?

A

Pozrite sa na funkcie: atoi, atol, strtol

50
Q

Ostatné otázky

Vo väčšine manuálov sa píše o chybovej premennej (nazvanej “errno”) a jej nastavovaní podľa chybových hlášok jednotlivých funkcii. Je táto premenná všeobecne daná v každom C-čkovskom programe, alebo ju treba osobitne definovať ?

A

V C-čkovskom programe vidíte len tie premenné, ktoré si definujete. Teda aj keď chcete používať premennú errno, musíte ju definovať, resp. oznámiť prekladaču, že ide o externú premennú definovanú v knižnici. napr. extern int errno; Bližšie informácie: man errno

51
Q

Ostatné otázky

  • Je možné používať na zápis na stdout, stderr inštancie tried cout (a cin na čítanie stdin), keď použijem prekladač g++ ?
  • Prečo v C pod Linux(unix) nemožno premenné deklarovať hocikde v tele procedúry, ale len na jej začiatku ?
A

Toto robiť nemôžete, pretože máte programovať v jazyku C a nie v jazyku C++.

52
Q

Ostatné otázky

Dá sa nejako rýchlejšie získať aktuálny čas a dátum ako spustením programu date ?

A

Skúste sa pozrieť na funkcie: time, gettimeofday, ctime, …

53
Q

Ostatné otázky

Keď spustím môj program v C-čku, systém mi vypisuje hlášku “Segmentation fault”. Čo to znamená ?

A

Chyba “Segmentation fault” znamená, že program pristúpil do pamäte, ktorá mu nepatrí, a preto bol operačným systémom ukončený. Skontrolujte si indexy do polí; či máte naplnené pointre; či pristupujete pomocou pointrov ku zmysluplným údajom, atď. Často táto chyba nastane úplne jednoducho: char ch; scanf(”%c”,ch); // ale malo tu byt: scanf(”%c”,&ch);

54
Q

Ostatné otázky

Mam problém: podľa zadania mám spraviť program, ktorého jeden argument ma byt štruktúrovaný, jeho zložky majú byť oddelené bodkočiarkami, takže program sa ma používať takto: >./zadanie jano;juro;jozo Keď tam tie bodkočiarky dám, ako shell bude vedieť že to všetko sú argumenty toho jedného programu a nie tri samostatné programy ?

A

Už by ste mali zo C-shellu vedieť, ako shellu povedať, že ; je obyčajný znak bez špeciálneho významu. (napr. >./zadanie jano\;juro\;jozo) Záleží predsa na používateľovi, aby vedel program správne použiť.

55
Q

Ostatné otázky

Ako sa dá debuggovať program v C?

A

V Unix-e mate k dispozícii debugger gdb. Je to síce riadkový, ale zato veľmi silný nastroj. Pokiaľ chcete zistiť, kde Vám spadol program (core dumped), skúste napr.: gdb program program.core a potom príkaz where. gdb Vám vypíše presne miesto, kde nastala chyba. Pred spúšťaním Vám ešte odporúčam skompilovať program s prepínačom -g (cc -g program.c -o program), aby boli v programe prítomné debuggovacie informácie.

56
Q

Ostatné otázky

Treba ošetrovať korektné prebehnutie aj takých funkcií, ako dup, close, … (printf :-) )? Pri pipe, open, fork, … je mi jasná potreba kontroly.

A

Mali by ste testovať návratovú hodnotu tých funkcii, ktorých výstup neskôr používate (close nie, dup áno, …).

57
Q

Ostatné otázky

strtol(“0s”,(char**)NULL,10) vráti 0, errno nenastaví. Ako zistím či došlo k chybe, alebo sa konvertoval reťazec “0” ?

A

Keď si pozriete man na strtol a konkrétne popis parametra endptr (teda druhého parametra, ktorý ste Vy nastavili na NULL), zistíte, že do zadanej premennej funkcia vloží pointer na prvý chybný znak a teda stačí potom otestovať, či prešiel celý reťazec …

Treba si však dať pozor, lebo ak v reťazci nptr neboli žiadne číslice, tak v *endptr bude originálna hodnota nptr. Teda, napríklad: ak po vykonaní strtol() *nptr nie je ‘\0’, ale **endptr je ‘\0’, tak je reťazec v poriadku.

Nespravíte zle, ak si pre seba spravíte pár príkladíkov, skúste túto funkciu zavolať s rôznymi jednoduchými parametrami.

58
Q

Ostatné otázky

V súbore syslimits.h sú rôzne limitné konštanty. Je v týchto limitoch zahrnutý aj ukončovací znak ? (teda, ak napr. PATH_MAX je 1024, potom cesta môže byt max. 1023 znakov + ‘\0’) ?

A

Presnejšie ide o súbor /usr/include/limits.h, ktorého použitie je portabilné, pretože súbor /usr/include/sys/syslimits.h je len vo FreeBSD a je z limits.h includovaný.

V limitoch JE zahrnutý aj ukončovací znak – napr. vami spomenutá cesta môže byť iba 1023 znakov.

59
Q

Ostatné otázky

Je potrebne osetrovat argumenty tym sposobom ze ked ma napriklad zadat meno suboru a popripade nejaky pocet (integer napr.) tak ci treba kontrolovat ze to cislo je cislo a meno suboru je string (aj ked v linuxe je v mene mozne takmer vsetko) a pod.?

A

Funkcia main dostane svoje argumenty ako pole ukazovatelov na retazce. Teda vsetky argumenty su vlastne stringy. Pokial ocakavate cislo, musite si ho samozrejme nasledne skonvertovat a tak aj zistite, ci to cislo naozaj je cislom a mozete pripadne oznamit chybu.

Meno suboru nemusite osetrovat, jedine co je zaujimave je ze ci uz existuje, teda ak neexistuje subor s danym menom a chcete z neho citat, tak vypisete chybu a ukoncite program, co sa tyka toho cisla, tak to by asi malo byt osetrene…

60
Q

Ostatné otázky

Program za ulohu skopirovat headerfile a stand. vstup na stand. vystup.
Ked sa spusta bez parametra prog tak mi to v poriadku vypise headerfile a potom ten std. vstup bere ako: to co napisem a potvrdim ENTERom echuje na obrazovku (ukoncim to vzdy CTRL+C) je to to co to ma robit?
nevadi ked som pouzil taku malu finticku miesto ziadneho programu spustil cat, ktory urobil to co sa malo bez programu ?

A

V zadani je/bude uvedene:
Program nesmie spustat ziadne externe programy okrem tych, ktore su v zadani uvedene.
To co posielas na terminal za headerfile (cize standardny vstup programu) je tiez svojim sposobom subor, ktory musi mat zakoncenie (CTRL-D). Ak program robi to co ma, po spusteni:
ls | ./zadanie3 headerfile > vysl.out
vo vysl.out budes mat headerfile a vypis ls hned za tym

61
Q

Ostatné otázky

Zadanie: napiste program, ktory spusti program zadany parametrom prog (bez argumentov), pricom na jeho standardny vstup posle obsah suboru headerfile a potom svoj standardny vstup.

ako sa ma program spravat v pripade, ze medostane svoj standardny vstup? ma nan zostat cakat? a v pripade ze nema zostat cakat,tak ako sa to da spravit?(ako sa da zistit ci je standardny vstup alebo nie?)

A

V Unix-e ma kazdy program definovany standarny vstup (teda deskriptor 0). To, na co tento deskriptor ukazuje, urcuje (moze urcit, zmenit) rodic procesu. Specialny pripad predstavuje situacia, ked rodic svojmu potomkovi stadardny vstup uzavrie pred tym, nez spusti pozadovany program. V tom pripade vsak prva operacia read/write v spustenom procese zlyha s chybou a proces by mal korektne skoncit (ak chyby testuje). Kedze Vy mate len spustit zadany program, nemusite sa starat o to, ako on pracuje so standardnym vstupom. A co sa tyka Vasho programu, tak v nom staci citat vstup kym read vracia korektne hodnoty (teda navratova hodnota read je > 0).

62
Q

Ostatné otázky

Da sa v gdb nejakou fintou docielit ci ma traceovat child-process alebo parent-process? V redhate tracuje povodny proces a na ose to bol naopak child process.

A

(v povodnom zneni, bez titulkov)
On most systems, GDB has no special support for debugging programs which create additional processes using the fork function. When a program forks, GDB will continue to debug the parent process and the child process will run unimpeded. If you have set a breakpoint in any code which the child then executes, the child will get a SIGTRAP signal which (unless it catches the signal) will cause it to terminate.
However, if you want to debug the child process there is a workaround which isn’t too painful. Put a call to sleep in the code which the child process executes after the fork. It may be useful to sleep only if a certain environment variable is set, or a certain file exists, so that the delay need not occur when you don’t want to run GDB on the child. While the child is sleeping, use the ps program to get its process ID. Then tell GDB (a new invocation of GDB if you are also debugging the parent process) to attach to the child process (see section 4.7 Debugging an already-running process). From that point on you can debug the child process just like any other process which you attached to.