Giter VIP home page Giter VIP logo

os_lab1's Introduction

os_lab1

PREKIDI I SIGNALI

Upute za laboratorijske vježbe


SIGNALI

Signali na razini procesa (pokrenutog programa) su analogni mehanizam sklopovskim prekidima na razini procesora. Služe za obradu nekih asinkronih događaja. Osnovna ideja je kao i kod prekida: proces nešto svoje radi dok se u nekom (neočekivanom) trenutku ne dogodi nešto što treba odmah obraditi. Stoga se pri primitku signala trenutni posao prekida, obrađuje se signal, te nastavlja s prekinutim poslom. Signal ne sadrži dodatne informacije (osim broja signala) - ako su one potrebne, treba ih dohvatiti u obradi signala. Signal procesu može poslati jezgra operacijska sustava (npr. SIGSEGV), drugi proces (npr. SIGTERM) ili proces sam sebi (npr. SIGALRM uz odgodu ili neki drugi događaj). Proces može programirati svoje ponašanje za signal: - može ga prihvatiti i obraditi pretpostavljenom funkcijom (većinom to znači prekid procesa) - može ga prihvatiti i obraditi funkcijom zadanom u programu (u programu je definirano što će se obaviti po primitku takvog signala) - može ga se zadržati (zapamtiti, ali ne i odmah obraditi) - može ga se ignorirati (odbaciti bez obrade). Izuzetak od navedenih pravila je SIGKILL koji ubija proces (SIGKILL ignorira postavke koje je program postavio). 

Kada se prihvati signal, pozove se funkcija za obradu signala. Slično kao i kod prekida na razini procesora, i pri prihvatu signala zabranjuje se daljnje prekidanje, ali samo s tim signalom - drugi signali mogu prekinuti tu obradu. Po završektu obrade ponovno se dozvoljava prekidanje s tim signalom te se eventualno zadržani signali (došli za vrijeme obrade) sada propuštaju. Signali koji se procesu upute za vrijeme obrade prethodnog signala istog tipa - isti broj, stavljaju se u red i čekaju. S time da se pamti samo po jedan signal istog tipa. Primjerice, ako procesu za vrijeme obrade signala SIGINT dođu još tri takva signala, zapamtit će se samo prvi takav signal. Po završetku obrade prvog signala SIGINT ponovno će se pozvati ista funkcija, ali samo jednom (uz prepostavku da za vrijeme ove druge obrade nije došao novi signal SIGINT).

Signali su standardni mehanizam na UNIX operacijskim sustavima i njemu sličnim (npr. Linux). Operacijski sustavi Windows imaju minimalnu podršku za signale i u mnogočemu su različiti (zapravo se oni ne koriste).

Signali i sučelja za upravljanje signalima

Moderne implementacije UNIX-a definiraju oko tridesetak signala. Ovdje je pregled samo istaknutijih signala, dok potpun popis daje man -s 3HEAD signal:

SIGINT (2)

(interrupt) "prekid", može ga se poslati programu sa Ctrl-C

SIGQUIT (3)

(quit) "završi (zbog nekih problema) može ga se poslati programu sa Ctrl+\ (na nekim HR tipkovnicama sa Ctrl+Ž)

SIGALRM (14)

(alarm) koristi se prilikom korištenja funkcije sleep

SIGTERM (15)

(terminate) traži se od procesa da završi s radom (na redoviti način)

SIGKILL (9)

(kill) traži se od operacijskog sustava da prekine navedeni proces kome se signal šalje

Simbolička imena signala nalaze se u biblioteci signal.h.

U nastavku su prikazane "starije" i jednostavnije funkcije za rad sa signalima (upravo zato jer su jednostavnije). Međutim, pri "ozbiljnom" korištenju signala treba razmotriti korištenje modernija sucelja (sigaction, pthread_kill, pthread_sigmask).
 

Funkcija sigset( signal, obrada_signala )

