65
Aleksandar Popovi} OSNOVI UNIX-A - skripta za ve`be iz predmeta Operativni sistemi - Novi Sad, 1998.

UNIX Osnovne Komande2

Embed Size (px)

Citation preview

Page 1: UNIX Osnovne Komande2

Aleksandar Popovi}

OSNOVI UNIX-A

- skripta za ve`be iz predmeta Operativni sistemi -

Novi Sad, 1998.

Page 2: UNIX Osnovne Komande2

0. UVODNA RE^ Ova skripta predstavqa gradivo koje se predaje na ve`bama iz

predmeta Operativni sistemi u drugom semestru. Podrazumeva se da su ~itaoci ovog teksta odslu{ali teorijski deo gradiva o operativnom sistemu UNIX, te da su upoznati sa wegovim osnovnim konceptima.

Skripta je podeqena u tri poglavqa. U prvom poglavqu predstavqene su osnovne komande operativnog sistema UNIX. Svaka od wih je ilustrovana sa nekoliko primera. U nastavku je predstavqen i jedan editor za Linux, tzv. Joe, kao i osnovne komande za rad sa wim.

U drugom poglavqu opisan je jedan prevodilac programskog jezika Module 2 za operativni sistem Linux - Mocka Modula 2. Data su osnovna uputstva za rad sa prevodiocem, kao i zaglavqa najva`nijih bibliote~nih modula.

