§
UNIX sistemsko programiranje

Lastnosti dokumenta

Naslov
UNIX sistemsko programiranje
Del
-
Datum vsebine
28. 08. 2007
Original
-
Vrsta
domača naloga
Jezik
slovenščina
Različica
1.0
Ustanova
Fakulteta za računalništvo in informatiko, Univerza v Ljubljani
Študij
Računalništvo in informatika, Logika in sistemi, 4. letnik
Predmet
Operacijska programska oprema
Mentor
prof. dr. Borut Robič
Avtor
Tine Lesjak
Ocena
-

Povzetki nekaterih poglavij iz knjige:
Haviland K., Gray D., Salama B. UNIX System Programming: A programmer's guide to software development, Second edition. Addison-Wesley. 1999.

Poglavje 2: Datoteka

Sistemski klici za delo z datotekami

open

Zagotovi dostop do navedene datoteke in vrne datotečni deskriptor. Načini dostopa:

  1. samo branje
  2. samo pisanje
  3. branje in pisanje
  4. ustvari
  5. ekskluzivno
  6. prireži
  7. dodaj
  8. odpri neblokirajoče

creat

Ustvari navedeno datoteko. Možno tudi s klicem open.

close

Sprosti dostop do datoteke. Ob koncu procesa, se vse odprte datoteke samodejno sprostijo. POSIX standard pravi, da lahko ima en proces največ 20 odprtih datotek naenkrat.

read

Prebere navedeno število bajtov v navedeno polje. Datotečni kazalec se premakne na naslednji neprebrani bajt. Vrne dejansko število prebranih bajtov.

write

Zapiše navedeno št. bajtov iz polja v datoteko in vrne število dejansko zapisanih bajtov.

lseek

Premakne datotečni kazalec za navedeni odmik (v bajtih) od:

  1. začetka datoteke
  2. konca datoteke
  3. trenutnega mesta kazalca

remove in unlink

Izbriše navedeno datoteko.

fcntl

Vrne ali nastavi status navedenega datotečnega deskriptorja.

stdin, stdout in stderr

Vsak proces samodejno dobi tri "datoteke": standardni vhod, izhod in "napako".
Vhod ponavadi predstavlja tipkovnica, izhod pa terminal.
Z ukazom < lahko vhod preusmerimo, z ukazom > pa preusmerimo izhod.
Na podoben način lahko uporabimo cevi |.
Standardno "napako" je potrebno posebej nastaviti.

Standardna V/I knjižnica

Nadgradnja sistemskih klicev, ki uniformira datotečni deskriptor in omogoča samodejno medpomnjenje.

Poglavje 3: Datoteka v kontekstu

Vsaka datoteka ima svojega lastnika. Lastnik je uporabnik (UID). Vsak uporabnik je član ene skupine (GID).
Uporabniki so zabeleželi v datoteki /etc/passwd, skupine v /etc/group.

Vsaka datoteka ima določena dovoljenja, kdo lahko dostopa do nje. To so lahko:

  1. lastnik datoteke
  2. vsak, ki pripada isti skupini kot lastnik datoteke
  3. vsi ostali

Poleg tega ima vsaka datoteka tudi dovoljenja, kaj lahko kdo počne z njo:

  1. bere
  2. piše
  3. poganja

Ta dovoljenja so predstavljene kot osmiška vrednost, npr. 0755. Uporabijo se pri klicih open, creat in chmod.

access

Vrne pravice dostopa do navedene datoteke:

chmod

Nastavi dovoljenja za navedeno datoteko.
Dovoljenja so podana v osmiški vrednosti, npr. 0755.

chown

Nastavi lastnika za navedeno datoteko.
Lastnik je podan kot UID in GID.

link

Ustvari trdo povezavo (hard link) do navedene datoteke.
Izgleda, kot da ima ena datoteka več imen. Vsaka datoteka ima zabeleženo število teh povezav.
Trda povezava je možna samo znotraj istega datotečnega sistema.