Funkcija definira što ce se zbiti prilikom primitka određenog signala (maskira signal). Argument signal je broj signala (npr. SIGINT). Drugi argument je kazaljka na funkciju i može biti:

  • SIG_DFL - (default) pretpostavljeno ponašanje za taj signal (za vecinu signala to znaci uništavanje procesa)
  • SIG_IGN - (ignore) ignoriranje signala
  • SIG_HOLD - (hold) signal se zapamti, ali ne obraduje odmah - obradit ce se onda kada se definicija ponašanja za taj signal promijeni (npr. kasniji poziv sigset)
  • obrada_signala - kazaljka na funkciju za obradu signala.

Funkcija sigset vraća prethodno ponašanje procesa za navedeni signal (ili adresu funkcije kojom se signal obrađivao).

void obrada_signala( int signal );

Funkcija za obradu signala treba primiti (minimalno) jedan parametar - broj signala, po kojem se u funkciji može odrediti koji je signal uzrok poziva te funkcije.

Funkcije sighold( signal ) i sigrelse( signal )

Funkcijama sighold i sigrelse može se zabraniti, odnosno omogućiti prekidanje nekim signalom.
Primjerice, ako je potrebno jedan dio koda zaštiti od prekidanja nekim signalom, taj kod se može ograditi sa  sighold i
sigrelse. Takoder, ako je u funkciji obrade signala potrebno ponovno dozvoliti prekidanje i unutar te funkcije, opet se mogu koristiti te funkcije.

Funkcija kill( pid, signal )

Funkcijom kill šalje se signal signal procesu s identifikacijskim brojem pid. pid procesa se može vidjeti i naredbom ps.
U ljusci postoji istoimena naredba kill -signal pid koja radi isto (šalje signal procesu). Ukoliko treba ubiti neki proces može se to učiniti naredbom kill -SIGKILL pid (ili kill -9 pid).

Funkcija pause()

Funkcija zaustavlja rad procesa dok se njemu ne pošalje bilo koji signal. Po primitku signala, najprije se obrađuje taj signal, a potom nastavlja s programom koji slijedi iza pause.

Funkcija alarm( t )

Funkcija alarm(t) programira alarm koji će nakon t sekundi procesu poslati signal SIGALRM. Ako se alarm pozove prije nego li se prethodno postavljeni alarm aktivirao, prethodni se poništava (prepisuje se novim). Ako je t=0, prethodno postavljeni alarm (ako je bilo takvog) se poništava.

Funkcija sleep( t )

Namjena funkcije sleep(t) je odgoditi izvođenje programa za t sekundi. Medutim, funkcija će biti prekinuta bilo kojim signalom te, nakon obrade pristiglog signala, program nastavlja nakon poziva sleep (i odgoda će u tom slučaju biti kraća), a povratna vrijednost će biti broj "neprospavanih" sekundi.
Primjerice, ako se 5 sekundi nakon poziva sleep(100) procesu pošalje neki signal (koji se brzo obradi), program će nastaviti s izvođenjem instrukcija nakon funkcije sleep već nakon tih 5 sekundi, tj. neće spavati još 95 nakon obrade signala! Međutim, funkcija sleep će vratiti vrijednost 95 pa se ta vrijednost može iskoristiti za dodatnu odgodu:

a = sleep(100);
while( (a = sleep( a )) > 0 );

Odgoda s mogučnošću veće preciznosti je funkcija nanosleep(t). Postoji i funkcija usleep(us) (mikrosekunde), ali se njeno korištenje ne preporuča (smatra se zastarjelom).

Umjesto funkcije sigset može se koristiti i naprednija funckija sigaction. Opis te funkcije dan je i kratkim primjerom.

Kostur programa koji poziva zadanu funkciju prilikom primitka signala SIGINT dan je sljedecim kodom:

#include <stdio.h>
#include <signal.h>

void prekidna_rutina(int sig)
{
   /* obrada prekida */
}

int main (void)
{
   sigset (SIGTSTP, prekidna_rutina);

   printf("Poceo osnovni program PID=%d\n", getpid());

   /* troši vrijeme da se ima šta prekinuti - 10 s */

   printf ("Zavrsio osnovni program\n");

   return 0;
}

Vježba 1: Signali