Tre}e poglavqe, koje je najobimnije, opisuje sistemske pozive operativnog sistema UNIX. Opisani su sistemski pozivi za rad sa procesima, za upravqawe signalima, za evidencije i za{tite, za rad sa fajlovima i direktorijumima, za rad sa terminalima, i za me|uprocesnu komunikaciju. Da bi materija bila {to jasnije izlo`ena, obja{weni su i neki osnovni koncepti UNIX-a.

Ve}ina sistemskih poziva ilustrovani su primerima. Sve programe napisali su Sa{a Popravak, student informatike i autor. Svi programi napisani su za prevodilac Mocka Modula 2, na kojem su i testirani.

Iako je ova skripta namewena prvenstveno studentima informatike, autor se nada da }e korisno poslu`iti i onima koji `ele da se upoznaju samo sa osnovnim komandama UNIX-a.

Autor

Page 3: UNIX Osnovne Komande2

1.Osnovi kori{}ewa UNIX-a 3

1. OSNOVI KORI[]EWA UNIX-A

Kada se ra~unar ukqu~i, i kada se kernel u~ita u memoriju, prvo se pojavi prompt: ime_racunara login: gde ime_racunara zavisi od ma{ine na kojoj se radi. Tada je potrebno uneti ime korisnika. Nakon toga, pojavi se prompt: Password: Tada je potrebno ukucati lozinku. Obratiti pa`wu na velika i mala slova, po{to UNIX pravi razliku izme|u velikih i malih slova. Ukoliko nismo dobro otkucali {ifru, dobijemo prompt: Login incorrect. ime_racunara login: pa je potrebno ponoviti postupak. Nakon toga, prijavili smo se na sistem, i nalazimo se u direktorijumu /home/ime_korisnika/, koji je na{ korenski i polazni direktorijum. U direktorijumskoj hijerarhiji iznad wega postoji jo{ direktorijuma, ali mi wima nemamo direktan pristup. U na{em direktorijumu mo`emo da radimo {ta god ho}emo: da bri{emo fajlove, da ih kreiramo, da kreiramo nove direktorijume, da bri{emo postoje}e, itd. Ra~unar NIKADA ne treba gasiti, ali ako je to ve} neophodno,ne sme se odmah pritisnuti dugme za iskqu~ivawe, ve} je potrebno prvo resetovati ra~unar sa Ctrl+Alt+Del, i tek kada UNIX obavi ga{ewe svih sistemskih procesa, i kada dobijemo poruku: Rebooting. smemo da iskqu~imo ra~unar.

Page 4: UNIX Osnovne Komande2

1.Osnovi kori{}ewa UNIX-a 4

1.1.OSNOVNE NAREDBE UNIX-A

U ovom poglavqu bi}e predstavqene osnovne komande UNIX-a. Svaka komanda }e biti predstavqena tako {to }e se prvo navesti weno ime, zatim sintaksa, a iza toga i detaqniji opis opcija, kao i primeri. Pre nego {to pre|emo na opise komandi UNIX-a, nave{}emo jo{ jednu tehniku koja se ~esto koristi. To je preusmeravawe standardnog ulaza/izlaza. Ako `elimo da komanda komanda ispisuje svoj rezultat u fajl fajl, a ne na ekran, pisa}emo: komanda > fajl Ovom komandom }emo izgubiti podatke koji su pre toga bili u fajlu fajl. Ako fajl ne postoji, on }e ovom komandom biti kreiran. Ako `elimo da podatke pi{emo na kraj fajla fajl, pisa}emo: komanda >> fajl Ako, pak, `elimo da komanda komanda ~ita podatke iz fajla fajl, a ne sa tastature, pisa}emo: komanda < fajl I kona~no, ako `elimo da rezultat komande komanda1 prosledimo nekoj drugoj komandi komanda2, pisa}emo: komanda1 | komanda2 Ovim smo dve komande povezali u tzv. cev, ili pajp (engl. pipe). ------------------------------------------------- MAN man [-k] [section] title Komanda man predstavqa najbr`i na~in da se do|e do odre|enih obja{wewa vezanih za UNIX operativni sistem. Skoro cela UNIX dokumentacija je sme{tena na disk. Ovom komandom se uputsvo za navedeni naslov izdvaja iz man baze i prikazuje na ekranu. Argument title mo`e biti ime komande, ime specijalnog fajla, ili sistemskog poziva. UNIX dokumentacija je podeqena u vi{e sekcija, kako je prikazano u slede}oj tabeli. Mo`e se desiti da jedan entitet postoji u vi{e sekcija. Na primer, postoji komanda write ali i sistemski poziv pod istim imenom. U ovakvim slu~ajevima, do

Page 5: UNIX Osnovne Komande2

1.Osnovi kori{}ewa UNIX-a 5

`eqenog obja{wewa se dolazi eksplicitnim zadavawem rednog broja sekcije u pozivu man komande. man sa opcijom -k vr{i pretra`ivawe kompletne baze (ili sekcije, ako je zadata) po kqu~noj re~i title.

Sekcija opis -------------------------------------------------------------------- 1 Commands 6 Demos and Games 2 System Calls 3 Subroutines 4 File Formats 5 Miscellaneous 7 Special Files 1M Maintenance primeri: % man ls Reformatting entry. Wait ... % man 2 write Reformatting entry. Wait ... % man -k slip Poruka Reformatting entry. Wait... se javqa samo kada prvi put pozivamo man za neku komandu. man ispisuje tekst na sli~an na~in kao {to }e komande biti opisane u ovoj skripti. Kada se stisne strelica gore ili dole, i tekst se pomera za jedan red u `eqenom pravcu. Ako se stisne <Space>, tekst se pomera za jedan ekran nadole. Ako se stisne <Enter>, tekst se pomera za jedan red nadole. U komandni prompt se izlazi pritiskom na q. ---------------------------------------------------- CD cd [direktorijum] Promena teku}eg (radnog) direktorijuma. Komanda kojom se omogu}ava kretawe po stablu fajl sistema. primeri: % cd dir4 -teku}i direktorijum je dir4 % cd .. -vra}awe na prethodni, roditeqski direktorijum % cd -vra}awe na polazni (HOME) direktorijum

% cd ../dir2/dir3 -relativno kretawe po stablu

Page 6: UNIX Osnovne Komande2

1.Osnovi kori{}ewa UNIX-a 6

% cd / -korenski direktorijum postaje teku}i % cd /users/tanja/dir2/dir3 -primer sa apsolutnim putem % cd - -vra}awe na direktorijum koji je bio teku}i pre

zadwe cd komande ---------------------------------------------------- LS ls [-alrRt] [name] Prikazuje sadr`aj direktorijuma name. Ukoliko direktorijum nije zadat, prikazuje se teku}i direktorijum. -a -prikazuje se celokupan sadr`aj direktorijuma ukqu~uju}i i skrivene fajlove (~ija imena po~iwu sa .) ; -l -prikazuje se sadr`aj direktorijuma u duga~kom formatu; -r -prikazuje fajlove u obrnutom redosledu; -R -rekurzivno prikazuje sadr`aje svih poddirektorijuma; -t -prikazuje fajlove po redosledu vremena posledwe izmene. U Linux-u, v je obi~no sinonim za ls -al, a koristi se i dir. primeri: % ls proba.c novi.c Makefile % ls -a .login .profile proba.c novi.c a.out* tmp/ % ls -l -r--r--r-- 1 root sys 1145 Oct 23 18:41 READ.ME -rw-rw-rw- 1 tanja user 85 Nov 7 14:47 boja.c -rwxrwxrwx 1 tanja user 1046 Nov 15 13:01 create Pored imena, duga~ki listing za svaki fajl ili direktorijum daje i slede}e informacije: tip fajla, pristupne dozvole, broj tvrdih linkova, vlasnika fajla, grupu kojoj fajl pripada, veli~inu u bajtovima, datum i vreme kreirawa, i na kraju, ime fajla. - obi~an fajl d direktorijum l link p pajp, odnosno FIFO c znakovni fajl b blokovski fajl

Page 7: UNIX Osnovne Komande2

1.Osnovi kori{}ewa UNIX-a 7

primer: % ls -l dr--r--r-- 1 root sys 1145 Oct 23 18:41 /dir1 lrw-rw-rw- 1 tanja user 85 Nov 7 14:47 tetris prwxrwxrwx 1 tanja user 1046 Nov 15 13:01 wr ---------------------------------------------------- MKDIR mkdir dirname Kreira direktorijum sa imenom dirname gde ime mo`e da bude zadato kao apsolutni ili relativni put. primer: % mkdir /usr/people/tanja/newdir ---------------------------------------------------- RMDIR rmdir dirname Bri{e prazan direktorijum sa imenom dirname. primer: % cd /usr/people/tanja % rmdir newdir ---------------------------------------------------- PWD pwd Komanda pwd ispisuje apsolutni put radnog, to jest teku}eg direktorijuma. primer: % pwd

Page 8: UNIX Osnovne Komande2

1.Osnovi kori{}ewa UNIX-a 8

/home/srle ---------------------------------------------------- CAT cat file1 file2 ... cat ~ita sadr`aj fajlova file1, file2, ... i ispisuje ih redom (sastavqene) na standardni izlaz. primeri: % cat proba Ovo je probni fajl za demonstraciju komande CAT I linija II III Kraj % cat file1 file2 > file3 [tampa se sadr`aj fajlova file1 i file2, umesto na standardni izlaz (zbog redirekcije) u tre}i fajl file3. Ova komanda mo`e da se iskoristi i za obi~no izlistavawe sadr`aja fajla na ekranu. ---------------------------------------------------- CHMOD chmod mode name Komanda chmod vr{i promenu dozvola pristupa jednom ili ve}em broju fajlova koji su zadati sa name. Nova dozvola pristupa je definisana sa mode.

Operativni sistem UNIX omogu}ava selektivno definisawe korisnika koji imaju pristup odre|enom fajlu ili direktorijumu. Za svaki fajl ili direktorijum postoje tri klase korisnika: vlasnik -korisnik koji je kreirao fajl ili direktorijum, grupa -vi{e korisnika je definisano kao grupa, a svaki fajl pripada jednoj

grupi, pored toga {to pripada korisniku ostali -ostali korisnici sistema koji nisu ni vlasnik ni ~lanovi grupe. Tako|e, svaki fajl ili direktorijum ima tri na~ina pristupa:

Page 9: UNIX Osnovne Komande2

1.Osnovi kori{}ewa UNIX-a 9

read (u oznaci r) : -fajl mo`e samo da se ~ita, a u slu~aju direktorijuma, fajlovi

koji se u wemu nalaze mogu se prikazati. write (u oznaci w): -dozvoqena je modifikacija fajla, na direktorijumu mogu da se

kreiraju novi fajlovi i bri{u postoje}i. execute (u oznaci x): -fajl je izvr{ni. Kod direktorijuma je dozvoqeno pristupiti

fajlovima (u slu~aju dozvole za ~itawe, bilo je mogu}e samo ih

prikazati). U odnosu na prethodno opisane klase i pristupe za svaki fajl ili direktorijum definisan je mod: rwx rwx rwx vlasnik grupa ostali Ukoliko stoji "-" pristup je zabrawen. Komandom chmod mogu}e je mewati pristup fajlu. Argument mode defini{e se na slede}i na~in: 1. oktalno 400 r 200 w vlasnik 100 x 40 r 20 w grupa 10 x

4 r 2 w ostatak sveta 1 x Napisani brojevi dati su u oktalnom obliku. Wihovim jednostavnim sabirawem dobijemo `eqeni mod fajla. Na primer, ako `elimo da postavimo

Page 10: UNIX Osnovne Komande2

1.Osnovi kori{}ewa UNIX-a 10

dozvolu r-xrw--wx, to ~inimo tako {to sabiramo 400+100+40+20+2+1 = 563 (oktalno). 2. simboli~ki u - r vlasnik g + w grupa o = x ostali a svi primeri: % chmod 444 dat1 % ls -l dat1 -r--r--r-- 1 tanja user 1046 Nov 15 13:01 dat1 % chmod 644 dat1 % ls -l dat1 -rw-r--r-- 1 tanja user 1046 Nov 15 13:01 dat1 % chmod a=r,u+w dat1 % ls -l dat1 -rw-r--r-- 1 tanja user 1046 Nov 15 13:01 dat1 % chmod a-rwx * % ll ---------- 1 tanja user 1046 Nov 15 13:01 dat1 % chmod u+rw,g+r,o+r * % chmod u+rw,go+r * % ll -rw-r--r-- 1 tanja user 1046 Nov 15 13:01 dat1 ---------------------------------------------------- CP cp file new_file cp file1 [file2 ...] dest_directory cp dir1 [dir2 ...] dest_directory Komandom cp mogu se obaviti slede}e akcije: ♦ kopira se sadr`aj fajla file u fajl new_file. Ukoliko fajl new_file

postoji, wegov stari sadr`aj }e biti uni{ten. ♦ fajlovi file1, file2, ... kopiraju se na postoje}i direktorijum

dest_directory, poddirektorijumi dir1, dir2, ... kopiraju se u novi ili postoje}i direktorijum dest_directory.

primeri: % ls proba.c

Page 11: UNIX Osnovne Komande2

1.Osnovi kori{}ewa UNIX-a 11

% cp proba.c novi.c % ls proba.c novi.c % ls proba.c tmp/ % cp proba.c tmp % ls proba.c tmp/ % cd tmp % ls novi.c ---------------------------------------------------- MORE more file Prikazuje se sadr`aj fajla strana po strana gde je veli~ina stranice jednaka broju linija koje mogu da stanu na ekran. Ukoliko program nije stigao do kraja fajla, na dnu ekrana }e biti ispisano --More--. Pritiskom na taster < Enter > ispisuje se jo{ jedna linija, a pritiskom na taster < Space >, jo{ jedan ekran. Ova komanda tako|e mo`e da poslu`i u slu~ajevima kada prikazivawe rezultata neke druge komande zahteva vi{e prostora nego {to to ekran mo`e da pru`i. Strani~ewe rezultata ovakve komande vr{i se wenim pajpovawem sa komandom more. primeri: % more program.c % ls -l | more ---------------------------------------------------- MV mv file1 file2 mv file1 dest_directory Promena imena fajla ili preme{tawe fajla na drugi direktorijum. primeri: % ls proba.c tmp % mv proba.c novi.c % ls novi.c tmp

% ls -p

Page 12: UNIX Osnovne Komande2

1.Osnovi kori{}ewa UNIX-a 12

novi.c tmp/ % mv novi.c tmp % ls -p tmp/ % cd tmp % ls novi.c ---------------------------------------------------- RM rm [-irf] name Komanda za brisawe fajla name. -i - brisawe fajla uz verifikaciju, -r - rekurzivno brisawe (brisawe svih poddirektorijuma sa celokupnim

sadr`ajem) -f - bri{e bez provere dozvola. primeri: % rm /users/tanja/tmp/novi.c % rm -r tanja Upozorewe!!! Sa zadwom varijantom komande treba biti oprezan jer bri{e sve fajlove na direktorijumu, poddirektorijumima ispod wega i sam direktorijum. ---------------------------------------------------- LN ln [-s] name new_name Komanda ln kreira fajl new_name koji je link ka ve} postoje}em fajlu name. Parametar name mo`e biti i direktorijum ili specijalni fajl. Ako je parametar -s zadat, kreira se simboli~ki, a ako nije, nastaje hard link. Ovo je mehanizam koji omogu}ava da se jednom fizi~kom fajlu dodeli vi{e imena. To zna~i da imena name i new_name nakon izvr{avawa ove komande postaju ekvivalentna.

Page 13: UNIX Osnovne Komande2

1.Osnovi kori{}ewa UNIX-a 13

---------------------------------------------------- CLEAR clear Bri{e sadr`aj koji se trenutno nalazi na ekranu i postavqa prompt i kursor u prvu liniju. ---------------------------------------------------- DATE date [mmddhhmm[yy]] Ukoliko argumenti nisu dati, na ekranu se ispisuje teku}i datum i vreme. U suprotnom, defini{e se novi datum i novo vreme sistemskog sata. Ovo zadwe mo`e da uradi samo super korisnik, tj. korisnik sa posebnim privilegijama u odnosu na ostale korisnike. mm - mesec dd - dan hh - sat (24 sata) mm - minuti yy - posledwe dve cifre godine primeri: % date Thu Mar 30 21:12:05 MET DST 1996 % date 10080045 U zadwem primeru je postavqen datum: 8 oktobar teku}e godine, 12:45 a.m. ---------------------------------------------------- FIND find starting_dir [matching_criteria_&_actions]

Komanda find se rekurzivno kre}e kroz hijerarhiju fajl sistema po~ev od direktorijuma starting_dir tra`e}i fajlove koji zadovoqavaju logi~ki izraz matching_criteria i nad takvim fajlovima izvr{ava akcije actions. U opisu kreirawa matching_criteria, argument n predstavqa

Page 14: UNIX Osnovne Komande2

1.Osnovi kori{}ewa UNIX-a 14

decimalnu vrednost gde +n zna~i vi{e od n, -n mawe od n dok n zna~i ta~no n. Logi~ki izraz se formira od slede}ih primitiva: -atime n istinito ako je fajlu pristupano u n dana -mtime n istinito ako je fajl modifikovan u n dana -size n[c] istinito ako veli~ina fajla iznosi n blokova gde je blok, kod ve}ine verzija UNIX-a veli~ine 512 bajtova. Ako iza n sledi c, veli~ina fajla je u broju znakova. -type c istinito ako je fajl tipa c (f-obi~an fajl, d-direktorijum, ...) -name name istinito ako je ime fajla name (dozvoqeno kori{}ewe * i ?) -user usr istinito ako je vlasnik fajla usr -group grp istinito ako je grupa fajla grp -perm p istinito ako je pristupna dozvola fajlu p. Pristupna dozvola se zadaje oktalno (videti chmod). -print uvek istinito. Ispisivawe puta tra`enog fajla. -exec cmd istinito ako cmd vrati nulu. Ako iza cmd sledi '{}', onda se komanda izvr{ava nad fajlom koji zadovoqava matching_critteria. -ok cmd sli~no kao -exec, samo pre izvr{avawa komande cmd nad prona|enim fajlom, od korisnika se tra`i da verifikuje akciju sa y. -prune iskqu~ivawe fajla iz akcije. Vi{e komandi se odvajaju separatorom ;. primeri: % find / -name proba -print /users/tanja/tmp/proba

Tra`i se od korenskog direktorijuma fajl sa imenom proba i prona|en je na direktorijumu /users/tanja/tmp.

Page 15: UNIX Osnovne Komande2

1.Osnovi kori{}ewa UNIX-a 15

% find /usr/people -size +1000 \(-mtime +30 \ -o -atime +120 \) -exec ls -l '{}' ';' Od direktorijuma /usr/people tra`e se fajlovi ~ija je veli~ina ve}a od 1000 blokova, nisu mewani vi{e od 30 dana ili kojima nije pristupano vi{e od 120 dana. Prona|eni fajlovi se prikazuju na ekranu.

Ovde se znak \ koristi na kraju reda, da bismo wime signalizirali da komandu nismo uneli do kraja, ve} da u slede}em redu sledi nastavak. Ovaj znak smo stavili jo{ i ispred otvorene i zatvorene zagrade, da bismo ukinuli wihovo posebno zna~ewe. U zagradama, izme|u opcija -mtime i -atime, stoji jo{ i opcija -o, koja se ovde tretira kao logi~ko OR. Tako, na}i }e se svi fajlovi koji nisu mewani vi{e od 30 dana, ili im nije pristupano vi{e od 30 dana. % find /usr/people/tanja \(-name a.out -o -name core \ -o -name ".BAK.*"\) -atime +14 -exec rm -f '{}' ';' Ispod direktorijuma /usr/people/tanja, prona|i sve fajlove a.out, core i one ~ije ime po~iwe sa .BAK., kojima nije pristupano vi{e od 14 dana i izbri{i ih. ---------------------------------------------------- GREP grep [opcije] [expression] [files ...] Komanda grep pretra`uje navedene fajlove (ili standardni ulaz). Svaka linija koja zadovoqava expression {tampa se na standardni izlaz. U slu~aju da se istovremeno pretra`uje vi{e fajlova, ispred svake linije {tampa se i ime fajla iz koje poti~e. Dozvoqene su slede}e opcije: -v prikazuju se sve linije koje ne zadovoqavaju expression -c prikazuje se samo broj linija sa poklapawima -l prikazuju se samo imena fajlova u kojima je ustanovqeno poklapawe -h ne prikazuju se imena fajlova -n pored imena fajla {tampaju se i brojevi linija -s ne prikazuju se poruke o gre{kama -i velika i mala slova se tretiraju isto primeri: % grep automation srle.txt and automation placement

Page 16: UNIX Osnovne Komande2

1.Osnovi kori{}ewa UNIX-a 16

Prika`i sve linije iz fajla srle.txt koje sadr`e re~ automation. % grep automation srle.txt tanja.txt srle.txt: and automation placement % grep '???' poruka He really wondered why? Why??? % grep -li serial *.h ---------------------------------------------------- UNAME uname Ispisuje verziju instaliranog UNIX-a. primer: % uname -a Linux ime_racunara 2.0.25 #5 Thu Apr 24 13:17:01 MET DST 1997 i486 ---------------------------------------------------- WHOAMI whoami Ispisuje ime teku}eg korisnika. primer: % whoami srle ---------------------------------------------------- WHO who Daje spisak korisnika koji trenutno rade na sistemu. Izlaz ima oblik: name line time gde je:

Page 17: UNIX Osnovne Komande2

1.Osnovi kori{}ewa UNIX-a 17

name - korisni~ko login ime, line - ime terminala, time - vreme kada je korisnik prijavqen sistemu. primer: % who srle console Nov 24 13:45 tanja ttyp1 Nov 24 14:21 dejan ttyp2 Nov 24 15:05 Sli~nu funkciju ima i komanda w s tom razlikom {to daje detaqnije informacije o prijavqenim korisnicima i wihovim trenutnim aktivnostima. primer: % w 11:31am up 1:11, 2 users, load average: 0.00, 0.00, 0.00 User tty from login@ idle JCPU PCPU what srle tty2 10:29am 1 w srle tty1 10:24am 30 29 joe komande.html ---------------------------------------------------- DF df daje podatke o slobodnom mestu na disku u blokovima. primer: % df Filesystem 1024-Blocks Used Available Capacity Mounted on /dev/hda1 266117 213165 52925 85% / /dev/hda3 735633 552880 182753 75% /dosc ---------------------------------------------- TAR tar [arguments] [name] Komanda za zapis, ~itawe i listawe sadr`aja arhive. Argumenti: -c - zapis od po~etka arhive. -r - zapis na kraju arhive (dodavawe fajlova starom sadr`aju)

Page 18: UNIX Osnovne Komande2

1.Osnovi kori{}ewa UNIX-a 18

-t - listawe sadr`aja arhive. -x - ~itawe sadr`aja arhive i zapis na disk. -f - definisawe arhive (naredni argument je specijalni fajl trake ili

ime obi~nog fajla arhive).

-v - za vreme snimawa ili ~itawa arhive ispisuju se imena fajlova koji se trenutno

obra|uju (verbose mod). name - ime fajla ili direktorijuma koji se arhivira ili restaurira (ukqu~uju se i

podirektorijumi). primeri: % tar -tvf arhiva.tar Prikazivawe sadr`aja arhive arhiva.tar. % tar -cvf nova.arhiva.tar * Arhivirawe svih fajlova iz teku}eg direktorijuma u novu arhivu pod imenom nova.arhiva.tar. % tar -rvf stara.arhiva.tar proba.mi Dodavawe fajla proba.mi na ve} postoje}u arhivu stara.arhiva.tar. % tar -cvf nova.tar srledir Arhivirawe celog direktorijuma srledir, sa svim wegovim poddirektorijumima u novu arhivu nova.tar. % tar -xvf arhiva.tar Prikazivawe sadr`aja arhive arhiva.tar.

1.2. EDITOR POD UNIX-OM Editor koji }emo mi koristiti zove se joe. Poziva se jednostavno: uz ime programa dovoqno je navesti i ime fajla koji `elimo da editujemo. Ako ne navedemo ime, mo`emo da fajl u~itamo iz samog editora. Osnovni help se dobija sa Ctrl+K+H. Osnovne naredbe: Ctrl + K + F find Ctrl + L find again Ctrl + K + U go to the top of the document

Page 19: UNIX Osnovne Komande2

1.Osnovi kori{}ewa UNIX-a 19

Ctrl + K + V go to the end of the file Ctrl + K + L go to line No. xxx Ctrl + K + B mark block begin Ctrl + K + K mark block end Ctrl + K + M move block Ctrl + K + C copy block Ctrl + K + Y delete block Ctrl + Y delete line Ctrl + W delete next word Ctrl + _ undo Ctrl + ^ redo Ctrl + K + X save and exit Ctrl + C abort Ctrl + K + Z shell Ctrl + K + E edit file Ctrl + K + R insert file Ctrl + K + D save file

Page 20: UNIX Osnovne Komande2

2. Moska Modula-2 20

2. MOCKA MODULA-2

Mocka Modula-2 je instalirana u direktorijumu /usr/mocka. Tu se, pored osnovnog uputstva za upotrebu, nalazi jo{ i pet poddirektorijuma. To su: lib bibliote~ki moduli sys sistemski poddirektorijum src izvorni kod mocka M2

examples primeri doc razne informacije o mocka M2

U mocka M2, obi~ni moduli, kao i implementacioni moduli zavr{avaju se sa .mi, dok se definicioni moduli zavr{avaju sa .md. Prilikom prevo|ewa, kompajler generi{e jo{ tri fajla. Fajl koji ima zavr{etak .o je objektni kod programa, a fajl bez "ekstenzije" je izvr{ni program. Tre}i fajl, sa zavr{etkom .r, je pomo}ni fajl. Mocka M2 prevodilac se poziva sa mc. Potom se dobije prompt: >> Ako `elimo da editujemo neki program, pozva}emo editor na slede}i na~in: >> i hello Ova komanda pozva}e editor joe, koji }e editovati novi fajl pod imenom hello.mi. Po{to napi{emo na{ program, i iza|emo iz editora, svakako }emo po`eleti da ga kompajliramo. To ~inimo naredbom: >> p hello Neka smo, me|utim, napravili neku gre{ku u programu. Nakon prevo|ewa programa do kraja, pozva}e se editor joe, koji }e editovati privremeni fajl sa porukama o gre{kama, koji izgleda ovako: @ LISTING

Page 21: UNIX Osnovne Komande2

2. Moska Modula-2 21

MODULE hello; FROM InOut IMPORT WriteString, WriteLn; BEGIN WriteNl; @ ^ @ Col 3: 'WriteNl' not declared WriteString ("Hello World"); WriteLn; END hello. Po{to ispravimo gre{ku, potrebno je sa~uvati fajl, iza}i iz editore, i ponovo kompajlirati program, pa ako sve bude u redu, mo`emo ga i pozvati: >> hello Hello, world! >> Iz shell-a prevodioca izlazimo jednostavno: >> q Mocka M2 ima nekoliko standardnih bibliote~kih modula, od kojih }emo ovde navesti samo neke, koji se naj~e{}e koriste. Pre svega, tu je modul InOut, koji sadr`i standardne ulazno/izlazne rutine: DEFINITION MODULE InOut; PROCEDURE Read (VAR x : CHAR); (* Read the next character from std input into 'x' *) PROCEDURE ReadString (VAR x : ARRAY OF CHAR); (* Read the next string from std input into 'x'. *) (* Leading blanks are ignored. *) (* Input is terminated by any character <= ' ' *) PROCEDURE ReadCard (VAR x : CARDINAL); (* Read the next string from std input and *) (* convert it to cardinal 'x'. *) (* Syntax : digit {digit} *) PROCEDURE ReadInt (VAR x : INTEGER); (* Read the next string from std input and *) (* convert it to integer 'x'. *) (* Syntax : ['+'|'-'] digit {digit} *) PROCEDURE ReadReal (VAR x : REAL); (* Read the next string from std input and convert it *) (* to real 'x'. *) (* Syntax : ['+'|'-'] digit {digit} ['.' digit {digit}] *) (* ['E'['+'|'-'] digit {digit}] *) PROCEDURE ReadLongReal (VAR x : LONGREAL); (* Read the next string from std input and convert it *)

Page 22: UNIX Osnovne Komande2

2. Moska Modula-2 22

(* to long real 'x'. *) (* Syntax : ['+'|'-'] digit {digit} ['.' digit {digit}] *) (* ['E'['+'|'-'] digit {digit}] *) PROCEDURE Write (x : CHAR); (* Write character 'x' onto std output *) PROCEDURE WriteString (VAR x : ARRAY OF CHAR); (* Write the string 'x' onto std output *) PROCEDURE WriteCard (x : CARDINAL; n : CARDINAL); (* Convert the cardinal 'x' into decimal representation and *) (* write it onto std output. Field width is at least 'n'. *) PROCEDURE WriteOct (x : CARDINAL; n : CARDINAL); (* Convert the cardinal 'x' into octal representation and *) (* write it onto std output. Field width is at least 'n'. *) PROCEDURE WriteHex (x : CARDINAL; n : CARDINAL); (* Convert the cardinal 'x' into hexadecimal representation *) (* and write it onto std output. Field width is at least 'n'. *) PROCEDURE WriteInt (x : INTEGER; n : CARDINAL); (* Convert the integer 'x' into decimal representation and *) (* write it onto std output. Field width is at least 'n'. *) PROCEDURE WriteReal (x : REAL; n : CARDINAL; k : INTEGER); (* Convert the real 'x' into external representation and *) (* write it onto std output. Field width is at least 'n'. *) (* If k > 0 use k decimal places. *) (* If k = 0 write x as integer. *) (* If k < 0 use scientific notation. *) PROCEDURE WriteLongReal (x : LONGREAL; n : CARDINAL; k : INTEGER); (* Convert long real 'x' into external representation and *) (* write it onto std output. Field width is at least 'n'. *) (* If k > 0 use k decimal places. *) (* If k = 0 write x as integer. *) (* If k < 0 use scientific notation. *) PROCEDURE WriteLn; (* Write the end of line character onto std output *) (* Emit buffer contents immediately *) PROCEDURE WriteBf; (* Emit buffer contents immediately *) PROCEDURE Done () : BOOLEAN; (* last operation ok *) PROCEDURE EOF () : BOOLEAN; (* EOF at standard input *) END InOut. Zatim je tu modul koji sadr`i rutine za rad sa fajlovima BasicIO.md:

Page 23: UNIX Osnovne Komande2

2. Moska Modula-2 23

DEFINITION MODULE BasicIO; FROM SYSTEM IMPORT ADDRESS; TYPE File = INTEGER; PROCEDURE OpenInput (VAR file : File; VAR name : ARRAY OF CHAR); (* Open file 'file' for input. Use External name 'name' *) PROCEDURE OpenOutput (VAR file : File; VAR name : ARRAY OF CHAR); (* Open file 'file' for input. Use External name 'name' *) PROCEDURE Close (file: File); (* Close file 'file' *) PROCEDURE Erase (VAR name : ARRAY OF CHAR; VAR ok : BOOLEAN); (* erase file with external name 'name' *) PROCEDURE Read(file : File;x : ADDRESS;n : INTEGER;

VAR read :INTEGER); (* Read n bytes from file 'file' into area starting at address 'x' *) (* On exit 'read' denotes the number of bytes actually read *) PROCEDURE Write (file : File; x : ADDRESS; n : INTEGER); (* Write 'n' bytes of area starting at address 'x' to file 'file' *) PROCEDURE Accessible (VAR name : ARRAY OF CHAR; ForWriting : BOOLEAN) : BOOLEAN; (* Return true if the file with external name 'name' is accessible for reading (ForWriting = FALSE) resp. for writing (ForWriting = TRUE).*) VAR DONE : BOOLEAN; (* READ ONLY variable *) END BasicIO. Standardni modul je i Storage.md: DEFINITION MODULE Storage; FROM SYSTEM IMPORT ADDRESS; PROCEDURE ALLOCATE (VAR a : ADDRESS; size : CARDINAL); (* Allocates an area of the given size 'size' and returns it's *) (* address in 'a'. If no space is available, 'a' becomes 'NIL'. *) PROCEDURE DEALLOCATE (VAR a : ADDRESS; size : CARDINAL); (* Frees the area of size 'size' starting at address 'a'. *) (* Upon return 'a' is set 'NIL' *) END Storage.

Page 24: UNIX Osnovne Komande2

2. Moska Modula-2 24

Pored ovih modula, Mocka M2 ima jo{ neke, koje }emo ovde samo ukratko navesti. Modul Arguments u sebi sadr`i rutine za rad sa argumentima glavnog programa. Sadr`i procedure GetArgs i GetEnv. Modul ByteIO sadr`i rutine za ulazno-izlazne operacije op{teg tipa. Ovaj modul je op{tiji od BasicIO, i sadr`i jo{ neke rutine za manipulaciju bajtovima. Modul Clock sadr`i rutine za ~itawe sistemskog vremena. Modul ErrNumbers sadr`i u sebi kodove gre{aka do kojih mo`e da do|e tokom rada sistema. Modul InOut u sebi sadr`i osnovne rutine za ulaz i izlaz. Modul LREAL sadr`i u sebi rutine za konverziju tipova LONGREAL i LONGINT. Modul MathLib u sebi sadr`i standardne matemati~ke funkcije i operacije. Moduli NumConv i RealConv u sebi sadr`e rutine za konverziju izme|u stringova i celih, odnosno realnih brojeva. Modul Signnals u sebi sadr`i kodove signala i rutinu koja predstavqa sistemski poziv Signal (vidi poglavqe 3.2.). Moduli Strings i Strings1 u sebi sadr`e rutine za rad sa stringovima. Modul SysLib u sebi sadr`i rutine koje predstavqaju sistemske pozive. Mnogi od wih se veoma ~esto koriste. Modul TextIO u sebi sadr`i standardne rutine za ulaz i izlaz, ali za rad sa tekstualnim fajlovima.

Page 25: UNIX Osnovne Komande2

2. Moska Modula-2 25

3. SISTEMSKI POZIVI UNIX-A

Sistemski pozivi UNIX-a jesu funkcije koje pozivaju operativni sistem da uradi odre|en posao za potrebe programa, npr. da u~itaju podatke sa diska, itd. Oni, uslovno re~eno, predstavqaju analogon prekidima u DOS-u. Zapravo, sistemski pozivi se i realizuju pomo}u posebnog prekida (u Linux-u prekid 0x80 je rezervisan za sistemske pozive). Spoqa, sistemski poziv izgleda kao obi~na C funkcija, tako da je mnogo lak{e i preglednije koristiti sistemski poziv, nego baratati sa registrima pri radu sa prekidima. U ovom poglavqu bi}e predstavqeni najva`niji i naj~e{}e kori{}eni sistemski pozivi UNIX-a, kao i programi koji ih ilustruju. Svi primeri su ura|eni u programskom jeziku Modula-2, i testirani na ve} pomenutom prevodiocu Mocka M2. Kao {to je ve} re~eno, svaki sistemski poziv je zapravo C funkcija. Obzirom na to da se u primerima koji slede svi sistemski pozivi pozivaju kao M2 funkcije, pre svega je potrebno objasniti na~in kako da svaki sistemski poziv predstavimo M2 funkcijom. Neka je dat slede}i sistemski poziv: int fork()

Prvo je potrebno napraviti poseban definicioni modul, koji po~iwe kqu~nom re~i FOREIGN, i koji sadr`i definiciju M2 funkcije koja je istovetna po imenu, broju i tipu argumenata kao i odgovaraju}i sistemski poziv (kod imena funkcija treba obratiti pa`wu na velika i mala slova): FOREIGN MODULE lib; PROCEDURE fork() : INTEGER; END lib.

Potom, potrebno je napraviti i odgovaraju}i implementacioni modul, koji u sebi ne}e sadr`ati ni{ta: IMPLEMENTATION MODULE lib; END lib.

Page 26: UNIX Osnovne Komande2

2. Moska Modula-2 26

Daqe, neka imamo neki slo`eniji slu~aj, na primer: char * fgets( char * s, int n, FILE * stream) Tada, odgovaraju}i definicioni modul izgleda ovako: FOREIGN MODULE lib2; FROM SYSTEM IMPORT ADDRESS; PROCEDURE fgets( s : ADDRESS; Size : INTEGER; Stream : ADDRESS) : ADDRESS; END lib2. Ovde treba obratiti pa`wu da su pokaziva~ki tipovi u C-u prevedeni kao tip ADDRESS u Mocka M2. Implementacioni modul }e i ovde biti prazan: IMPLEMENTATION MODULE lib2; END lib. Tako|e nije veliki problem usposatviti odnos izme|u C tipova i Mocka M2 tipova. U slu~aju prostih tipova, ovo je ~ak veoma jednostavno. U slede}oj tabeli dat je odnos prostih tipova Mocka Module-2 i C-a*: C tip Modula-2 tip -------------------------------------------------------------------- int INTEGER, WORD long int LONGINT unsigned int CARDINAL, WORD unsigned long int LONGCARD short int BYTE, CHAR unsigned short int BYTE, CHAR char CHAR, BYTE unsigned shar BYTE, CHAR float REAL Kod slo`enijih tipova podataka, kao {to su slogovi, tako|e nije problem uspostaviti korespodenciju. Na primer: C slog Modula-2 slog -------------------------------------------------------------------------------- struct slog { slog = RECORD int x, y; x, y : INTEGER; char a, b; a, b : CHAR; } END;

Me|utim, kod pokaziva~a se mora obratiti pa`wa na jo{ jednu stvar. Pokaziva~ u C-u se u M2 prevodi kao tip ADDRESS, s tim da se mora obratiti pa`wa na {ta ta adresa pokazuje. Ako u C-u imamo, na primer, char * x,

* U slu~aju da se radi sa nekim drugim prevodiocem, korespodencija bi mo`da bila druga~ija.

Page 27: UNIX Osnovne Komande2

2. Moska Modula-2 27

tada }e x u M2 biti tipa ADDRESS, s tim da x mora da pokazuje na promenqivu tipa CHAR.

3.1. PROCESI 3.1.1. Fork

Novi proces mo`emo kreirati pomo}u sistemskog poziva fork: PROCEDURE fork() : INTEGER;

Nakon poziva funkcije, kreira se novi proces, potpuno istovetan onom iz kojeg je rutina pozvana. Funkcija kao svoj rezultat vra}a PID novostvorenog procesa. PID predstavqa jedinstveni identifikacioni broj procesa ( Process ID ), pomo}u kojeg ga operativni sistem mo`e jednozna~no identifikovati. Nakon poziva fork-a, nikada se ne zna ta~no koji }e se proces po~eti izvr{avati, roditeq ili potomak. Mo`e se dogoditi da }e roditeq nastaviti da se izvr{ava, sve dok ne zavr{i posao ili ga operativni sistem ne prekine, pa potom preda kontrolu potomku. Sa druge strane, mo`e se desiti da se kontrola odmah po pozivu fork-a preda potomku, pa da on nastavi sa radom dok ne zavr{i posao, ili dok ga operativni sistem ne prekine.

Novi proces od svog roditeqa nasle|uje ceo niz osobina. Ipak, neke ne mogu biti iste, da bismo ih uop{te mogli razlikovati. Novi proces razlikuje se od svog roditeqa u slede}em:

♦ proces potomak ima svoj jedinstven PID; ♦ proces potomak ima razli~it PID roditeqa, nego {to ima wegov

roditeq; ♦ proces potomak }e imati svoje posebne kopije svih fajl deskriptora

koje je wegov roditeq otvorio ili kreirao. Potomak ih mo`e zatvoriti bez uticaja na roditeqa. Ofset za pristup unutar wih }e, me|utim, biti isti. Tako, ako oba procesa pi{u u fajl istovremeno, zapis }e biti izme{an. Isto tako, ako ~itaju fajl u isto vreme, svaki }e primiti samo deo podataka;

♦ skup zadr`anih signala za proces potomak se inicijalizuje na prazan skup;

♦ svi lokovi (engl. locks, zabrane ~itawa, odnosno pisawa nekog fajla postavqeni od strane nekog procesa) koje je proces roditeq kreirao, za proces potomak ne va`e.

Sistemska funkcija fork je zanimqiva zbog jo{ jedne stvari. Ona

vra}a razli~ite vrednosti; jednu kada se pozove u procesu roditequ, a drugu u procesu potomku. U prvom slu~aju, vra}a se PID procesa potomka, a u drugom

Page 28: UNIX Osnovne Komande2

2. Moska Modula-2 28

nula. Ovo je siguran na~in da razlikujemo ova dva procesa*, i svaki program koji u sebi sadr`i fork, obi~no ima ovakav kod: ... IF fork() = 0 THEN naredbe za potomka... ELSE naredbe za roditelja... END; ... Sistemski poziv fork }emo ilustrovati na jednom jednostavnom primeru. Neka oba procesa samo ispisuju 10 nizova cifara od 0-9, s tim da se na po~etku ispi{e koji proces je trenutno aktivan. Program izgleda ovako: MODULE Fork; (* Implemented by Sasa Popravak *) FROM InOut IMPORT WriteInt, WriteLn, WriteString; FROM lib IMPORT fork; VAR i, j : SHORTCARD; PID : INTEGER; BEGIN (* Create child process. *) PID := fork (); IF PID = -1 THEN WriteString ("Error forking process. Aborting..."); WriteLn; HALT; END; (* This got executed by child process. *) IF PID = 0 THEN WriteLn; WriteString ("Executed by child process: "); WriteLn; FOR i := 0 TO 10 DO FOR j := 0 TO 9 DO WriteInt (j, 1); END; END; ELSE (* Parent process should do this. *) WriteLn; WriteString ("Executed by parent process: "); WriteLn; FOR i := 1 TO 10 DO FOR j := 0 TO 9 DO

* Proces potomak nikada ne mo`e imati PID nula. Proces sa PID jednak nuli je poseban sistemski proces, koji je aktivan sve dok se ceo sistem ne obori.

Page 29: UNIX Osnovne Komande2

2. Moska Modula-2 29

WriteInt (j, 1); END; END; END; (* This is executed in both processes, which means twice. *) WriteLn; END Fork. Primer izvr{avawa: # Fork Executed by parent process: 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 Executed by child process: 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 #

Primetimo da, ukoliko smo kao rezultat fork-a dobili -1, da je do{lo do gre{ke, i da smesta prekidamo program. fork se, ina~e, retko koristi da bi se pomo}u wega napravilo nekoliko kopija jednog te istog programa. Mnogo ~e{}e se proces potomak zameni sa nekim drugim procesom, koji zauzme resurse potomka, i popuni ih svojim kodom. Na taj na~in, u potomku }e se izvr{iti kod potpuno razli~it od koda roditeqa. U poglavqu 3.1.3. vide}emo koji sistemski pozivi omogu}avaju da se ovo uradi. Pored fork-a, postoje jo{ dva sistemska poziva koji su u tesnoj vezi sa wim: PROCEDURE wait( status : ADDRESS (* pointer to integer *) ) : INTEGER; PROCEDURE exit( status : INTEGER );

Kada se pozove exit, proces koji ga je pozvao zavr{ava sa radom, a u promenqivoj status vra}a svoj izlazni status. Kako }e se taj broj tretirati, zavisi iskqu~ivo od programera, ali se po konvenciji uzima, ako je proces na izlazu vratio nulu, da je sve pro{lo u redu. Ne-nula vrednost obi~no ozna~ava da je do{lo do neke gre{ke. Izlazni status se vra}a procesu roditequ. Proces roditeq mo`e da primi izlazni status nekog svog potomka pomo}u sistemskog poziva wait. Po pozivu wait-a, proces koji ga je pozvao prekida rad sve dok neki od wegovih neposrednih potomaka ne zavr{i sa radom. Na adresi status ( koja pokazuje na ceo broj) se, nakon zavr{etka rada nekog od procesa potomaka, nalazi izlazni status. Funkcija kao svoj rezultat vra}a PID procesa potomka.

Programsku ilustraciju ova dva sistemska poziva ima}emo zajedno sa ilustracijom sistemskih poziva exelc i execv, u poglavqu 3.1.3.

Page 30: UNIX Osnovne Komande2

2. Moska Modula-2 30

3.1.2. System

Za izvr{avawe proizvoqnog programa, obezbe|en je sistemski poziv system: PROCEDURE system( string : ADDRESS (* pointer to string *) ) : INTEGER; Na adresi string mora da se nalazi string koji sadr`i ta~nu komandu operativnog sistema. Kao svoj rezultat, ova funkcija vra}a izlazni status komande operativnog sistema koju smo pozvali. Ovaj sistemski poziv ilustrova}emo na jednostavnom primeru. Neka na{ program ispisuje koji je teku}i dan u nedeqi, koriste}i komande grep i date. Komanda operativnog sistema koju pozivamo, izgleda ovako: date | grep > /dev/null kratko_ime_dana Rezultat komande date prosledimo komandi grep, koja u dobijenom stringu tra`i prosle|eno ime dana. Svoj rezultat grep vra}a u nepostoje}i ure|aj /dev/null, tj. nigde. Da li smo na{li dan ili ne, zna}emo na osnovu izlaznog statusa grep-a. MODULE Grep; (* Implemented by Sasa Popravak *) FROM InOut IMPORT WriteLn, WriteString; FROM SysLib IMPORT system; FROM SYSTEM IMPORT ADR; FROM Strings IMPORT String, Concat; TYPE DayNames = RECORD fullname : String; (* Full day name. *) abbrev : String; (* And short one. *) END; (* Whole week. *) DaysArray = ARRAY [1..7] OF DayNames; VAR Command : String; Status : INTEGER; Days : DaysArray; i : CARDINAL; d : DaysArray; (* As Wirth created Modula-2 without having constant arrays or records this procedure is needed to set record fields in an array

("acting" CONST). *)

Page 31: UNIX Osnovne Komande2

2. Moska Modula-2 31

PROCEDURE Init (VAR d : DaysArray); BEGIN d [1].abbrev := "Sun"; d [1].fullname := "Sunday"; d [2].abbrev := "Mon"; d [2].fullname := "Monday"; d [3].abbrev := "Tue"; d [3].fullname := "Tuesday"; d [4].abbrev := "Wed"; d [4].fullname := "Wednesday"; d [5].abbrev := "Thu"; d [5].fullname := "Thursday"; d [6].abbrev := "Fri"; d [6].fullname := "Friday"; d [7].abbrev := "Sat"; d [7].fullname := "Saturday"; END Init; BEGIN (* Create "CONST" array of records ... *) Init (d); (* ... and for each day of week give us it's full name. *) FOR i := 1 TO 7 DO Command := "date | grep > /dev/null "; Concat (Command, d [i].abbrev, Command); Status := system (ADR (Command)); (* grep returns 0 if we have a match, 256 if no match and

something else otherwise. *) IF Status = 0 THEN WriteString ("Today is "); WriteString (d [i].fullname); WriteLn; ELSIF Status = 256 THEN WriteString ("Today is not "); WriteString (d [i].fullname); WriteLn; ELSE WriteString ("Grep error. Aborting..."); WriteLn; HALT; END; END; END Grep. Primer izvr{avawa: # Grep Today is not Sunday Today is not Monday Today is Tuesday Today is not Wednesday Today is not Thursday

Page 32: UNIX Osnovne Komande2

2. Moska Modula-2 32

Today is not Friday Today is not Saturday #

Boqe je, me|utim, izbegavati kori{}ewe funkcije system kada god je to mogu}e. Postoje tri va`na razloga za to: 1) Veoma je neefikasan. Svaki put kada se on pozove, on pokre}e ne samo

komandu koja mu je prosle|ena, ve} i novu kopiju shell-a. Ako korisnikov program izvr{ava mnogo komandi, boqe je da se izvr{e direktno, nego da se koristi system. Na~in da se ovo uradi, opisan je u slede}em odeqku.

2) Sistemski pozivi i bibliote~ke rutine su uvek efikasnije od system-a,