rename

Preimenuje in/ali premakne navedeno datoteko.

symlink

Ustvari bližnjico do datoteke (symbolic link, soft link). Bližnjica je dejansko posebne vrste datoteka in lahko kaže na neobstoječo datoteko. Bližnjica lahko kaže na datoteko v drugem datotečnem sistemu.

readlink

Enako kot read, le da ne bere bližnjico, temveč datoteko, na katero kaže.

stat in fstat

Vrne vse lastnosti navedene datoteke v strukturi:

Poglavje 4: Direktoriji, datotečni sistemi in posebne datoteke

Direktoriji

Direktoriji so zbirke datotek, ki so predstavljeni z drevesno strukturo.

Trenutni delovni direktorij je direktorij, v katerem se trenutno nahajamo (v terminalu ali procesu).

Direktorij je posebna datoteka, v katero ni mogoče pisati ali je narediti z open ali creat. Vsebina direktorija je seznam (trdih) povezav. Takšna povezava je predstavljena z inode številko in imenom datoteke ali poddirektorija. Direktorij sam sebe predstavlja z imenom ., direktorij nad seboj (parent) pa kot ...

Vsak direktorij ima, enako kot datoteke, dovoljenja, kaj se lahko počne z njim, s tem, da je kontekst malenkost drugačen:

Ta dovoljenja pa ne vplivajo direktno na datoteke/poddirektorije. Ti imajo še vedno svoja dovoljenja.

mkdir

Ustvari naveden direktorij in nastavi podana dovoljenja (npr. 0755).

rmdir

Izbriše naveden direktorij. Izbriše samo, če v njem ni datotek/poddirektorijev.

chdir

Nastavi trenutni delovni direktorij na navedenega.

opendir

Zagotovi dostop do navedenega direktorija na zelo podoben način kot open do datoteke. Vrne datotečni deskriptor direktorija.

closedir

Sprosti dostop do direktorija.

readdir

Vrne zapis direktorija in premakne kazalec za en zapis naprej. Deluje na zelo podoben način kot read za datoteke.

rewinddir

Vrne kazalec direktorija na prvi zapis.

getcwd

Vrne ime trenutnega delovnega direktorija.

ftw

Ta rutina se sprehodi po drevesni strukturi navedenega direktorija in za vsako datoteko/poddirektorij izvede specifično podano funkcijo.

Datotečni sistemi

Drevesna struktura direktorijev in datotek je združena v višjo enoto, datotečni sistem. Datotečni sistem se lahko priključi (mount) kateremukoli direktoriju v že obstoječem datotečnem sistemu. Lahko se tudi odklopi (unmount).

Datotečni sistem je zgrajen iz:

Super blok je naložen v pomnilniku.

sync

Sprazni vse medpomnilnike na disk.

fsync

Sprazni medpomnilnik navedene datoteke na disk.

Datoteke naprav

Datotečni sistem prebiva na diskovni particiji, ki je identificirana s posebno datoteko: datoteko naprave.

Datoteka naprave je posebna datoteka, ki predstavlja določeno V/I napravo.

Gonilniki za naprave so razdeljeni v dve kategoriji:

  1. bločni: diski, trakovi; dostop je posredno prek datotečnega sistema
  2. znakovni: linije, tiskalniki, terminali; neposreden dostop

Datotečni sistem lahko prebiva le na bločnih napravah.

statvfs in fstatvfs

Vrne lastnosti datotečnega sistema (iz super bloka):

Poglavje 5: Procesi

Proces je instanca programa v izvajanju. Poleg ukazov vsebuje tudi podatke (spremenljivke, informacije o registrih, kopicah). Isti program je lahko pognan večkrat, tako da ima več procesov.

Procesi so urejeni hierarhično, s korenskim procesom na čelu, init.
Vsak proces ima svoj ID (PID).

Sistemski klici za manipulacijo procesov

fork