Zadatak

Računati proste brojeve te preko signala periodički ispisivati status. Koristiti setitimer sučelje za periodički alarm (vidjeti Primjer periodičke obrade pri dnu stranice). Na signal SIGINT privremeno zaustaviti rad na idućim brojevima (programski ostvariti zaustavljanje), odnosno, nastaviti s radom ako je program prethodno bio zaustavljen. Na signal SIGTERM ispisati zadnji broj koji se provjerava (ili će biti idući) i završiti s radom.

Skica rješenja:

pauza = 0;
broj = 1000000001;
zadnji = 1000000001;

periodicki_ispis () { ispisi ( zadnji ); }

postavi_pauzu () { pauza = 1 - pauza; }

prekini () { ispisi ( zadnji ); izadji_iz_programa (); }

glavna_funkcija () { povezi_signale_s_funkcijama; // na signal SIGTERM pozovi funkciju prekini() postavi_periodicki_alarm; // svakih 5 sekundi pozovi funkciju periodicki_ispis();

ponavljaj { ako je ( prost ( broj ) == DA ) zadnji = broj; broj++; dok je ( pauza == 1 ) pauziraj (); } }

/* sa kill -SIGINT/SIGTERM/SIGSTOP/SIGCONT pid ispitati rad */

Provjera je li broj prost može se obaviti jednostavnim kodom, npr. prema:
int prost ( unsigned long n ) {
unsigned long i, max;

if ( ( n &amp; 1 ) == 0 ) /* je li paran? */
	return 0;

max = sqrt ( n );
for ( i = 3; i &lt;= max; i += 2 )
	if ( ( n % i ) == 0 )
		return 0;

return 1; /* broj je prost! */

}

Primjer kako bi trebao izgledati ispis programa (ako se izvorna datoteka zove lab1.c):
$ gcc lab1.c -lm -o lab1
$ ./lab1
zadnji prosti broj = 1000139111
zadnji prosti broj = 1000279801
zadnji prosti broj = 1000420261
^Czadnji prosti broj = 1000478719    (stisnut Ctrl+C)
zadnji prosti broj = 1000478719
zadnji prosti broj = 1000478719      (stisnut [Ctrl]+[] tj. [Ctrl]+[Ž])
^\Quit (core dumped)
$
(Tekst u zagradama ne ispisuje program već se samo opisuju korisnikove radnje.)
Primjer periodičke obrade

Mnoge operacije na UNIX sustavima se oslanjaju na signale. Primjerice, jedan od načina periodičke obrade može se ostvariti korištenjem signala, ne izravno već korištenjem sučelja koje periodički šalje signal procesu, a na koji se može pozvati potrebna funkcija.

Idući primjer, itimer_primjer.c, prikazuje takav program.

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/time.h>

void periodicki_posao ( int sig ) { printf ( "Radim periodicki posao\n" ); }

int main () { struct itimerval t;

/* povezivanje obrade signala SIGALRM sa funkcijom "periodicki_posao" */
sigset ( SIGALRM, periodicki_posao );

/* definiranje periodičkog slanja signala */
/* prvi puta nakon: */
t.it_value.tv_sec = 0;
t.it_value.tv_usec = 500000;
/* nakon prvog puta, periodicki sa periodom: */
t.it_interval.tv_sec = 0;
t.it_interval.tv_usec = 500000;

/* pokretanje sata s pridruženim slanjem signala prema "t" */
setitimer ( ITIMER_REAL, &amp;t, NULL );

while (1)
	pause (); /* pauzira do primitka bilo kojeg signala */

return 0;

}

/* prevodjenje i pokretanje:

  • $ gcc itimer_primjer.c -o itimer_primjer
  • $ ./itimer_primjer
  • Radim periodicki posao
  • Radim periodicki posao
  • Radim periodicki posao
  • ...
  • ^C
  • (Ctrl+C prekida izvodjenje)
  • isprobati pokrenuti te s naredbom kill mu poslati signale:
    • SIGINT, SIGTERM, SIGKILL, SIGSTOP, SIGCONT
  • npr. nakon pokretanja, u drugoj konzoli napraviti:
  • $ ps -a
  • PID TTY TIME CMD
  • 3232 pts/0 00:00:00 itimer_primjer
  • 3233 pts/6 00:00:00 ps
  • $ kill -SIGTERM 3232
  • u prvoj konzoli će program biti prekinut s porukom "Terminated" */