da bi se wima izvr{ila ista stvar. Na primer, umesto poziva

system( "rm -f file" ); system( "mkdir foo" ); system( "mv oldfile newfile" );

boqe je koristiti odgovaraju}e sistemske pozive:

unlink( "file" ); mkdir( "foo" ); rename( "oldfile", "newfile" );

3) Veoma je opasno pisati programe sa super-user privilegijama, koji pozivaju

system, jer se u okviru wega poziva nova kopija shell-a, a postoje na~ini da se izvr{i neka druga komanda od one koja je namerena.

3.1.3. Execl i Execv

Mnogo efikasniji i mnogo mo}niji aparat za izvr{avawe programa nude sistemski pozivi execl i execv. Oni su veoma sli~ni, i izgledaju ovako: PROCEDURE execl( a1, ... an : ADDRESS (* pointer to string *) ) : INTEGER; PROCEDURE execv( a, b : ADDRESS ) : INTEGER; (* a - pointer to string, b - pointer to array of strings *)

Kod execl, u a1 se prosle|uje adresa stringa koji sadr`i apsolutnu stazu (engl. pathname) do programa koji `elimo da izvr{imo. U a2 se prosle|uje adresa stringa koji sadr`i ime programa kojeg pozivamo, a u a3,...,an-1 prosle|uju se adrese stringova koji predstavqaju argumente sa kojima pozivamo program. U an se uvek prosle|uje NIL, da bismo dali indikaciju za kraj liste argumenata.

Kod execv, argument a je pokaziva~ na string koji sadr`i pathname programa koji `elimo da izvr{imo. U b se prosle|uje pokaziva~ na niz

Page 33: UNIX Osnovne Komande2

2. Moska Modula-2 33

stringova, od kojih je prvi ime programa koji `elimo da pozovemo, a ostali su argumenti sa kojima pozivamo program. Posledwi string je uvek NIL, da bi se znalo gde je kraj liste.

Kod ova dva sistemska poziva, potrebno je obratiti pa`wu na jo{ jedan veoma va`an detaq. Naime, prilikom poziva, sadr`aj procesa koji je pozvao exec se prepisuje sadr`ajem novog programa. Nova slika procesa se konstrui{e iz obi~nog izvr{nog fajla. Ako exec uspe, on nikada ne vra}a vrednost, jer je sadr`aj procesa koji ga je pozvao prepisan sadr`ajem novog programa.

execl }emo ilustrovati na primeru. Neka proces roditeq izvr{ava komandu echo, a proces potomak komandu date, tako da kao rezultat dobijemo teku}i datum sa propratnom porukom. MODULE WFork; (* Implemented by Sasa Popravak *) FROM SYSTEM IMPORT ADR, ADDRESS; FROM Strings IMPORT String, EmptyString, Assign; FROM InOut IMPORT WriteLn, WriteString; FROM lib IMPORT fork, execl, system, wait; VAR s1, s2, s3, s4, s5 : String; Status : INTEGER; PID : INTEGER; BEGIN (* These strings are needed because 'execl' is defined as int execl (const char *path, const char *arg, ...); which means with variable number of parameters whis is not support in Modula-2, so this is some kind of patch ;)) *) EmptyString (s1); EmptyString (s1); EmptyString (s3); EmptyString (s4); EmptyString (s5); (* Create child process. *) PID := fork (); IF PID = -1 THEN WriteString ("Error forking process. Aborting..."); HALT; END; IF PID = 0 THEN