Ustvari kopijo procesa, otroka, in nadaljuje izvajanje obeh istočasno od tod dalje.
Staršu vrne PID od otroka, otroku vrne 0.
Starš in otrok si delita datotečne deskriptorje.

exec

Prepiše trenutni proces tako, da naloži naveden program (datoteko) v pomnilnik in ga z navedenimi parametri požene od začetka. Prepisan proces ima isti PID.
Nov proces privzeto ohranja datotečne deskriptorje starega, v kolikor ni bila nastavljena posebna zastavica (fcntl), ki samodejno zapre vse odprte datoteke ob exec.

exit

Konča proces in vrne navedeni status staršu procesa. Vse datoteke se sprostijo.
Požene vse funkcije registrirane z atexit v obratnem vrstnem redu.

atexit

Rutina, ki registrira podano funkcijo, ki se pokliče pri exit.

wait

Začasno suspendira proces, dokler otrok teče. Ko otrok konča, se proces ponovno oživi. Če teče več otrokov, se proces oživi, ko prvi otrok konča. Vrne PID od končanega otroka. Ob vrnitvi vrne tudi naveden status otroka.

waitpid

Začasno suspendira proces, dokler otrok z navedenim PID-om teče. Ko ta otrok konča, se proces ponovno oživi. Vrne PID od končanega otroka. Ob vrnitvi vrne tudi naveden status otroka. Možno je podati tudi dodatne opcije. Ena izmed njih je, da je waitpid neblokirajoč.

Če otrok konča, preden starš pokliče wait/waitpid, postane zombi. Zombi je ustavljen proces, ki ne zaseda nobenih resursov, le kontrolni blok se ohranja v pomnilniku.

Če starš konča pred otrokom, se vsi njegovi otroci dodelijo korenskemu procesu, init.

Lastnosti procesa

PID: ID procesa

getpid

Vrne ID procesa.

getppid

Vrne ID starša procesa.

Skupina procesov

Vsak proces pripada eni skupini procesov. Procesi v isti skupini lahko med seboj bolje komunicirajo. Če je PID enak ID skupine, je ta proces vodja.

getpgrp

Vrne ID skupine procesa.

setpgrp

Prestavi naveden proces v navedeno skupino.

Seja skupin

Vsaka skupina procesov pripada eni seji.

getsid

Vrne ID seje navedenega procesa.

setsid

Prestavi proces v novo sejo, če ni vodja skupine. ID prestavljenega procesa bo enak ID-ju nove skupine in ID-ju nove seje. Takšen proces se imenuje demon.

Okolje procesa

Okolje procesa predstavljajo okoljske spremenljivke. Proces lahko te spremenljivke dobi prek dodatnega parametra main metode ali prek funkcije v standardni V/I knjižnici:

getenv

Vrne vrednost navedene okoljske spremenljivke.

putenv

Nastavi novo ali spremeni obstoječo navedeno okoljsko spremenljivko na podano vrednost.

Proces je povezan s trenutnim delovnim direktorijem. Vsak proces je povezan tudi s korenskim direktorijem.

chroot

Nastavi korenski direktorij procesa na navedenega.

Poglavje 6: Signali

Signali omogočajo preprost način prenašanja vnaprej definiranih programskih prekinitev na procese. Jedro sistema pošlje signal vsem procesom, ki so tako ali drugače povezani s tem tipom signala.
Proces lahko pošlje signal tudi drugemu procesu.

Signali so namenjeni za signaliziranje nenormalnih dogodkov.

Vsak proces lahko ob prejemu signala:

  1. nastavi, kako ga obravnava
  2. ga blokira
  3. pošlje signal drugemu procesu

Signali ne morejo nositi informacij direktno. Od njih lahko dobimo le njihovo ime.

Nekaj pogostih in pomembnih imen:

Pri nekaterih signalih normalen zaključek procesa sledi. Pri drugih signalih, nenormalen zaključek procesa sledi tako, da se odloži (dump) celotno stanje procesa v datoteko, ki jo je možno razhroščevati.