Vježba 1: Prekidi i signali

UNIX ne dozvoljava pojedinom korisniku izravno korištenje prekida procesora. Stoga prekide treba simulirati koristeći signale koje jezgra operacijskog sustava šalje procesima.

Zadatak

Napisati dva programa:

  • obrada - program koji omogućava obradu prekida s više razina/prioriteta (simulira ponašanje sustava opisanog u 3. poglavlju i to bez sklopa za prihvat prekida)
  • generator_prekida - program koji generira signale i šalje ih prvom procesu

Svaki program pokrenuti u svojoj ljusci.

Struktura prekidne rutine dana je sljedećim pseudokodom:

prekidna_rutina  /* pokreće se pojavom signala uz zabranu daljih prekida */
{
   odredi uzrok prekida, tj. indeks i;
   OZNAKA_ČEKANJA[i] = 1;
   ponavljaj {
      /* odredi signal najveceg prioriteta koji ceka na obradu */
      x = 0;
      za j = TEKUćI_PRIORITET + 1 do N radi {
         ako je (OZNAKA_ČEKANJA[j]<>0) tada {
            x = j;
         }
      }
      /* ako postoji signal koji ceka i prioritetniji je od trenutnog posla, idi u obradu */
      ako je (x > 0) tada {
         OZNAKA_ČEKANJA[x] = 0;
         PRIORITET[x] = TEKUćI_PRIORITET;
         TEKUćI_PRIORITET = x;
         omogući prekidanje;
         obrada_prekida(x);
         zabrani prekidanje;
         TEKUćI_PRIORITET = PRIORITET[x];
      }
   } dok je (x > 0);
} 

UPUTA

Sklopovski prekid u jednoj razini simulira se slanjem određene vrste signala. Nakon toga će se prekinuti izvođenje programa, zabraniti dalje prekidanje, i pozvati funkcija za obradu signala koja simulira prekidnu rutinu.

Osim izravno preko tipkovnice, proces može dobiti signal do drugog procesa (funkcija kill(pid,sig)). Također, iz komandne linije se naredbom kill može poslati signal nekom od procesa (npr. kill -SIGINT 12345).

Na početku prekidne rutine prvo treba zabraniti daljnje prekidanje. Kako se koristi više signala, na osnovu signala koji je uzrokovao prekid treba odrediti razinu prioriteta prekida i. Prekidna rutina mora biti funkcija s jednim cjelobrojnim parametrom i mora biti najavljena u glavnom programu za svaki signal koji se prihvaća naredbom:

sigset (SIGNAL, prekidna_rutina);

Program treba moći prihvatiti i obraditi pet različitih signala (odabrati iz skupa signala) s time da prekid SIGINT treba biti najveće razine.  Razine prioriteta se kreću od 1 do 5 s time da veći broj označava veći prioritet.

Zabrana prekida signalom SIGNAL simulira se naredbom sighold(SIGNAL), a omogućavanje prekida simulira se naredbom: sigrelse(SIGNAL);

Budući da se ovdje ista funkcija koristi za obradu više prekida funkcije sighold i sigrelse treba pozvati za svaki od signala (više uzastopnih poziva)! Zbog toga je zgodno te pozive grupirati u dvije funkcije: zabrani_prekidanje() i dozvoli_prekidanje(), kao u kosturu rješenja.

Obrada prekida ne mora ništa korisno raditi, već samo treba trajati neko vrijeme. Umjesto dugih petlji, može poslužiti petlja s naredbom sleep(1).

Kostur rješenja programa za obradu prekida dan je sljedećim kodom:

#include <stdio.h>
#include <signal.h>

	
#define N 6    /* broj razina proriteta */

	
int OZNAKA_CEKANJA[N];
int PRIORITET[N];
int TEKUCI_PRIORITET;

	

	
int sig[]={SIGUSR1, SIGUSR2, ..., SIGINT};
void zabrani_prekidanje(){
   int i;
   for(i=0; i<5; i++)
      sighold(sig[i]);
}
void dozvoli_prekidanje(){
   int i;
   for(i=0; i<5; i++)
      sigrelse(sig[i]);
}

	
void obrada_signala(int i){
   /* obrada se simulira trošenjem vremena,
      obrada traje 5 sekundi, ispis treba biti svake sekunde */
}
void prekidna_rutina(int sig){
   int n=-1;
   zabrani_prekidanje();
   switch(sig){
      case SIGUSR1: 
         n=1; 
         printf("- X - - - -\n");
         break;
      case SIGUSR2: 
         n=2; 
         printf("- - X - - -\n");
         break;
      ...
   }
   OZNAKA_CEKANJA[n]=1;
   ponavljaj{
      ...
      dozvoli_prekidanje();
<pre style="margin-top: 0cm; margin-right: 0cm; margin-left: 0cm; margin-bottom: 0.0001pt; font-size: 10pt; font-family: &#39;Courier New&#39;; "> &nbsp;    obrada_prekida(n);</pre>
<pre style="margin-top: 0cm; margin-right: 0cm; margin-left: 0cm; margin-bottom: 0.0001pt; font-size: 10pt; font-family: &#39;Courier New&#39;; "><font color="#FF0000">      zabrani_prekidanje();</font></pre>
<pre style="margin-top: 0cm; margin-right: 0cm; margin-left: 0cm; margin-bottom: 0.0001pt; font-size: 10pt; font-family: &#39;Courier New&#39;; ">      ...</pre>
<pre style="margin-top: 0cm; margin-right: 0cm; margin-left: 0cm; margin-bottom: 0.0001pt; font-size: 10pt; font-family: &#39;Courier New&#39;; ">   }</pre>
   dozvoli_prekidanje();
<pre style="margin-top: 0cm; margin-right: 0cm; margin-left: 0cm; margin-bottom: 0.0001pt; font-size: 10pt; font-family: &#39;Courier New&#39;; ">}</pre>
<pre style="margin-top: 0cm; margin-right: 0cm; margin-left: 0cm; margin-bottom: 0.0001pt; font-size: 10pt; font-family: &#39;Courier New&#39;; ">&nbsp;</pre>
<pre style="margin-top: 0cm; margin-right: 0cm; margin-left: 0cm; margin-bottom: 0.0001pt; font-size: 10pt; font-family: &#39;Courier New&#39;; ">int main ( void )</pre>
<pre style="margin-top: 0cm; margin-right: 0cm; margin-left: 0cm; margin-bottom: 0.0001pt; font-size: 10pt; font-family: &#39;Courier New&#39;; ">{</pre>
<pre style="margin-top: 0cm; margin-right: 0cm; margin-left: 0cm; margin-bottom: 0.0001pt; font-size: 10pt; font-family: &#39;Courier New&#39;; ">&nbsp;&nbsp; sigset (SIGUSR1, prekidna_rutina);</pre>
<pre style="margin-top: 0cm; margin-right: 0cm; margin-left: 0cm; margin-bottom: 0.0001pt; font-size: 10pt; font-family: &#39;Courier New&#39;; ">   ...</pre>
<pre style="margin-top: 0cm; margin-right: 0cm; margin-left: 0cm; margin-bottom: 0.0001pt; font-size: 10pt; font-family: &#39;Courier New&#39;; ">&nbsp;&nbsp; sigset (SIGINT, prekidna_rutina);</pre>
<pre style="margin-top: 0cm; margin-right: 0cm; margin-left: 0cm; margin-bottom: 0.0001pt; font-size: 10pt; font-family: &#39;Courier New&#39;; ">&nbsp;</pre>
<pre style="margin-top: 0cm; margin-right: 0cm; margin-left: 0cm; margin-bottom: 0.0001pt; font-size: 10pt; font-family: &#39;Courier New&#39;; ">   printf("Proces obrade prekida, PID=%ld\n", getpid());
   /* troši vrijeme da se ima šta prekinuti - 10 s */

	
   printf ("Zavrsio osnovni program\n");

	
   return 0;
}