Page 34: UNIX Osnovne Komande2

2. Moska Modula-2 34

(* This got executed by child process. *) (* Construct command for Exec/execl. *) Assign (s1, "/bin/echo"); Assign (s2, "echo"); Assign (s3, "Today's"); Assign (s4, "date"); Assign (s5, "is:"); Status := execl(ADR(s1), ADR(s2), ADR(s3), ADR(s4), ADR(s5), NIL); IF Status = -1 THEN WriteString ("Error executing child program. Aborting..."); WriteLn; HALT; END; ELSE (* Wait for child to finish. *) WHILE wait (NIL) # PID DO END; (* This code is executed by parent process. *) EmptyString (s1); EmptyString (s1); EmptyString (s3); Assign (s1, "/bin/date"); Assign (s2, "date"); Assign (s3, "+%A, %B %d, %Y"); Status := execl (ADR (s1), ADR (s2), ADR (s3), NIL, NIL, NIL); IF Status = -1 THEN WriteString ("Error executing parent program. Aborting..."); WriteLn; HALT; END; END; (* This is executed in both processes, which means twice. *) WriteLn; END WFork. Primer izvr{avawa: # WFork Today's date is: Tuesday, June 09, 1998 # Primetimo da, u ovom primeru proces dete nije zavr{io svoj rad sa exit, ve} sa execl. Po{to execl prepisuje sadr`aj procesa koji ga je pozvao, u procesu roditequ ~ekamo na PID potomka, koji }e se vratiti posle izvr{ewa execl-a, bez izlaznog statusa.

Page 35: UNIX Osnovne Komande2

2. Moska Modula-2 35

Na samom kraju, da}emo primer kako da se napravi krajwe jednostavan shell, koriste}i fork, execl i wait. Primer }e biti dat u pseudokodu. ... LOOP read_command( command, parameters ); IF fork() <> 0 THEN wait( status ); (* izvrsava roditelj *) ELSE execl( command, parameters ); (* izvrsava potomak *) END; END; ... Na ovom primeru se mo`e videti kako se kod procesa potomka zameni potpuno drugim kodom, u na{em slu~aju kodom naredbe command. Dok se program command izvr{ava, proces roditeq ~eka da potomak zavr{i sa radom, da bi ponovo u~itao slede}u komandu.

3.2. SIGNALI Signali predstavqaju sredstvo pomo}u kojeg se procesima mo`e saop{titi da se ne{to dogodilo. Oni su zapravo softverski prekidi, i za wih je pod Linux-om rezervisan prekid 0x80. Wih u raznim varijantama UNIX-a ima razli~it broj, i taj broj se ne mo`e promeniti. Pod Linux-om ih ima 31, a za Mocka M2 prevodilac svi su definisani u modulu Signals.md.

Postoje strogo odre|ena pravila pod kojima jedan proces mo`e poslati signal drugom procesu:

♦ Kernel mo`e poslati signal bilo kom procesu; ♦ Proces sa super user privilegijama mo`e poslati signal bilo kom

procesu; ♦ Proces mo`e poslati signal drugom procesu samo ako su im UID (User

ID, identifikacioni broj korisnika koji je vlasnik procesa) i GID (Group ID, identifikacioni broj grupe koja je vlasnik procesa) isti. Svaki signal ima tzv. dispoziciju, t.j. stawe u kojem mo`e da se na|e u

odnosu na proces kome je poslat. Za sve signale postoje ~etiri osnovne dispozicije:

1) Signal mo`e biti primqen. Proces primalac prekida svoj rad i

daje kontrolu rutini za obradu signala. 2) Signal mo`e biti zanemaren. Proces iz nekog razloga ne `eli da

prima odre|enu vrstu signala, tako da mu operativni sistem nikada ni ne saop{ti da je signal postojao.

Page 36: UNIX Osnovne Komande2

2. Moska Modula-2 36

3) Signal mo`e biti zadr`an. Iz nekog razloga, proces ne `eli da obradi signal ~im on pristigne, ve} mo`da kasnije. Proces, ako `eli, mo`e da blokira signal i da ga nikada ne primi.

Svaki signal ima podrazumevanu dispoziciju. Naj~e{}a

podrazumevana dispozicija za signale je da proces prekine sa radom, ali ne uvek i ne obavezno. Podrazumevana dispozicija se, naravno, mo`e promeniti.

Svaki proces uz sebe ima dve promenqive tipa CARDINAL, koje su, zapravo, sekvence bitova. Prva promenqiva predstavqa bit-mapu pristiglih signala. Druga, koja se jo{ zove i maska, predstavqa bit-mapu signala koje je proces blokirao. Tre}a promenqiva vezana za signale je zapravo niz od 31 pokaziva~a, koji pokazuju na rutine za obradu pojedinih signala.

Ovde ne}e biti pomenuti svi signali, ve} samo neki, koji }e se

koristiti u primeru koji sledi. ♦ SIGHUP - terminal dodeqen procesu je iskqu~en. Podrazumevana

dispozicija je prekid rada procesa. ♦ SIGINT - pritisnuto je Ctrl+C na tastaturi. Podrazumevana

dispozicija je prekid rada procesa. ♦ SIGQUIT - pritisnuto je Ctrl+\ na tastaturi. Podrazumevana

dispozicija je prekid rada procesa. ♦ SIGFPE - pogre{na aritmeti~ka insturkcija. Podrazumevana

dispozicija je prekid rada procesa. ♦ SIGKILL - hitan prekid rada procesa. Ovaj signal ne mo`e biti

zadr`an niti zanemaren. Podrazumevana (i jedina) dispozicija je prekid rada procesa.

♦ SIGPIPE - prekinut pajp. Signal se {aqe procesu ako on poku{a da pi{e u pajp iz kojeg niko ne ~ita. Podrazumevana dispozicija je prekid rada procesa. O pajpovima }e biti vi{e re~i u poglavqu 3.7.

♦ SIGSTOP - zaustavqa proces dok ne primi signal SIGCONT. Ovaj signal ne mo`e biti zadr`an niti zanemaren. Podrazumevana (i jedina) dispozicija je prekid rada procesa.

♦ SIGCONT - nastavak rada procesa posle signala SIGSTOP. Ovaj signal predstavqa izuzetak: on mo`e biti poslat bilo kom procesu od strane bilo kog procesa. Podrazumevana dispozicija je nastavak rada procesa, ako je bio prekinut, ina~e je zanemarivawe.

♦ SIGCHLD - promena statusa procesa potomka. Proces roditeq mo`e da ~eka na ovaj signal pomo}u nekog od sistemskih poziva wait. Podrazumevana dispozicija je zanemarivawe; proces prima signal samo ako ~eka na wega.

Page 37: UNIX Osnovne Komande2

2. Moska Modula-2 37

Postoji mnogo sistemskih poziva za rad sa signalima. Ovde }e biti pomenuti samo neki, koji sasvim dobro ilustruju mogu}nosti rada sa signalima. PROCEDURE sigaction (Sig : INTEGER; Act, OldAct : PSigAction); PROCEDURE sigprocmask (How : INTEGER; Set, OldSet : PSigSet); PROCEDURE sigemptyset (Set : SigSet) : INTEGER; PROCEDURE sigaddset (Set : SigSet; SigNum : INTEGER) : INTEGER; Procedura sigaction defini{e akciju Act koja treba da se izvr{i po prispe}u signala Sig. Stara akcija se ~uva u OldAct. Ako se ovde prosledi NIL, stara akcija se ne}e sa~uvati. Procedura sigemptyset inicijalizuje na nulu bit-masku koja defini{e koji }e signali biti zadr`ani od strane procesa. Procedura sigaddset postavqa bit-masku za zadr`avawe signala SigNum. Procedura sigprocmask se koristi da se ispita ili promeni maska datog procesa. Koja }e se akcija izvr{iti, zavisi od vrednosti promenqive How; Set je nova maska, a u OldSet se ~uva stara maska. Dozvoqene vrednosti How su: How = 0 : signali u Set se dodaju na masku; How = 1 : signali u Set se izbacuju iz maske; How = 2 : signali u Set predstavqaju novu masku procesa.

Strukture podataka PSigSet, SigSet i SSigAction }e biti obja{wene na slede}em primeru. FOREIGN MODULE lib; (* Implemented by Sasa Popravak *) FROM SYSTEM IMPORT ADDRESS; FROM Signals IMPORT SigHandler, SigNum; TYPE PSigSet = POINTER TO SigSet; SigSet = POINTER TO LONGCARD; PSigAction = POINTER TO SSigAction; SSigAction = RECORD SaHandler : SigHandler; SaMask : SigSet; SaFlags : LONGCARD; SaRestorer : PROCEDURE (SigNum); END; PROCEDURE sigaction (Sig : INTEGER; Act, OldAct : PSigAction); PROCEDURE sigprocmask (How : INTEGER; Set, OldSet : PSigSet); PROCEDURE sigemptyset (Set : SigSet) : INTEGER; PROCEDURE sigaddset (Set : SigSet; SigNum : INTEGER) : INTEGER;