Proces lahko nastavi, kako obravnava prejeti signal z akcijo:

  1. naredi privzeto (normalen zaključek)
  2. ignoriraj
  3. izvedi točno določeno funkcijo

sigemtpyset

Nastavi podano zbirko signalov tako, da so vsi signali izpuščeni.

sigfillset

Nastavi podano zbirko signalov tako, da so vsi signali vsebovani.

sigaddset

Doda naveden signal v podano zbirko signalov.

sigdelset

Izbriše naveden signal iz podane zbirke signalov.

sigaction

Nastavi akcijo za naveden signal v podani zbirki.
V tretji parameter je možno shraniti trenutno akcijo signala, da jo lahko pozneje vrnemo.

Proces bo začel izvajati akcijo takoj, ko bo prejel signal. Po izvedbi te akcije se bo vrnil nadaljeval točno tam, kjer je bil signaliziran.

Signali se ne morejo uporabljati kot povsem zanesljivo metodo medprocesne komunikacije, saj proces po njegovem pošiljanju ne more zagotovo vedeti, kaj se je z njim zgodilo.

sigsetjmp

Zaznamuje lokacijo v programu.

siglongjmp

Skoči na zaznamovano lokacijo v programu.

sigprocmask

Blokira/deblokira prejemanje signalov v podani zbirki. Uporabno pri izvajanju kritične kode.

kill

Pošlje naveden signal navedenemu procesu (PID).

raise

Pošlje naveden signal samo sebi.

alarm

Nastavi časovnik na navedeno število sekund. Ko se časovnik izteče, proces prejme SIGALRM signal. Pri drugi uporabi klica se časovnik prepiše s prejšnjim.

pause

Suspendira proces. Takšen proces je možno prebuditi samo s signalom, za katerega smo nastavili ustrezno akcijo.

Poglavje 7: Cevi

Delovanje cevi (pipe) je zelo podobno branju/pisanju navidezne začasne datoteke. Cevi se ponavadi uporabljajo za enosmerno komunikacijo. En proces piše vanjo, drugi bere iz nje. Cev hrani podatke na FIFO način. Iz cevi je mogoče prebrati le zadnji podatek (lseek ne deluje).

pipe

Vrne dva datotečna (cevna) deskriptorja, enega za pisanje v cev, drugega za branje iz cevi.

Cevi se navadno uporabljajo za komunikacijo med staršem in otrokom. Običajno je, da starš ali otrok zapre tisto stran cevi, ki jo ne bo več potreboval.

Cev je velikostno omejena. Če proces, ki piše vanjo, naleti na polno cev, se suspendira, dokler se iz cevi ne prebere dovolj podatkov. Če proces, ki bere iz cevi, naleti na prazno cev, se tudi suspendira, dokler proces, ki vanjo piše, ne zapiše dovolj podatkov.

Če proces, ki ima pisalni dostop do cevi, le-tega zapre, se bralni proces prebudi oz. ne prebere nič podatkov. Če proces, ki bere iz cevi, bralni dostop zapre, pisalni proces dobi SIGPIPE signal in se konča (če nima definirane lastne akcije za ta signal).

Neblokirajoče branje in pisanje lahko izvedemo s fcntl tako, da nastavimo posebno zastavico na datotečni deskriptor.

select

Omogoča izbiro cevi, če proces bere iz več cevi (strežnik). Nastavi se, katere cevi so pomembne in koliko časa čaka (timeout).

Cevi se lahko uporabljajo samo med procesi, ki so med seboj sorodni (starši-otroci).

FIFO

"FIFO" ali "imenovane cevi" so izboljšava navadnih cevi tako, da je FIFO dejansko viden kot datoteka z imenom v datotečnem sistemu.
FIFO ustvarimo z ukazom mknod.
FIFO ima enake lastnosti kot prava datoteka (dovoljenja, lastnika, velikost).