Drugi program nasumično generira signale (četri odabrana, SIGINT nije u tom skupu) i šalje ih u slučajnim vremenskim intervalima (od 3 do 5 sekundi) procesu za obradu prekida (PID mu se zadaje preko komandne linije). Kada proces koji šalje signale (generator) primi (npr. od korisnika preko tipkovnice) signal SIGINT, tada proces treba poslati signal SIGKILL procesu koji prihvaća signale te nakon toga i sam završiti s radom.

Kostur rješenja programa za slanje signala dan je sljedećim kodom:

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>

int pid=0;

void prekidna_rutina(int sig){
   /* pošalji SIGKILL procesu 'pid'*/
   exit(0);
}

int main(int argc, char *argv[]){
   pid=atoi(argv[1]);
   sigset(SIGINT, prekidna_rutina);

   while(1){
      /* odspavaj 3-5 sekundi */
      /* slučajno odaberi jedan signal (od 4) */
      /* pošalji odabrani signal procesu 'pid' funkcijom kill*/
   }
   return 0;
}

Zgodno je programe pokretati iz dvije ljuske (iz jedne program za obradu prekida, a iz druge program za generiranje prekida). Program za generiranje signala mora se pokrenuti drugi da bi mogao dobiti identifikacijski broj prvog procesa kome šalje signale.

Ispis programa za obradu prekida treba izgledati vrlo slično kao u nastavku:

~/os1/vj1> ./obrada 
Proces obrade prekida, PID=10962
G 1 2 3 4 5
-----------
1 - - - - -
2 - - - - -
3 - - - - -
4 - - - - -

Nakon pokretanja prvog programa i kada se zna PID prvog procesa (u ovom slučaju 10962) u drugoj ljusci (dvije ljuske možete dobiti tako da se dvaput logirate) se pokrene drugi program koji generira prekide: 
~/os1/vj1> ./generator_prekida 10962

Tada bi se u prvoj ljusci trebalo ispisivati (stanja varijabli nije nužno potrebno ispisivati!):