PROCEDURE waitpid (PID : INTEGER; Status : ADDRESS;

Page 38: UNIX Osnovne Komande2

2. Moska Modula-2 38

Options : INTEGER) : INTEGER; PROCEDURE execl (a1, a2, a3, a4, a5 : ADDRESS) : INTEGER; PROCEDURE fork () : INTEGER; END lib.

SigSet je, dakle, veoma jednostavna struktura; to je, zapravo, samo jedna promenqiva tipa LONGCARD, i predstavqa bit-mapu za signale. Struktura SSigAction je ne{to slo`enija. Od wenih poqa u ovom primeru bi}e nam zanimqiva samo prva dva poqa. Poqe SaHandler je tipa SigHandler, koji je zapravo proceduralni tip, a predstavqa rutinu koja }e se izvr{iti po prispe}u signala. Ono mo`e imati tri vrednosti:

SaHandler = 0 : signal se obra|uje po podrazumevanoj

dispoziciji; SaHandler = 1 : signal se zanemaruje; SaHandler = 2 : signal se zadr`ava. Poqe SaMask predstavqa masku procesa, t.j. signale koji }e biti

zadr`ani po prispe}u. Primer dat u nastavku radi slede}e: prvo ~eka na unos sa tastature,

zatim postavi dispoziciju signala SIGIGN i SIGQUIT na "zadr`an", i kreira nov proces. U novom procesu, izvr{ava se komanda operativnog sistema koja je uneta sa tastature, ali se prethodno vra}aju stare dispozicije signala. Po izvr{ewu komande, proces potomak zavr{ava sa radom. Za to vreme, proces roditeq ga ~eka, a potom i on vra}a stare dispozicije signala, i ponovo se vra}a na po~etak, t.j. ~eka na unos komande.

MODULE Shellcmd; (**) (* Implemented by Sasa Popravak *) FROM SYSTEM IMPORT ADR, ADDRESS; FROM Signals IMPORT signal, SigHandler, SIGINT, SIGQUIT, SIGCHLD; FROM InOut IMPORT WriteLn; FROM lib IMPORT SigSet, sigemptyset, sigaddset, waitpid, execl, sigaction, sigprocmask, SSigAction, fork; FROM Strings IMPORT String, EmptyString, Assign; FROM SysLib IMPORT read, exit;

CONST

Page 39: UNIX Osnovne Komande2

2. Moska Modula-2 39

BufSize = 64; SigIgn = 1; VAR Ignore, SaveInt, SaveQuit : SSigAction; s1, s2, s3, s4 : String; Status, p, PID : INTEGER; Mask, SaveMask : SigSet; Buf : ARRAY [1..BufSize] OF CHAR; BEGIN WHILE TRUE DO Status := read (0, ADR (Buf), BufSize); IF Status = 0 THEN WriteLn(); HALT; END; (* Set up a sigaction structure to ignore signals. *) Status := sigemptyset (ADR (Ignore.SaMask)); Ignore.SaHandler := SigHandler (SigIgn); Ignore.SaFlags := 0; (* Ignore keyboard signals; save old dispositions. *) sigaction (SIGINT, ADR (Ignore), ADR (SaveInt)); sigaction (SIGQUIT, ADR (Ignore), ADR (SaveQuit)); (* Start a child process. *) PID := fork (); IF PID = -1 THEN Status := -1; END; (* This code is executed by child process. *) IF PID = 0 THEN (* Restore signals to their original dispositions, and restore the signal mask. *) sigaction (SIGINT, ADR (SaveInt), NIL); sigaction (SIGQUIT, ADR (SaveQuit), NIL); (* Execute a shell with the command as argument. *) EmptyString (s1); EmptyString (s2); EmptyString (s3); EmptyString (s4); Assign (s1, "/bin/sh"); Assign (s2, "sh"); Assign (s3, "-c"); Assign (s4, Buf); Status := execl (ADR (s1), ADR (s2), ADR (s3), ADR (s4), NIL); exit (127); END; (* Wait for child to finish. *) WHILE (waitpid (PID, ADR (Status), 0) < 0) DO (* EINTR (interrupted system call) is okay, otherwise we

we got some error that we need to report back.

Page 40: UNIX Osnovne Komande2

2. Moska Modula-2 40

*) END; (* Restore signals to their original dispositions, and restore the signal mask. *) sigaction (SIGINT, ADR (SaveInt), NIL); sigaction (SIGQUIT, ADR (SaveQuit), NIL); END; END Shellcmd. Primer izvr{avawa: # Shellcmd Unesi komandu : ls IOLib.c IOLib.d IOLib.md IOLib.o IOLib.r Makefile Shellcmd Shellcmd.ddd Shellcmd.mi Shellcmd.mi~ Shellcmd.o Shellcmd.r lib.c lib.d lib.md lib.md~ lib.o lib.r shellcmd.tar Unesi komandu : ^C #

Signali SIGINT i SIGQUIT se kod procesa roditeqa zanemaruju iz slede}eg razloga. Pretpostavimo da smo, prilikom izvr{avaqa procesa potomka stisnuli neki od tastera za prekid rada. Po{to se po pritisku tih tastera generi{e signal, on se prosledi svim procesima koji poti~u sa tog terminala, bez obzira da li su trenutno aktivni, ili rade u pozadini. Ovako, pritiskom na te tastere prekinu}emo rad samo potomka, ali ne i roditeqa, jer dok roditeq ~eka na dete u petqi sa wait, on ignori{e signale. Me|utim, dok se ~eka na unos znaka sa tastature, roditeq mo`e biti prekinut, i upravo to je na~in da okon~amo rad programa. Da su procedure za zanemarivawe signala inicijalizovane pre ~ekawa na tastaturi, program ne bi mogao biti prekinut.

Page 41: UNIX Osnovne Komande2

2. Moska Modula-2 41

Prilikom inicijalizacije poqa SaHandler na "zanemarivawe", nije dovoqno samo dodeliti mu vrednost 1, jer se radi o proceduralnom tipu. Upravo zato je pre toga izvr{ena eksplicitna konverzija u tip SigHandler.

U ovom programu je kori{}en jo{ i sistemski poziv waitpid, koji je ne{to op{tiji nego wait, a za argumente ima PID procesa potomka kojeg ~ekamo da se okon~a, status u kojem potomak vra}a status, i options kao razne opcije, koje u ovom slu~aju nisu upotrebqene.

Ako bismo `eleli da zadr`imo neki signal, npr. SIGCHLD, bilo bi

potrebno uraditi slede}e. Kod prvog poziva sigaction ubacili bismo slede}i deo koda:

Status := sigemptyset (ADR (Mask)); Status := sigaddset (ADR (Mask), SIGCHLD);

sigprocmask (0, ADR (Mask), ADR (SaveMask)); Ovim smo postavili dispoziciju signala SIGCHLD na "zadr`an".

Zatim bismo u procesu potomku posle restauracije starih dispozicija pisali:

sigprocmask (2, ADR (SaveMask), NIL); I na kraju, posle restauracije starih dispozicija kod procesa

roditeqa, pisali bismo to isto: sigprocmask (2, ADR (SaveMask), NIL);

3.3. EVIDENCIJE I ZA[TITE

3.3.1. Chown i Chmod U UNIX-u, svaki fajl ima svog vlasnika i svoju grupu kojima pripada. Svaki fajl uz sebe ima identifikacione brojeve vlasnika (UID) i grupe (GID) kojima pripadaju, kao i nekoliko rezervisanih bita koji slu`e kao indikator {ta korisnik mo`e da radi sa fajlom. Ovi bitovi se nazivaju dozvole pristupa fajlu, i ima ih tri: dozvola za ~itawe, dozvola za pisawe i dozvola za izvr{avawe fajla. U zavisnosti od korisnika koji pristupa fajlu, postoje tri grupe ovih bitova: dozvole pristupa za vlasnika, za grupu i za sve ostale. Ovde }emo pomenuti nekoliko sistemskih poziva koji slu`e za modifikaciju ovih brojeva i bitova. Pre svega, tu je sistemski poziv za mewawe pripadnosti fajla: PROCEDURE chown( path : ADDRESS (* pointer to string *);

owner, group : CARDINAL );

Page 42: UNIX Osnovne Komande2

2. Moska Modula-2 42

Ovde path pokazuje na konstantan string koji ozna~ava pathname fajla, a owner i group su identifikacioni brojevi novog vlasnika i nove grupe fajla. Ovde treba napomenuti da ovaj sistemski poziv ne}e raditi u slu~aju linkova, ve} tada treba koristiti poziv lchown sa istim argumentima. Ako se chown pozove za link, on }e promeniti vlasnika i grupu za fajl na koji link pokazuje, a ne za sam link. Sistemski poziv za mewawe dozvola pristupa fajlu je PROCEDURE chmod( path : ADDRESS (* pointer to stirng *); c : CARDINAL ); Ovde path ima isto zna~ewe kao i malopre, a c je oktalna konstanta koja predstavqa nove dozvole pristupa fajlu. Ova tri sistemska poziva mo`e da izvr{i samo super user. 3.3.2. SETUID i SETGID bitovi

Pored navedenih bitova, svaki fajl ima pri sebi jo{ tri rezervisana bita. To su SETUID (set-user-ID) bit, SETGID (set-group-ID) bit i sticky bit. UNIX ima jednu veoma zanimqivu mogu}nost. Naime, pomo}u prva dva bita mogu}e je fajlu, odnosno procesu kojem je fajl pridru`en dodeliti neke dodatne privilegije.

Pre nego {to pre|emo na detaqnije obja{wewe ovih bitova, potrebno je upoznati se sa jo{ dve veli~ine koje svaki proces poseduje. To su efektivni UID i GID, tj. EUID i EGID. Dok se UID i GID koriste da bi se odredili korisnik i grupa kojima dati proces pripada, EUID i EGID se koriste da bi se odredile dozvole pristupa za proces. Procesov UID i GID se postavqaju na UID i GID procesa koji ga je kreirao - na primer, kada korisnik startuje neki program, kreira se proces koji dobija UID i GID od korisnika koji ga je startovao. Ovo se de{ava u slu~aju kada bitovi SETUID i SETGID od izvr{nog fajla nisu setovani. EUID i EGID se tako|e postavqaju na UID i GID, ali se kasnije mogu izmeniti.

Kada neki korisnik pozove program sa setovanim SETUID bitom, za vreme trajawa tog procesa procesov EUID se postavi na UID vlasnika pozvanog izvr{nog fajla. Ova osobina se veoma ~esto koristi da se obi~nim korisnicima dozvoli da izvr{e programe sa super user privilegijama, {to ina~e ne bi bilo mogu}e. Na primer, prilikom kreirawa direktorijuma, tj. poziva programa mkdir, pozva}e se funkcija mknod, koja je dozvoqena samo za super user-a. Tako, ako se rutini za kreirawe direktorijuma mkdir setuje SETUID bit, obi~ni korisnici mo}i }e da izvr{e mknod, mada samo u okviru mkdir, i sa veoma velikim restrikcijama. Ako mkdir ne bi imao setovan SETUID bit, obi~ni korisnici ne bi mogli da ga pozovu. Ova pravila analogno va`e i za SETGID bit.

Naravno, pri radu sa ovim bitovima treba biti veoma obazriv; wih treba koristiti samo ako ste potpuno sigurni da nema drugog na~ina da obavite posao koji ste naumili. Tre}i pomenuti bit nam u daqem

Page 43: UNIX Osnovne Komande2

2. Moska Modula-2 43

razmatrawu ne}e biti posebno zanimqiv, pa ga ne}emo detaqnije razja{wavati.

Proces mo`e da promeni UID/GID i EUID/EGID na dva na~ina. Prvi je da pozove program koji ima setovane SETUID/SETGID bitove, s tim da }e se tu promeniti samo EUID/EGID. Drugi na~in je da koristi odre|ene sistemske pozive. Sistemski pozivi za mewawe UID i GID jesu: PROCEDURE setuid( uid : CARDINAL ) : INTEGER; PROCEDURE setgid( gid : CARDINAL ) : INTEGER; PROCEDURE seteuid( euid : CARDINAL ) : INTEGER; PROCEDURE setegid( egid : CARDINAL ) : INTEGER;

Ovde su uid/euid, odnosno gid/egid novi UID/EUID, odnosno GID/EGID procesa koji je trenutno aktivan. Obe funkcije vra}aju nulu ako je sve proteklo kako treba, a -1 u slu~aju gre{ke. Ove sistemske pozive mo`e da koristi samo super user. Analogno navedenim, postoje i sistemski pozivi koji daju informaciju o UID/EUID, odnosni GID/EGID. To su: PROCEDURE getuid( ) : CARDINAL; PROCEDURE getgid( ) : CARDINAL; PROCEDURE geteuid( ) : CARDINAL; PROCEDURE getegid( ) : CARDINAL; Svaka od funkcija vra}a navedenu veli~inu. 3.3.3. Umask

Pri kreirawu ili otvarawu fajla, uvek se moraju navesti i dozvole pristupa. Me|utim, one se kao takve ne koriste direktno, ve} se sa wima i komplementom jedne vrednosti koja se zove umask, izvr{i operacija "AND". Umask pripada procesu koji je pozvao neku od ove dve operacije, i predstavqa jednostavan niz bitova koji }e se sigurno iskqu~iti u privilegijama fajla koji otvaramo ili kreiramo. Na primer, ako je mod fajla dat sa 0666, a umask sa 022 (vrednosti su oktalne), ima}emo: actual_mode := mode & ~umask; actual_mode := 0666 & ~022; actual_mode := 0666 & 0755; actual_mode := 0644;

Procesov umask mo`emo modifikovati pomo}u sistemskog poziva umask: PROCEDURE umask( cmask : CARDINAL ) : CARDINAL;

cmask je ovde nova vrednost umask-a, a funkcija vra}a staru vrednost.

Page 44: UNIX Osnovne Komande2

2. Moska Modula-2 44

3.4. FAJL SISTEM I RAD SA FAJLOVIMA

Jedan od razloga zbog kojih je UNIX postao toliko popularan je i wegov veoma dobro isprojektovan i realizovan fajl sistem. UNIX-ov fajl sistem je hijerarhijskog tipa, podr`an je rad sa velikim brojem fajl sistema, pristup raznim hardverskim ure|ajima je fleksibilan i veoma pojednostavqen uvo|ewem posebne vrste fajlova koji su vezani za ure|aje, itd. Pored osnovnih sistemskih poziva za rad sa fajlovima, ovde }e biti opisani i osnovni koncepti UNIX-ovog fajl sistema.