mkfifo

Ustvari FIFO z navedenim imenom in dovoljenji (kot creat) in vrne datotečni (FIFO) deskriptor.

Če proces odpre blokirajoči FIFO za pisanje (open), se proces ustavi, dokler ga drug proces ne odpre za branje. Če proces odpre blokirajoči FIFO samo za branje, se proces ustavi, dokler ga drug proces ne odpre za pisanje. Če proces odpre blokirajoči FIFO za branje in pisanje, se proces ustavi, dokler ni podatkov.

Poglavje 8: Napredne medprocesne komunikacije

Zaklepanje

Z "zaklepanjem zapisov" (record locking) lahko proces zaklene določen del datoteke. To lahko stori s klicem fcntl tako, da navede datotečni deskriptor, vrsto zahteve in informacije o delu datoteke.
Vrste zahteve so:

  1. vrni opis ključavnice
  2. nastavi ključavnico
  3. počakaj, da se ta del datoteke odklene, nato nastavi ključavnico

Informacije o delu datoteke so:

Če se proces konča, sistem samodejno odstrani vse njegove ključavnice.

Ključavnice se ne podedujejo otrokom pri klicu fork.

Vsi procesi morajo sodelovati pri zaklepanju; ključavnica ne vpliva na read ali write klice.

Klic fcntl je sposoben preprečiti nastanek mrtve zanke (deadlock) pri zaklepanju samo med dvema procesoma. Kompleksnejše aplikacije lahko to rešujejo s časovnikom (timeout).

IPC

IPC je del sistema, ki skrbi za sinhronizacijo in komunikacijo med procesi.

Najpomembnejši del medprocesne komunikacije (IPC) je ključ. Ključ je ID IPC objekta. Ključi se uporabljajo za ustvarjanje ali za pridobitev dostopa do IPC objekta. Ko se IPC objekt ustvari, se ustvari tudi IPC statusna struktura, ki vsebuje:

Pošiljanje sporočil

Sporočilo je struktura:

Pošiljajo se preko sporočilne vrste (IPC objekt).

msgget

Zagotovi dostop do sporočilne vrste (podobno kot open ali creat). Podamo IPC ključ in dovoljenja. Če vrsta ne obstaja, jo ustvari. Vrne ID sporočilne vrste.

msgsnd

Doda podano sporočilo v navedeno sporočilno vrsto.
Če ni postavljene zastavice IPC_NOWAIT in je sporočilna vrsta premajhna, klic čaka, da se vrsta sprosti.

msgrcv

Vzame sporočilo določenega tipa iz navedene sporočilne vrste, in ga vrne v strukturi.
Če ni postavljene zastavice IPC_NOWAIT in sporočila ni, klic čaka na sporočilo.

msgctl

Klic se uporablja za tri namene:

  1. vrne stanje sporočilne vrste
  2. nastavi stanje sporočilne vrste
  3. izbriše sporočilno vrsto

Semaforji

Semaforje (semaphore) lahko uporabljamo za sinhronizacijo procesov v primeru kritične sekcije tako, da ima lahko samo en proces dostop do tega dela programa (mutual exclusion).
Semaforji so predstavljeni v množici semaforjev (IPC objekt).

semget

Zagotovi dostop do množice semaforjev (podobno kot msgget). Če množica ne obstaja, jo ustvari. Podamo IPC ključ, število semaforjev in dovoljenja. Vrne ID množice.

semctl

Klic se uporablja za nastavljenje semaforjev:

  1. vrne IPC stanje
  2. nastavi IPC stanje
  3. izbriše množico semaforjev
  4. vrne stanje semaforja v množici (vrednost semaforja ...)
  5. nastavi stanje semaforja v množici (vrednost semaforja ...)
  6. vrne vse semaforje iz množice
  7. nastavi vse semaforje iz množice

semop

Nastavi novo vrednost semaforja v navedeni množici. Semafor je podan kot:

Skupen pomnilnik