GP S1 S2 S3 S4 S5
-----------------
 1  -  -  -  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=0  PRIOR[0 0 0 0 0 0 ]
 2  -  -  -  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=0  PRIOR[0 0 0 0 0 0 ]
 3  -  -  -  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=0  PRIOR[0 0 0 0 0 0 ]
 4  -  -  -  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=0  PRIOR[0 0 0 0 0 0 ]
 5  -  -  -  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=0  PRIOR[0 0 0 0 0 0 ]
 6  -  -  -  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=0  PRIOR[0 0 0 0 0 0 ]
 7  -  -  -  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=0  PRIOR[0 0 0 0 0 0 ]
 8  -  -  -  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=0  PRIOR[0 0 0 0 0 0 ]
 9  -  -  -  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=0  PRIOR[0 0 0 0 0 0 ]
 -  X  -  -  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=0  PRIOR[0 0 0 0 0 0 ]
 -  P  -  -  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=1  PRIOR[0 0 0 0 0 0 ]
 -  1  -  -  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=1  PRIOR[0 0 0 0 0 0 ]
 -  2  -  -  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=1  PRIOR[0 0 0 0 0 0 ]
 -  3  -  -  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=1  PRIOR[0 0 0 0 0 0 ]
 -  4  -  -  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=1  PRIOR[0 0 0 0 0 0 ]
 -  -  -  X  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=1  PRIOR[0 0 0 0 0 0 ]
 -  -  -  P  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  1  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  2  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  3  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  X  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  4  -  -      O_CEK[0 0 0 1 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  5  -  -      O_CEK[0 0 0 1 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  K  -  -      O_CEK[0 0 0 1 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  P  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  -  X  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  -  P  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=4  PRIOR[0 0 0 1 3 0 ]
 -  -  -  -  1  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=4  PRIOR[0 0 0 1 3 0 ]
 -  -  -  -  2  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=4  PRIOR[0 0 0 1 3 0 ]
 -  -  -  -  3  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=4  PRIOR[0 0 0 1 3 0 ]
 -  -  -  -  4  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=4  PRIOR[0 0 0 1 3 0 ]
 -  -  -  -  X  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=4  PRIOR[0 0 0 1 3 0 ]
 -  -  -  -  5  -      O_CEK[0 0 0 0 1 0 ]  TEK_PRIOR=4  PRIOR[0 0 0 1 3 0 ]
 -  -  -  -  K  -      O_CEK[0 0 0 0 1 0 ]  TEK_PRIOR=4  PRIOR[0 0 0 1 3 0 ]
 -  -  -  -  P  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=4  PRIOR[0 0 0 1 3 0 ]
 -  -  -  -  1  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=4  PRIOR[0 0 0 1 3 0 ]
 -  -  -  -  2  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=4  PRIOR[0 0 0 1 3 0 ]
 -  -  -  X  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=4  PRIOR[0 0 0 1 3 0 ]
 -  -  -  -  3  -      O_CEK[0 0 0 1 0 0 ]  TEK_PRIOR=4  PRIOR[0 0 0 1 3 0 ]
 -  -  -  -  4  -      O_CEK[0 0 0 1 0 0 ]  TEK_PRIOR=4  PRIOR[0 0 0 1 3 0 ]
 -  -  X  -  -  -      O_CEK[0 0 0 1 0 0 ]  TEK_PRIOR=4  PRIOR[0 0 0 1 3 0 ]
 -  -  -  -  5  -      O_CEK[0 0 1 1 0 0 ]  TEK_PRIOR=4  PRIOR[0 0 0 1 3 0 ]
 -  -  -  -  K  -      O_CEK[0 0 1 1 0 0 ]  TEK_PRIOR=4  PRIOR[0 0 0 1 3 0 ]
 -  -  -  1  -  -      O_CEK[0 0 1 1 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  2  -  -      O_CEK[0 0 1 1 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  3  -  -      O_CEK[0 0 1 1 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  4  -  -      O_CEK[0 0 1 1 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
^C -  -  -  -  -  X      O_CEK[0 0 1 1 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  -  -  P      O_CEK[0 0 1 1 0 0 ]  TEK_PRIOR=5  PRIOR[0 0 0 1 0 3 ]
 -  -  -  X  -  -      O_CEK[0 0 1 1 0 0 ]  TEK_PRIOR=5  PRIOR[0 0 0 1 0 3 ]
 -  -  -  -  -  1      O_CEK[0 0 1 2 0 0 ]  TEK_PRIOR=5  PRIOR[0 0 0 1 0 3 ]
 -  -  -  -  -  2      O_CEK[0 0 1 2 0 0 ]  TEK_PRIOR=5  PRIOR[0 0 0 1 0 3 ]
 -  -  -  -  -  3      O_CEK[0 0 1 2 0 0 ]  TEK_PRIOR=5  PRIOR[0 0 0 1 0 3 ]
 -  -  -  -  -  4      O_CEK[0 0 1 2 0 0 ]  TEK_PRIOR=5  PRIOR[0 0 0 1 0 3 ]
 -  -  -  X  -  -      O_CEK[0 0 1 2 0 0 ]  TEK_PRIOR=5  PRIOR[0 0 0 1 0 3 ]
 -  -  -  -  -  5      O_CEK[0 0 1 3 0 0 ]  TEK_PRIOR=5  PRIOR[0 0 0 1 0 3 ]
 -  -  -  -  -  K      O_CEK[0 0 1 3 0 0 ]  TEK_PRIOR=5  PRIOR[0 0 0 1 0 3 ]
 -  -  -  5  -  -      O_CEK[0 0 1 3 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  K  -  -      O_CEK[0 0 1 3 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  P  -  -      O_CEK[0 0 1 2 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  1  -  -      O_CEK[0 0 1 2 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  2  -  -      O_CEK[0 0 1 2 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  X  -  -  -      O_CEK[0 0 1 2 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  3  -  -      O_CEK[0 0 2 2 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  4  -  -      O_CEK[0 0 2 2 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  5  -  -      O_CEK[0 0 2 2 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  K  -  -      O_CEK[0 0 2 2 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  P  -  -      O_CEK[0 0 2 1 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  1  -  -      O_CEK[0 0 2 1 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  2  -  -      O_CEK[0 0 2 1 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  3  -  -      O_CEK[0 0 2 1 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  4  -  -      O_CEK[0 0 2 1 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  5  -  -      O_CEK[0 0 2 1 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  K  -  -      O_CEK[0 0 2 1 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  P  -  -      O_CEK[0 0 2 0 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  1  -  -      O_CEK[0 0 2 0 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  2  -  -      O_CEK[0 0 2 0 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  3  -  -      O_CEK[0 0 2 0 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  4  -  -      O_CEK[0 0 2 0 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  5  -  -      O_CEK[0 0 2 0 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  -  K  -  -      O_CEK[0 0 2 0 0 0 ]  TEK_PRIOR=3  PRIOR[0 0 0 1 0 0 ]
 -  -  P  -  -  -      O_CEK[0 0 1 0 0 0 ]  TEK_PRIOR=2  PRIOR[0 0 1 0 0 0 ]
 -  -  1  -  -  -      O_CEK[0 0 1 0 0 0 ]  TEK_PRIOR=2  PRIOR[0 0 1 0 0 0 ]
 -  -  2  -  -  -      O_CEK[0 0 1 0 0 0 ]  TEK_PRIOR=2  PRIOR[0 0 1 0 0 0 ]
 -  -  3  -  -  -      O_CEK[0 0 1 0 0 0 ]  TEK_PRIOR=2  PRIOR[0 0 1 0 0 0 ]
 -  -  4  -  -  -      O_CEK[0 0 1 0 0 0 ]  TEK_PRIOR=2  PRIOR[0 0 1 0 0 0 ]
 -  -  5  -  -  -      O_CEK[0 0 1 0 0 0 ]  TEK_PRIOR=2  PRIOR[0 0 1 0 0 0 ]
 -  -  K  -  -  -      O_CEK[0 0 1 0 0 0 ]  TEK_PRIOR=2  PRIOR[0 0 1 0 0 0 ]
 -  -  P  -  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=2  PRIOR[0 0 1 0 0 0 ]
 -  -  1  -  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=2  PRIOR[0 0 1 0 0 0 ]
 -  -  2  -  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=2  PRIOR[0 0 1 0 0 0 ]
 -  -  3  -  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=2  PRIOR[0 0 1 0 0 0 ]
 -  -  4  -  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=2  PRIOR[0 0 1 0 0 0 ]
 -  -  5  -  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=2  PRIOR[0 0 1 0 0 0 ]
 -  -  K  -  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=2  PRIOR[0 0 1 0 0 0 ]
 -  5  -  -  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=1  PRIOR[0 0 0 0 0 0 ]
 -  K  -  -  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=1  PRIOR[0 0 0 0 0 0 ]
10  -  -  -  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=0  PRIOR[0 0 0 0 0 0 ]
11  -  -  -  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=0  PRIOR[0 0 0 0 0 0 ]
12  -  -  -  -  -      O_CEK[0 0 0 0 0 0 ]  TEK_PRIOR=0  PRIOR[0 0 0 0 0 0 ]
Killed

X - označava pojavu signala, P početak obrade, K završetak obrade, a brojevi koliko je sekundi potrošeno na obradu.

U ispisu se mogu uočiti tri stvari. Prvo, ^C znači da je procesu došao signal SIGINT s tipkovnice, a drugo Killed znači da je program za slanje signala završio s radom (i prije toga poslao SIGKILL). I treće, u primjeru ispisa program pamti više prekida iste razine (OZNAKA_ČEKANJA[i] se ne postavlja u 1 kao što je navedeno u pseudokodu, već se povećava za 1). 

os_lab1's People

Contributors

matthew77cro avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.