Svaki fajl u okviru jednog fajl sistema ima sebi pridru`en jedan broj koji se naziva i-broj. Ovaj broj ga jednozna~no identifikuje u okviru datog fajl sistema. Ovaj broj se koristi kao indeks u odre|enoj tabeli (odatle i naziv i-broj), gde se pristupa tzv. i-~voru, koji predstavqa strukturu koja sadr`i sve podatke o fajlu (veli~inu, tip, vlasnika, grupu, dozvole pristupa, i t.d.)

Kada neki proces otvori fajl, on je tada u tom procesu jednozna~no predstavqen jednim celim brojem, tzv. fajl deskriptorom (engl. file descriptor). Svaki put kada taj proces na neki na~in pristupi fajlu preko sistemskih poziva, pristupi}e mu pomo}u fajl deskriptora, a ne preko wegovog imena. U jednom procesu, na jedan fajl mo`e da pokazuje vi{e razli~itih fajl deskriptora. Ovo mo`e biti korisno kada iz nekog razloga fajl u okviru jednog procesa treba koristiti na razli~ite na~ine U UNIX-u postoji nekoliko vrsta fajlova. Tri osnovne vrste fajlova jesu: ♦ Obi~ni fajlovi - su najjednostavniji objekti u fajl sistemu. U wima

mo`e biti sme{teno bilo {ta; operativni sistem to ne interpretira ni na koji na~in. UNIX ne name}e nikakav format obi~nim fajlovima; oni se tretiraju jednostavno kao niz bajtova, i oni se mogu ~itati i pisati po voqi korisnika. Svakako, odre|eni programi o~ekuju ta~an format nekih fajlova, ali to se odnosi na nivo korisnika, a ne operativnog sistema.

♦ Posebni fajlovi (device files) - predstavqaju jedan od najneobi~nijih aspekata UNIX-a. Svaki U/I ure|aj je povezan sa najmawe jednim ovakvim fajlom. Da bi se pristupilo ure|aju, program otvori poseban fajl i ~ita/pi{e podatke, kao da se radi o obi~nom fajlu. Razlika izme|u obi~nih i posebnih fajlova je u tome {to kada se poseban fajl ~ita/pi{e, hardverski ure|aj koji mu je dodeqen ne{to radi. Postoje dve vrste posebnih fajlova: znakovni i blokovski fajlovi. Prvi su dosta sli~ni obi~nim fajlovima, jer jednostavno prenose podatke izme|u programa i ure|aja znak po znak, bez obzira na to u kojim ih jedinicama program koristi. Drugi su, opet, baferisani od strane operativnog sistema u slede}em smislu: ako program, recimo, ~ita jedan znak iz blok-posebnog fajla, operativni sistem nala`e ure|aju da prebaci blok

Page 45: UNIX Osnovne Komande2

2. Moska Modula-2 45

podataka (obi~no neki umno`ak 512 bajta) u memoriju, i potom zadovoqava programski zahtev. Po{to program zadovoqi svoje potrebe, od ure|aja se zahteva slede}i blok. Sli~no tome, ako se `eli pisati na ure|aj, operativni sistem baferi{e podatke u veli~inu jednog bloka, i {aqe ih na ure|aj.

♦ Direktorijumi - su osnova za hijerarhijsku strukturu UNIX-ovog fajl sistema. Oni sadr`e odre|en broj fajlova, kao i druge direktorijume. Kao i obi~ni fajlovi, i direktorijumi su samo niz bajtova, naravno sa smislenim formatom, i oni se mogu ~itati kao i bilo koji drugi fajl. Me|utim, program ne mo`e da pi{e u direktorijum, jer je to posao obezbe|en samo za operativni sistem. Za svaki fajl sistem, odr`ava se jedan osnovni direktorijum, tzv. root. On slu`i kao koren za hijerarhiju fajl sistema. Svaki fajl je podre|en svom root-u; do bilo kog fajla u fajl sistemu mo`e se do}i navo|ewem lanca direktorijuma, koji uvek po~iwe sa root-om, i koji ga jednozna~no odre|uje (ovaj lanac se naziva pathname). Svaki direktorijum u sebi obavezno ima dve stavke: . i .. . . ukazuje na sam direktorijum; ovo omogu}ava programima da otvaraju svoj teku}i direktorijum za ~itawe bez znawa path-a. .. ukazuje na nadre|eni direktorijum. Program mo`e da se "pro{eta" do root-a otvaraju}i redom .., sve dok se do root-a ne stigne. .. u root direktorijumu pokazuje na samog sebe.

Pored osnovnih, postoje jo{ ~etiri vrste fajlova: ♦ Tvrdi linkovi - mogu}e je imati vi{e od jednog imena koja ukazuju na

jedan isti fajl, i to upravo pomo}u linkova. Link se stvara tako {to se otvori nova stavka u direktorijumu, sa novim imenom i novim i-brojem. Me|utim, po{to i-broj jednozna~no identifikuje fajl samo u okviru datog fajl sistema, nemogu}e je napraviti hard link izme|u dva fajl sistema.

♦ Simboli~ki linkovi - razre{uju dati problem tako {to umesto i-broja fajla sadr`e pathname fajla, koji ga jednozna~no odre|uje u okviru kompletne hijerarhije fajl sistema. Link mo`e da sadr`i i apsolutni i relatvni pathname fajla, i od toga zavisi u odnosu na {ta se posmatra ciqni fajl linka.

♦ FIFO-i - zovu se i imenovani pajpovi. Oni se koriste za me|uprocesnu komunikaciju. Program kreira FIFO koriste}i posebnu bibliote~nu rutinu. Po{to je kreiran, FIFO-u mogu pristupiti i drugi procesi, ba{ kao da je obi~an fajl. Kada se ~ita/pi{e, podaci se prosle|uju direktno iz/u proces koji ga je kreirao, a nikada na disk ili sa diska. Kada proces koji ga je kreirao nestane, FIFO se vi{e ne mo`e koristiti. Me|utim, on ostaje kao fajl sve dok se eksplicitno ne ukloni.

♦ UNIX-Domain Sockets - mawe-vi{e imaju istu upotrebu kao i FIFO-i, osim {to im se mora pristupati posebnim setom sistemskih poziva (istim kao i kod me|ura~unarske komunikacije pod Internet-Domain Sockets). 3.4.1. Osnovni sistemski pozivi za rad sa fajlovima

Page 46: UNIX Osnovne Komande2

2. Moska Modula-2 46

UNIX, kao i svi drugi operativni sistemi, pru`a veoma velik izbor rutina za rad sa fajlovima. Ovde }emo navesti samo neke od wih. Tri osnovna sistemska poziva za rad sa fajlovima su: PROCEDURE open( path : ADDRESS (* pointer to string *);

flags : CARDINAL; mode : CARDINAL) : INTEGER; PROCEDURE create( path : ADDRESS (* pointer to string *);

mode : CARDINAL ) : INTEGER; PROCEDURE close( fd : INTEGER ) : INTEGER; Funkcija open otvara fajl, ukoliko on postoji na disku. Funkcija create kreira novi fajl ako on ve} ne postoji, a ako postoji, i ako ima dozvolu za pisawe, on se bri{e i otvara se novi fajl. Funkcija close zatvara fajl. Ovde je path pokaziva~ na string koji predstavqa pathname fajla, mode predstavqa dozvole pristupa, na koji se logi~ki "enduje" vrednost umask (vidi poglavqe 3.3.3.), a flags skup flegova koji ozna~avaju kako `elimo da otvorimo fajl: za ~itawe, za pisawe, za dopisivawe, i sl. Vrednosti ovih flegova date su u primeru koji sledi. Prve dve funkcije vra}aju fajl deskriptor, ako su operacije izvr{ene uspe{no, a -1 u suprotnom. fd kod tre}e funkcije predstavqa upravo taj fajl deskriptor, dok ona kao svoj rezultat vra}a samo indikator o uspe{nosti operacije. Slede}a dva sistemska poziva, bez kojih bi rad sa fajlovima bio nemogu}, su: PROCEDURE read( fd : INTEGER;

buf : ADDRESS (* pointer to array of byte *); nbytes : INTEGER ) : INTEGER;

PROCEDURE write( fd : INTEGER; buf : ADDRESS (* pointer to array of byte *); nbytes : INTEGER ) : INTEGER;

Funkcija read ~ita nbytes bajtova iz fajla sa fajl deskriptorom fd, i sme{ta ih na adresu buf. Funkcija write pi{e nbytes bajtova iz bafera sa adresom buf u fajl sa fajl deskriptorom fd. Obe funkcije vra}aju broj pro~itanih, odnosno napisanih bajtova. Ako `elimo da fajlu pristupimo na ta~no odre|enoj poziciji, koristi}emo sistemski poziv lseek: PROCEDURE lseek( fd : INTEGER; offset : INTEGER; whence : INTEGER ) : INTEGER; Ovde je fd fajl deskriptor fajla, offset nova pozicija pristupa, a whence pozicija od koje se offset ra~una. Dozvoqene vrednosti su: whence = 0 : pozicija se ra~una od po~etka fajla; whence = 1 : pozicija se ra~una od teku}e pozicije; whence = 2 : pozicija se ra~una od kraja fajla.

Page 47: UNIX Osnovne Komande2

2. Moska Modula-2 47

Ovde treba obratiti pa`wu da, ako poziciju ra~unamo od kraja fajla, offset mora biti negativan.

3.4.2. Link i Symlink Da bi se napravio link, koriste se slede}a dva poziva: PROCEDURE link( existing : ADDRESS (* pointer to string *);

new : ADDRESS (* pointer to string *) ) : INTEGER; PROCEDURE symlink( existing : ADDRESS (* poniter to string *);

new : ADDRESS (* pointer to string *) ) : INTEGER; Ovde je existing adresa koja pokazuje na string koji predstavqa pathname do fajla na koji `elimo da kreiramo link, a new je adresa koja pokazuje na string koji predstavqa ime linka. link kreira hard link, a symlink simboli~ki link. Obe funkcije vra}aju -1 u slu~aju gre{ke, a ina~e vra}aju nulu.

3.4.3. Stat

Sistemski poziv stat se koristi da bi se dobile osnovne informacije o fajlu: kojeg je tipa, koje su mu dozvole pristupa, koliko je velik, kada je posledwi put modifikovan, kada mu je pristupano, itd. PROCEDURE stat( path : ADDRESS (* pointer to string *);

st : ADDRESS (* pointer to structure Stat *)) : INTEGER; Ovde je path pokaziva~ na string koji predstavqa pathname fajla. Funkcija vra}a uobi~ajeni indikator gre{ke. Ako path pokazuje na link, onda treba koristiti sistemski poziv lstat, sa istim argumentima. st je pokaziva~ na jednu posebnu strukturu Stat, koja }e biti obja{wena na slede}em primeru. Program demonstrira rad sistemskog poziva stat: FOREIGN MODULE lib; (* Implemented by Sasa Popravak *) FROM SYSTEM IMPORT ADDRESS; TYPE SIGNED = INTEGER; UNSIGNED = CARDINAL; timeT = LONGINT; clockT = LONGINT; uidT = SHORTCARD; gidT = SHORTCARD; devT = SHORTCARD; inoT = LONGCARD; modeT = SHORTCARD;

umodeT = SHORTCARD;

Page 48: UNIX Osnovne Komande2

2. Moska Modula-2 48

nlinkT = SHORTCARD; offT = LONGINT; Stat = RECORD stDev : devT; pad1 : SHORTCARD; stIno : inoT; stMode : umodeT; stNlink : nlinkT; stUid : uidT; stGid : gidT; stRdev : devT; pad2 : SHORTCARD; stSize : offT; stBlksize: LONGCARD; stBlocks : LONGCARD; stAtime : timeT; unused1 : LONGCARD; stMtime : timeT; unused2 : LONGCARD; stCtime : timeT; unused3 : LONGCARD; unused4 : LONGCARD; unused5 : LONGCARD; END; tms = RECORD utime : clockT; stime : clockT; cutime : clockT; cstime : clockT; END; CONST (* flags for open *) oTRUNC = 01000B; (* open with truncation *) oAPPEND = 02000B; (* append, i.e writes at the end *) oRDWR = 02B; (* open for reading and writing *) oWRONLY = 01B; (* open for writing only *) oRDONLY = 0B; (* open for reading only *) (* file access permisson flags (for create and umask) *) pXUSID = 04000B; (* set user ID on execution *) pXGRID = 02000B; (* set group ID on execution *) pSTEXT = 01000B; (* save text image after execution *) pROWNER = 0400B; (* read by owner *) pWOWNER = 0200B; (* write by owner *) pXOWNER = 0100B; (* execute by owner *) pRGROUP = 040B; (* read by group *) pWGROUP = 020B; (* write by group *) pXGROUP = 010B; (* execute by group *)

pROTHERS = 04B; (* read by others *)

Page 49: UNIX Osnovne Komande2

2. Moska Modula-2 49

pWOTHERS = 02B; (* write by others *) pXOTHERS = 01B; (* execute by others *) pEMPTY = 0B; (* no flag set *) (* file access check flags (for access) *) cREAD = 04H; (* check if readable *) cWRITE = 02H; (* check if writable *) cEXEC = 01H; (* check if executable *) cEXISTS = 0H; (* check existance *) PROCEDURE stat (path: ADDRESS; buf : ADDRESS) : SIGNED; END lib. Kao {to se na primeru vidi, Stat u sebi sadr`i osnovne podatke o fajlu. Program koji koristi ovaj modul izgleda ovako: MODULE Stat; (* Implemented by Sasa Popravak *) FROM Arguments IMPORT ArgTable, GetArgs; FROM lib IMPORT Stat, stat; FROM InOut IMPORT WriteString, WriteLn, WriteInt, Write, WriteCard; FROM SYSTEM IMPORT ADR, ADDRESS; FROM Strings IMPORT String, EmptyString, Assign; VAR Status : INTEGER; argc : SHORTCARD; argv : ArgTable; st : Stat; c : CARDINAL; s : String; BEGIN (* Collect argument(s). *) GetArgs (argc, argv); EmptyString (s); IF argc = 1 THEN WriteString ("Missing argument. Aborting..."); WriteLn; HALT; END; Assign (s, argv^[1]^);

Status := stat (ADR (s), ADR (st));

Page 50: UNIX Osnovne Komande2

2. Moska Modula-2 50

WriteString (" File Name: "); WriteString (s); WriteLn; WriteString (" File Type: "); c := st.stMode; (* Determine file type. See manual pages for details. *) IF BITSET (c) * BITSET (00170000B) = BITSET (0100000B) THEN WriteString ("regular file."); ELSIF BITSET (c) * BITSET (00170000B) = BITSET (0140000B) THEN WriteString ("socket."); ELSIF BITSET (c) * BITSET (00170000B) = BITSET (0120000B) THEN WriteString ("symbolic link."); ELSIF BITSET (c) * BITSET (00170000B) = BITSET (0060000B) THEN WriteString ("block device."); ELSIF BITSET (c) * BITSET (00170000B) = BITSET (0040000B) THEN WriteString ("directory."); ELSIF BITSET (c) * BITSET (00170000B) = BITSET (0020000B) THEN WriteString ("character device."); ELSIF BITSET (c) * BITSET (00170000B) = BITSET (0010000B) THEN WriteString ("fifo."); END; WriteLn; WriteString (" File Size: "); WriteInt (st.stSize, 1); WriteString (" bytes, "); WriteCard( CARDINAL( st.stBlocks ), 1 ); (* WriteLngCard (st.stBlocks); *) WriteString (" blocks."); WriteLn; WriteString (" Optimum I/O Unit: "); WriteCard( CARDINAL( st.stBlksize ), 1 ); (* WriteLngCard (st.stBlksize); *) WriteLn; WriteString (" Device Numbers: "); WriteInt (st.stRdev, 1); WriteLn; (* Find about permissions. See documentation for details. *) WriteString (" Permission bits: "); c := st.stMode; (* For owner. *) IF BITSET (c) * BITSET (00400B) # BITSET (0) THEN Write ('r'); ELSE Write ('-'); END; IF BITSET (c) * BITSET (00200B) # BITSET (0) THEN Write ('w'); ELSE Write ('-');

END;

Page 51: UNIX Osnovne Komande2

2. Moska Modula-2 51

IF BITSET (c) * BITSET (00100B) # BITSET (0) THEN Write ('x'); ELSE Write ('-'); END; (* For group. *) IF BITSET (c) * BITSET (00400B DIV 8) # BITSET (0) THEN Write ('r'); ELSE Write ('-'); END; IF BITSET (c) * BITSET (00200B DIV 8) # BITSET (0) THEN Write ('w'); ELSE Write ('-'); END; IF BITSET (c) * BITSET (00100B DIV 8) # BITSET (0) THEN Write ('x'); ELSE Write ('-'); END; (* For aliens. *) IF BITSET (c) * BITSET (00400B DIV 64) # BITSET (0) THEN Write ('r'); ELSE Write ('-'); END; IF BITSET (c) * BITSET (00200B DIV 64) # BITSET (0) THEN Write ('w'); ELSE Write ('-'); END; IF BITSET (c) * BITSET (00100B DIV 64) # BITSET (0) THEN Write ('x'); ELSE Write ('-'); END; (* Display and ordinal for rights. *) Write (' '); Write ('('); WriteCard (CARDINAL (BITSET (c) * BITSET (07777B)), 1); Write (')'); WriteLn; WriteString (" Inode Number: "); WriteCard( CARDINAL( st.stIno ), 1 ); (* WriteLngCard (st.stIno); *) WriteLn; WriteString (" Owner User-ID: "); WriteCard (st.stUid, 1); WriteLn; WriteString (" Owner Group-ID: ");

WriteCard (st.stGid, 1);

Page 52: UNIX Osnovne Komande2

2. Moska Modula-2 52

WriteLn; WriteString (" Link Count: "); WriteCard (st.stNlink, 1); WriteLn; WriteString (" Last Access: "); WriteCard( CARDINAL( st.stAtime ), 1 ); (* WriteLngCard (st.stAtime); *) WriteLn; WriteString (" Last Modification: "); WriteCard( CARDINAL( st.stMtime ), 1 ); (* WriteLngCard (st.stMtime); *) WriteLn; WriteString ("Last I-Node Change: "); WriteCard( CARDINAL( st.stCtime ), 1 ); (* WriteLngCard (st.stCtime); *) WriteLn; END Stat. Primer izvr{avawa: # Stat Stat.mi File Name: Stat.mi File Type: regular file. File Size: 4378 bytes, 10 blocks. Optimum I/O Unit: 4096 Device Numbers: 0 Permission bits: rw-r--r-- (420) Inode Number: 176740 Owner User-ID: 0 Owner Group-ID: 0 Link Count: 1 Last Access: 889735412 Last Modification: 889735410 Last I-Node Change: 889735410 #

Program je u osnovi veoma jednostavan, po{to samo o~itava {ta smo dobili u Stat strukturi posle sistemskog poziva. Maska koja se koristi prilikom odre|ivawa tipa fajla i vrednosti koje treba da se dobiju, mogu se pogledati u man stat. 3.4.4. Dup i Dup2 Posledwa dva sistemska poziva koja }emo pomenuti u vezi sa fajlovima su:

Page 53: UNIX Osnovne Komande2

2. Moska Modula-2 53

PROCEDURE dup( fd : INTEGER ) : INTEGER; PROCEDURE dup2( fd1 : INTEGER; fd2 : INTEGER ) : INTEGER; Sistemski poziv dup vra}a novi fajl deskriptor koji pokazuje na isti fajl na koji pokazuje fajl deskriptor fd. Sistemski poziv dup2 postavqa fajl deskriptor fd2 da pokazuje na isti fajl kao i fajl deskriptor fd1. Ako fd2 ve} pokazuje na neki otvoren fajl, on se prethodno zatvori. Ovi sistemski pozivi bi}e ilustrovani u poglavqu 3.7.

3.5. DIREKTORIJUMI

Kao {to je ve} napomenuto, UNIX-ov fajl sistem je hijerarhijskog tipa. Ako `elimo da pristupimo nekom drugom fajl-sistemu, prvo ga je potrebno ukqu~iti u hijerarhiju UNIX-ovog fajl-sistema. Ovaj postupak se naziva mauntovawe (engl. mounting). Mauntovawe se vr{i pomo}u sistemskog poziva mount: PROCEDURE mount( dev_name : ADDRESS; dir_name : ADDRESS; type : ADDRESS; flags : LONGCARD ) : INTEGER;

Ovde je dev_name pokaziva~ na string koji predstavqa ime hardverskog ure|aja sa kojeg se mauntovawe vr{i, dir_name pokaziva~ na string koji predstavqa ime direktorijuma na koji se mauntovawe vr{i, type pokaziva~ na string koji predstavqa tip fajl-sistema koji se mauntuje, a flags razni flegovi. Kada se fajl-sistem mauntuje, cela wegova struktura se ukqu~uje u strukturu fajl-sistema na koji se mauntuje. dir_name predstavqa prazan direktorijum koji }e postati novi korenski direktorijum mauntovanog fajl-sistema. type je ime mauntovanog fajl-sistema: ext2, msdos...

Kada se zavr{i rad sa mauntovanim fajl-sistemom, potrebno ga je iskqu~iti iz osnovne strukture fajl-sistema. Ovo se vr{i pomo}u sistemskog poziva umount: PROCEDURE umount( dev_name : ADDRESS (* pointer to string *)) : INTEGER;

Ovde je dev_name pokaziva~ na string koji predstavqa ime ure|aja sa kojeg je dati fajl-sistem mauntovan. Obe funkcije kao svoj rezultat vra}aju indikator o uspehu izvr{avawa operacije. Mo`e da ih izvr{i samo super user. Sistemski poziv za promenu radnog direktorijuma je chdir: PROCEDURE chdir( path : ADDRESS (* pointer to string *) ) : INTEGER;

Page 54: UNIX Osnovne Komande2

2. Moska Modula-2 54

Ovde je path pokaziva~ na string koji predstavqa pathname novog radnog direktorijuma, a funkcija vra}a uobi~ajen indikator o gre{ki. Direktorijum se bri{e pomo}u sistemskog poziva rmdir: PROCEDURE rmdir( path : ADDRESS (* pointer to string *) ) : INTEGER; Ovde je path pokaziva~ na string koji predstavqa pathname direktorijuma koji se bri{e, a funkcija vra}a uobi~ajen indikator o gre{ki. Direktorijum se mo`e obrisati samo ukoliko je prazan, i ukoliko na wega nema linkova. Direktorijum se kreira pomo}u sistemskog poziva mkdir: PROCEDURE mkdir( path : ADDRESS (* pointer to string *);

mode : CARDINAL ) : INTEGER;

Ovde je path pokaziva~ na string koji predstavqa pathname direktorijuma koji se kreira, mode dozvole pristupa, a funkcija vra}a uobi~ajen indikator o gre{ki. Dozvole pristupa se dobiju tako {to nad mode i umask aktivnog procesa izvr{i operacija "AND" (vidi poglavqe 3.3.). Pre nego {to po~nemo da radimo sa direktorijumom, potrebno ga je otvoriti. Ovo se ~ini pomo}u sistemskog poziva opendir: PROCEDURE opendir( name : ADDRESS (* pointer to string *) ) : ADDRESS; DirEnt = RECORD dIno : CARDINAL; dOff : CARDINAL; dRecLen : SHORTCARD; dName : ARRAY [1..256] OF CHAR; END; DIR = RECORD ddFd : INTEGER; ddLoc : INTEGER; ddSize : INTEGER; d_Buff : DirEnt; END;

name je pokaziva~ na string koji predstavqa pathname direktorijuma, a funkcija vra}a pokaziva~ na strukturu DIR, koja je prakti~no deskriptor direktorijuma, i koja sadr`i nekoliko poqa, od kojih }e nam ovde biti zanimqivo samo poqe d_buff, koje je tipa DirEnt. DirEnt je struktura koja sadr`i osnovne podatke o stavki u direktorijumu kojeg ~itamo. Direktorijum je, zapravo, niz ovakvih struktura, koje predstavqaju fajlove. Struktura DirEnt u sebi sadr`i ~etiri poqa (vidi slede}i primer) : broj i-~vora odgovaraju}eg fajla, ofset stavke u odnosu na po~etak direktorijuma, du`inu stavke i ime fajla kojeg stavka predstavqa.

Page 55: UNIX Osnovne Komande2

2. Moska Modula-2 55

Stavke u direktorijumu se ~itaju pomo}u sistemskog poziva readdir: PROCEDURE readdir( DirEntry : ADDRESS (* pointer to string *) ) : ADDRESS; DirEntry je ovde pokaziva~ na promenqivu koja sadr`i deskriptor otvorenog direktorijuma, a tipa je DIR. readdir vra}a pokaziva~ na slede}u stavku u direktorijumu. Direktorijum se zatvara sistemskim pozivom closedir: PROCEDURE closedir( dp : ADDRESS (* pointer to string *) ) : INTEGER;

dp je pokaziva~ na deskriptor direktorijuma, a funkcija vra}a indikator o uspe{nosti operacije.

3.6. TERMINALI Terminal je ure|aj za komunicirawe sa mati~nim ra~unarom. Postoje tri osnovna moda rada terminala: ♦ Cooked mode - "kuvani" mod, kod kojeg se terminalski ulaz obra|uje po

linijama. Kraj linije se ozna~ava sa ASCII LF ili ASCII EOT. Tako|e, omogu}eno je i brisawe znakova, pa i cele linije, po potrebi. U ovom modu, sa ulaza je mogu}e generisati i odre|ene signale sa tastature, u zavisnosti od kombinacije pritisnutih tastera, koji se daqe prosle|uju svim procesima u istoj grupi. Na kraju, omogu}ena je i obrada izlaznih znakova, npr. pretvarawe tabova u praznine, pretvarawe velikih slova u mala, itd.