Skupen pomnilnik (shared memory) omogoča enemu ali več procesov, da si med seboj delijo pomnilnik. Del pomnilnika, ki je skupen, je IPC objekt.

shmget

Zagotovi dostop do skupnega pomnilnika {podobno kot msgget ali semget). Če skupen pomnilnik ne obstaja, ga ustvari. Podamo IPC ključ in velikost pomnilnika. Vrne ID skupnega pomnilnika.

shmat

Doda naveden skupni pomnilnik v logični naslovni prostor procesa in vrne kazalec nanj.

shmdt

Odstrani naveden skupni pomnilnik iz logičnega naslovnega prostora procesa.

shmctl

Enako kot msgctl se uporablja za:

  1. branje stanja skupnega pomnilnika (IPC objekta)
  2. nastavi stanje skupnega pomnilnika (npr. odstrani)
  3. odstrani skupni pomnilnik (IPC objekt)

Skupni pomnilnik (IPC objekt) se podeduje otroku.

Poglavje 10: Vtičnice

Vtičnice (sockets) predstavljajo dvosmerne komunikacijske končne točke strežnik/odjemalec v omrežnem sistemu.

Za komunikacijo so potrebna pravila, protokoli. Glede na vrsto povezave ločimo dva protokola:

  1. TCP - povezavno orientiran model (connection oriented model)
  2. UDP - brezpovezavno orientiran model (connectionless oriented model)

UNIX uporablja drugačen način pomnjenja IP naslovov. Za pretvorbo iz standardnega IP naslova (x.y.z.w) v UNIX format, lahko uporabimo rutino inet_addr.
Za uporabo lokalnih naslovov, uporabimo konstanto INADDR_ANY.

Ločimo dve vrsti vmesnika vtičnice:

  1. za medprocesno komunikacijo na istem sistemu (lokalno)
  2. za omrežno komunikacijo

socket

Ustvari vtičnico za podani tip vmesnika (lokalno, omrežno) in navedeno vrsto protokola (TCP, UDP). Vrne datotečni deskriptor vtičnice.

bind

Poveže naveden omrežni naslov (in vrata) z vtičnico in s sistemom.

listen

Strežnik začne poslušati morebitne vhodne povezave na navedeni vtičnici. Podamo tudi največje število vhodnih povezav.

accept

Strežnik čaka na vhodne povezave na navedeni vtičnici. Ko se povezava vzpostavi, ustvari novo vtičnico, s katero zasebno komunicira s priključenim odjemalcem.

connect

Odjemalec vzpostavi povezavo s strežnikom na navedeni vtičnici. Podamo tudi omrežni naslov in vrata strežnika.

recv

Prebere podatke iz navedene vtičnice (kot read) glede na zastavice:

  1. samo poglej podatke, ne sprejmi jih
  2. čakaj samo na OOB signal, ostale podatke spusti
  3. počakaj na vse podatke

Če klic vrne 0, pomeni, da je povezava končana.

send

Pošlje podatke na navedeno vtičnico (kot write) glede na zastavici:

  1. pošlji OOB signal
  2. pošlji podatek

Če je povezava prekinjena, se sproži SIGPIPE signal.

Vtičnice je potrebno po uporabi zapreti (close). Pri uporabi TCP protokola, se bodo podatki prenesli do konca, pri uporabi UDP protokola, se bo vtičnica zaprla takoj.

Pri brezpovezavno orientiranem modelu, mora tudi odjemalec biti povezan s sistemom, da lahko sprejme morebitne podatke (bind). Strežniku ni potrebno poslušati (listen) in ustvarjati novih vtičnic (accept).

recvfrom

Prebere podatke iz navedene vtičnice (kot recv) in dobi informacije o pošiljatelju.
Samo za brezpovezavno orientirani model.

sendto

Pošlje podatke na navedeno vtičnico (kot send) in poda tudi informacije o želenem odjemalcu.
Samo za brezpovezavno orientirani model.