♦ Raw mode - "sirovi" mod, kod kojeg se ulaz obra|uje znak po znak. Znaci se odmah po unosu prosle|uju procesu koji ~eka na wih, bez ikakve daqe obrade. Generisawe signala i eventualna ispravka gre{aka nisu omogu}eni.

♦ CBreak mode - "polukuvani" mod, kod kojeg je onemogu}ena obrada ulaza po linijama, ali je omogu}eno generisawe signala sa tastature, kao i obrada izlaznih znakova.

Sistemski poziv za upravqawe radom terminala je ioctl:

PROCEDURE ioctl( fd : INTEGER; cmd : INTEGER; arg : ADDRESS ) : INTEGER;

Page 56: UNIX Osnovne Komande2

2. Moska Modula-2 56

fd je fajl deskriptor terminala sa kojim se radi, cmd je komanda koju `elimo da izvr{imo, a arg je pokaziva~ na odre|enu strukturu podataka, koja mo`e biti razli~itog tipa i koja zavisi od komande cmd. Komande koje mogu da se proslede se uglavnom odnose na razli~ite atribute datog terminala, na wihovo postavqawe, mewawe ili o~itavawe.

3.7. ME\UPROCESNA KOMUNIKACIJA

UNIX je vi{eprocesni (engl. multitasking) operativni sistem, {to zna~i da pod wim u isto vreme mo`e da se izvr{ava vi{e procesa istovremeno. Naravno, veoma ~esto se javqa potreba za komunikacijom izme|u procesa, tako da postoji vi{e na~ina da se ona realizuje. Ovde }e biti pomenuta dva osnovna na~ina me|uprocesne komunikacije pod UNIX-om: pomo}u pajpova i pomo}u FIFO-a. Pajpovi (cevi) jesu interfejs izme|u dva procesa. Oni predstavqaju poseban par deskriptora, koji su povezani sa procesima, a ne sa fajlovima. Kada proces A pi{e u svoj pajp deskriptor, proces B mo`e da ~ita iz wega, i obratno. Kada se pajp kreira, postoji veoma malo razlika izme|u pajp deskriptora i fajl deskriptora.

3.7.1. Popen i Pclose Osnovni sistemski pozivi za rad sa pajpovima jesu: PROCEDURE popen( command : ADDRESS (* pointer to string *);

type : ADDRESS (* pointer to string *) ) : ADDRESS; PROCEDURE pclose( stream : ADDRESS (* pointer to string *) ) : INTEGER; Funkcija popen otvara pajp izme|u procesa koji ju je pozvao i komande operativnog sistema na koju pokazuje adresa command. type je tip pajpa: w ako je pajp za pisawe, a r ako je za ~itawe. Funkcija kao svoj rezultat vra}a pokaziva~ na fajl. Ako do|e do gre{ke, vra}a se NIL. Funkcija pclose zatvara pajp na koji pokazuje stream. Pritom, pclose poziva sistemski poziv waitpid, da bi sa~ekali da se proces potomak zavr{i. Kao svoj rezultat, ova funkcija vra}a izlazni status procesa potomka. Ilustrova}emo ova dva sistemska poziva na sli~nom primeru kao i sistemski poziv system. Poveza}emo pajpom program i komandu date, da bismo saznali koji je danas dan. FOREIGN MODULE lib; (* Implemented by Sasa Popravak *) FROM SYSTEM IMPORT ADDRESS; TYPE

Page 57: UNIX Osnovne Komande2

2. Moska Modula-2 57

PFD = ARRAY [1..2] OF INTEGER; PROCEDURE fgets (s : ADDRESS; Size : INTEGER; Stream : ADDRESS) : ADDRESS; PROCEDURE popen (Command : ADDRESS; Type : ADDRESS) : ADDRESS; PROCEDURE pclose (Stream : ADDRESS) : INTEGER; END lib. U programu se koristi jo{ i sistemski poziv fgets, koji iz fajla stream u~itava Size bajtova, i stavqa ih u bafer na adresi s. Program izgleda ovako: MODULE Popen; (* Implemented by Sasa Popravak *) FROM InOut IMPORT WriteLn, WriteString; FROM lib IMPORT fgets, popen, pclose; FROM SYSTEM IMPORT ADR, ADDRESS; FROM Strings IMPORT String, EmptyString, Assign; CONST BufLen = 10; TYPE DayNames = RECORD fullname : String; (* Full day name *) abbrev : String; (* and short version *) END; (* Whole week. *) DaysArray = ARRAY [1..7] OF DayNames; VAR Status : INTEGER; s1, s2 : String; Days : DaysArray; adr : ADDRESS; pf : ADDRESS; i : CARDINAL; d : DaysArray; a : ARRAY [1..BufLen] OF CHAR; (* As Wirth created Modula-2 without having constant arrays or records this procedure is needed to set record fields in an array ("acting" CONST). *)

Page 58: UNIX Osnovne Komande2

2. Moska Modula-2 58

PROCEDURE Init (VAR d : DaysArray); BEGIN d [1].abbrev := "Sun"; d [1].fullname := "Sunday"; d [2].abbrev := "Mon"; d [2].fullname := "Monday"; d [3].abbrev := "Tue"; d [3].fullname := "Tuesday"; d [4].abbrev := "Wed"; d [4].fullname := "Wednesday"; d [5].abbrev := "Thu"; d [5].fullname := "Thursday"; d [6].abbrev := "Fri"; d [6].fullname := "Friday"; d [7].abbrev := "Sat"; d [7].fullname := "Saturday"; END Init; (* Compare first three bytes of two strings. *) PROCEDURE Equal (a, b : ADDRESS) : BOOLEAN; VAR i : CARDINAL; BEGIN FOR i := 0 TO 2 DO IF CHAR (a^) # CHAR (b^) THEN RETURN FALSE; ELSE (* I just looove this :)) *) INC (a); INC (b); END; END; RETURN TRUE; END Equal; BEGIN (* Create "CONST" array of records ... *) Init (d); EmptyString (s1); EmptyString (s2); Assign (s1, "date"); Assign (s2, "r"); (* Open a pipe to the date command. We'll be reading from the pipe. *) pf := popen (ADR (s1), ADR (s2)); IF pf = NIL THEN WriteString ("Popen error. Aborting..."); WriteLn; HALT; END; (* Read one line of output from the pipe. *) adr := fgets (ADR (a), 10, pf); IF adr = NIL THEN WriteString ("No output from date command. Aborting..."); WriteLn;

HALT;

Page 59: UNIX Osnovne Komande2

2. Moska Modula-2 59

END; (* For each day, see if it matches the output from the date command. *) FOR i := 1 TO 7 DO IF Equal (ADR (d [i].abbrev), ADR (a)) THEN WriteString ("Today is "); WriteString (d [i].fullname); ELSE WriteString ("Today is not "); WriteString (d [i].fullname); END; WriteLn; END; (* Close the pipe and pick up the command's termination status. *) Status := pclose (pf); IF Status = -1 THEN WriteString ("Pclose error. Aborting..."); WriteLn; HALT; END; END Popen. Primer izvr{avawa: # Popen Today is not Sunday Today is not Monday Today is Tuesday Today is not Wednesday Today is not Thursday Today is not Friday Today is not Saturday #

Kada se pozove popen, ako je sve pro{lo kako treba, u~ita se prvih 10 znakova koje je u pajp upisala komanda date. Zatim se prva tri znaka (po{to oni predstavqaju dan u sedmici) upore|uju sa skra}enicama dana, i vr{i se odgovaraju}i ispis.

3.7.2. Pipe popen je, me|utim, veoma neefikasan sistemski poziv, iz istih

razloga kao i system. Umesto wega, uvek je boqe koristiti sistemski poziv pipe: PROCEDURE pipe( fd : ARRAY OF INTEGER ) : INTEGER;

Page 60: UNIX Osnovne Komande2

2. Moska Modula-2 60

Ova funkcija kreira dva fajl deskriptora; fd[0] je otvoren za ~itawe, a fd[1] za pisawe. Dva fajl deskriptora su povezana kao pajp: podaci napisani u fd[1] se mogu ~itati iz fd[0].

Sistemski poziv pipe ilustrova}emo na primeru.

FOREIGN MODULE lib; (* Implemented by Aleksandar Popovic *) FROM SYSTEM IMPORT ADDRESS; PROCEDURE fork() : INTEGER; PROCEDURE pipe( fd : ARRAY OF INTEGER ) : INTEGER; PROCEDURE cuserid( buf : ADDRESS ) : ADDRESS; PROCEDURE execl( a1, a2, a3, a4 : ADDRESS ) : INTEGER; PROCEDURE close( fd : INTEGER ); PROCEDURE dup2( fd1, fd2 : INTEGER ); PROCEDURE waitpid( pid : INTEGER; status : ADDRESS; options : INTEGER ); PROCEDURE write( fd : INTEGER; buf : ADDRESS; nbytes : INTEGER ); END lib.

Ovde se koristi i sistemski poziv cuserid, koji vra}a ime korisnika koji je pozvao proces.

MODULE dup; (* Implemented by Aleksandar Popovic *) FROM SYSTEM IMPORT ADDRESS, ADR; FROM InOut IMPORT WriteString, WriteLn; FROM lib IMPORT fork, write, cuserid, dup2, close, pipe, waitpid, execl; FROM Strings IMPORT String, EmptyString, Assign; VAR pid : INTEGER; pfd : ARRAY [0..1] OF INTEGER; i, status : INTEGER; username : ADDRESS; a1, a2, a3 : String; BEGIN username := cuserid( NIL ); IF username = NIL THEN WriteString( "Koj si sad pa ti?" );

Page 61: UNIX Osnovne Komande2

2. Moska Modula-2 61

WriteLn(); WriteString( "Abortiram..." ); WriteLn(); HALT; END; IF pipe( pfd ) < 0 THEN WriteString( "Ne mogu da otvorim cevku. Abortiram..." ); WriteLn(); HALT; END; pid := fork(); IF pid < 0 THEN WriteString( "Ne mogu da se porodim. Abortiram..." ); WriteLn(); HALT; END; (* dete, bre! *) IF pid = 0 THEN dup2( pfd[0], 0 ); close( pfd[1] ); EmptyString( a1 ); EmptyString( a2 ); EmptyString( a3 ); Assign( a1, "/bin/mail" ); Assign( a2, "mail" ); Assign( a3, "root" ); status := execl( ADR( a1 ), ADR( a2 ), ADR( a3 ), NIL ); IF status = -1 THEN WriteString( "Auuu, ne mogu da se execlujem. Abortiram..." ); WriteLn(); HALT; END; END; (* roditelj... *) close( pfd[0] ); EmptyString( a1 ); Assign( a1, "Ja sam ja, Jeremija,\n" ); write( pfd[1], ADR( a1 ), 21 ); EmptyString( a1 ); Assign( a1, "prezivam se Krstic.\n" ); write( pfd[1], ADR( a1 ), 20 ); EmptyString( a1 ); Assign( a1, "Selo mi je Toponica,\n" ); write( pfd[1], ADR( a1 ), 21 ); EmptyString( a1 ); Assign( a1, "drvena mi dvokolica,\n" ); write( pfd[1], ADR( a1 ), 21 ); EmptyString( a1 ); Assign( a1, "sluzio sam stari kadar,\n" );

write( pfd[1], ADR( a1 ), 23 );

Page 62: UNIX Osnovne Komande2

2. Moska Modula-2 62

EmptyString( a1 ); Assign( a1, "artiljeriju!\n\n" ); write( pfd[1], ADR( a1 ), 14 ); close( pfd[1] ); waitpid( pid, ADR( status ), 0 ); END dup.

Program kreira proces potomak, koji izvr{ava komandu mail, a proces roditeq {aqe poruku. Po{to mail ~ita sa standardnog ulaza, proces potomak koristi dup2 da preusmeri svoj standardni ulaz na pajpovu stranu za ~itawe. Po{to ne}e pisati u pajp, potomak zatvara pfd[1]. Proces roditeq zatvara pfd[0] po{to ne}e ~itati pajp, i zatim ispisuje nekoliko poruka procesu potomku. Potom on zatvara pfd[1], i ~eka da potomak zavr{i sa radom. Zatvarawe pfd[1] od strane roditeqa je za proces potomak indikacija da je stigao kraj poruke. Obzirom da su procesi u UNIX-u te{ki, pajpovi predstavqaju veoma pogodno sredstvo za komunikaciju izme|u procesa. Na slede}em primeru bi}e ilustrovana op{ta procedura za uspostavqawe komunikacije dva procesa preko pajpa. Neka je potrebno da proces koji pi{e rezultate svog rada na standardni izlaz, rezultate zapravo prosle|uje direktno drugom procesu. Drugi proces, koji ina~e podatke ~ita sa standardnog ulaza, sada treba da preuzima podatke direktno od prvog procesa. Komunikaciju izme|u dva procesa ostvari}emo postavqawem pajpa izme|u wih, i to tako da ni prvi ni drugi proces ne moramo mewati. Prvi proces }e i daqe "misliti" da pi{e na standardni izlaz (a pisa}e ih, zapravo, u pajp), a drugi }e, analogno, "misliti" da svoje podatke preuzima sa standardnog ulaza (a preuzima}e ih, zapravo, iz pajpa). Primer je dat u pseudokodu. ... pipe( ADR( fd ) ); (* kreira se pajp *) IF fork() <> 0 THEN close( fd[0] ); (* proces 1 nece citati iz pajpa *) close( STD_OUTPUT ); (* pripremi se za novi standardni izlaz *) dup( fd[1] ); (* postavi novi standardni izlaz na pajp *) close( fd[1] ); (* pajp nam vise ne treba *) execl( process1 ); ELSE close( fd[1] ); (* proces 2 nece pisati u pajp *) close( STD_INPUT ); (* pripremi se za novi standardni ulaz *) dup( fd[0] ); (* postavi novi standardni ulaz na pajp *) close( fd[0] ); (* pajp nam vise ne treba *) execl( process2 ); END; ...

Na samom po~etku, kreira se pajp, kojem su pridru`ena dva fajl deskriptora: jedan za pisawe u pajp, a drugi za ~itawe iz wega. Potom se kreira proces potomak. U procesu roditequ }e se izvr{iti fajl process1, a u potomku process2. Po{to process1 i process2 ne znaju da im je

Page 63: UNIX Osnovne Komande2

2. Moska Modula-2 63

standardni ulaz, odnosno standardni izlaz zapravo pajp, neophodno je a`urirati fajl deskriptore pre pozivawa fajlova, tako da za process1 standardni izlaz bude strana pajpa za pisawe, a da za process2 standardni ulaz bude strana pajpa za ~itawe.

Tako, proces roditeq, kada na wega do|e red da se izvr{i, zatvara fajl deskriptor za ~itawe pajpa, po{to mu on ne}e biti potreban. Zatim preusmerava standardni izlaz na fajl deskriptor za pisawe u pajp, pa potom zatvara pajp, jer mu on vi{e nije potreban. Na samom kraju, poziva se program process1.

Analogno tome, proces potomak, kada na wega do|e red da se izvr{i, zatvara fajl deskriptor za pisawe u pajp, zatvara standardni ulaz da bi ga pripremio za preusmeravawe, postavqa standardni ulaz na fajl deskriptor za ~itawe iz pajpa, i zatvara pajp, jer mu on vi{e ne treba. Na kraju se poziva program process2.

3.7. FIFO-i Komunikacija me|u procesima ostvarena preko pajpova ima jedan

veoma ozbiqan nedostatak. Naime, dva procesa mogu da komuniciraju preko pajpa samo ako su me|usobno povezani, u smislu da je jedan potomak drugog, ili obrnuto. Da bi se uspostavila komunikacija izme|u dva procesa koji nisu povezani, uveden je pojam FIFO-a (engl. First In - First Out, ili prvi unutra - prvi napoqe), ili imenovanog pajpa. Za wega je vezana stavka u fajl sistemu, koja se kreira u isto vreme kada se kreira i sam FIFO. Me|utim, kada se FIFO zatvori, stavka vezana za wega ostaje u fajl sistemu sve dok se eksplicitno ne izbri{e. FIFO se mo`e i ~itati i pisati od strane istog procesa, za razliku od pajpa; on uspostavqa punu komunikaciju izme|u dva procesa. Sistemski pozivi za rad sa wim su istovetni kao i za rad sa obi~nim fajlovima; jedina razlika je u sistemskom pozivu za kreirawe. FIFO se kreira pomo}u sistemskog poziva mkfifo: PROCEDURE mkfifo( path : ADDRESS (* pointer to string *);

mode : CARDINAL ) : INTEGER; path i mode imaju uobi~ajeno zna~ewe, kao i rezultat koji funkcija vra}a. Rad sa FIFO-ima ilustrova}emo na jednostavnom primeru. Neka imamo dva procesa: klijent i server, i neka klijent preko FIFO-a ne{to pi{e serveru. Server to jednostavno ~ita i prikazuje na ekranu. MODULE FIFOClient; (* Implemented by Sasa Popravak *) FROM SYSTEM IMPORT ADR, ADDRESS; FROM SysLib IMPORT open, close, read, write;

FROM Strings IMPORT

Page 64: UNIX Osnovne Komande2

2. Moska Modula-2 64

String, EmptyString, Assign, Append; FROM InOut IMPORT WriteString, WriteLn; (* We accept max BufLen characters. *) CONST BufLen = 1024; VAR n, c, fd : INTEGER; Buf : ARRAY [1..BufLen] OF CHAR; s1 : String; BEGIN EmptyString (s1); Assign (s1, "FIFO"); (* Open the FIFO for writting. It was created by the server. *) fd := open (ADR (s1), 1); IF fd = -1 THEN WriteString ("Open error. Aborting..."); WriteLn; HALT; END; (* Read from standard input and copy the data to the FIFO. *) n := read (0, ADR (Buf), BufLen); WHILE n > 0 DO c := write (fd, ADR (Buf), n); n := read (0, ADR (Buf), BufLen); END; (* Close the FIFO. *) c := close (fd); END FIFOClient. MODULE FIFOServer; (* Implemented by Sasa Popravak *) FROM SYSTEM IMPORT ADR, ADDRESS; FROM SysLib IMPORT open, close, read, write, unlink, system; FROM Strings IMPORT String, EmptyString, Assign, Append; FROM InOut IMPORT WriteString, WriteLn; (* We accept max BufLen characters. *) CONST BufLen = 1024; VAR s1, s2, s3, s4 : String;

Page 65: UNIX Osnovne Komande2

2. Moska Modula-2 65

n, fd, c : INTEGER; Buf : ARRAY [1..BufLen] OF CHAR; BEGIN EmptyString (s1); Assign (s1, "FIFO"); (* Remove any previous FIFO. *) n := unlink (ADR (s1)); (* Create the FIFO. *) EmptyString (s1); Assign (s1, "/usr/bin/mkfifo -m 0666 FIFO"); (* Note: system is used to avoid creating lib.o library in c. Insted, we use standard Mocka SySLib. It's less efficient, though. *) n := system (ADR (s1)); IF n = -1 THEN WriteString ("System/mkfifo error. Aborting..."); WriteLn; HALT; END; (* Open the FIFO for reading. *) EmptyString (s1); Assign (s1, "FIFO"); fd := open (ADR (s1), 0); IF fd = -1 THEN WriteString ("Open error. Aborting..."); WriteLn; HALT; END; (* Read from the FIFO until EOF and print what we got on stdout. *) n := read (fd, ADR (Buf), BufLen); WHILE n > 0 DO c := write (1, ADR (Buf), n); n := read (fd, ADR (Buf), BufLen); END; (* Close FIFO. *) c := close (fd); (* Remove the mess. *) n := unlink (ADR (s1)); END FIFOServer. Server prvo mora da izbri{e sve prethodne FIFO-e sa sistemskim pozivom unlink, pa tek potom poziva mkfifo da stvori novi. Ovo nije zaista neophodno, ali obezbe|uje da FIFO ima odgovaraju}e dozvole pristupa i vlasnika.