5
Operační systémy (IOS) – Projekt č. 1 a 2
První projekt se psal v unixovém bashi, tvořily jej dva skripty, první na práci s regulárními výrazy a druhý na práci s archivy. Druhý projekt řešil problém spícího holiče s použitím podprocesů.
Hodnocení:
3. projekt – 13/15
4. projekt – 14/15
Je zakázáno kopírovat tyto zdrojové kódy! Veškeré projekty procházejí kontrolou na plagiátorství, takže se nepokoušejte použít mé kódy a to ani tak, že přepíšete názvy proměnných, nepomůže to. Výsledkem opisování je předvolání před komisi a většinou také odebrání zápočtu, takže vzhledem k tomu, že jsem nezpochybnitelným autorem následujících kódů, uškodíte pouze sami sobě.
Přejít na projekt č. 1 – hltrace
Přejít na projekt č. 2
Projekt č. 1 – ardiff
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 | #!/bin/sh export LC_ALL=C # IOS - Projekt 1, skript ardiff # Autor: Milan Seitler (xseitl01@stud.fit.vutbr.cz) # # Popis skriptu: Skript ardiff zaznamenava rozdily dvou archivu, ktere uklada # do adresarove struktury a zpetne rekonstruuje puvodni archivy za pouziti # rozdiloveho archivu #promenne pro osetreni parametru napoveda=false patch=false rozdil=false reverze=false vystup="" vypis=false #vygenerujeme docasny adresar temp=`mktemp -d /tmp/tempf.XXXXX`/ temp=${temp} nazev1="a" nazev2="b" #odchyceni signalu trap preruseni INT trap preruseni KILL trap preruseni TERM ####################################################################################### ###################################DEFINICE FUNKCI##################################### #pokud dojde k preruseni, vymazeme docasne soubory a ukoncime program preruseni(){ rm -rf $temp$nazev1/* ; rmdir $temp$nazev1 2> /dev/null rm -rf $temp$nazev2/* ; rmdir $temp$nazev2 2> /dev/null rm -rf "$temp"c/* ; rmdir "$temp"c 2> /dev/null rm -rf $temp* ; rmdir $temp 2> /dev/null exit 1 } #je treba zjistit typ archivu a pouzit odpovidajici unpack funkci rozbal(){ archiv=$(file $1) echo $archiv | grep -q ".*: POSIX tar.*" if [ $? -eq 0 ] ; then mkdir -p "$temp$2" tar -xf $1 -C "$temp$2" else echo $archiv | grep -q ".*: bzip2.*" if [ $? -eq 0 ] ; then mkdir -p "$temp$2" tar -jxf $1 -C "$temp$2" else echo $archiv | grep -q ".*: gzip.*" if [ $? -eq 0 ] ; then mkdir -p "$temp$2" tar -zxf $1 -C "$temp$2" else echo $archiv | grep -q ".*: Zip.*" if [ $? -eq 0 ] ; then mkdir -p "$temp$2" unzip -q $1 -d "$temp$2" fi fi fi fi } #funkce zabali vysledny archiv, pred zabalenim jeste smaze prazdne adresare zabal(){ archiv=$1 #zjistime priponu souboru pripona=$(echo $archiv | sed "s/.*\(...\)/\1/g") cd c #archiv nesmi obsahovat prazdne slozky find . -type d | tail -r | while read slozka ; do rmdir "$slozka" 2> /dev/null done #zvolime odpovidajici balici funkci case $pripona in tar) tar -cf ../vystupni.archiv * ;; tgz|.gz) tar -zcf ../vystupni.archiv * ;; bz2) tar -jcf ../vystupni.archiv * ;; zip|ZIP) zip -rq ../vystupni.archiv ./ ;; *) #pri nespravnem typu archivu smazeme docasne soubory a ukoncime program echo "Typ vysledneho archivu neni podporovan." rm -rf $temp$nazev1/* ; rmdir $temp$nazev1 2> /dev/null rm -rf $temp$nazev2/* ; rmdir $temp$nazev2 2> /dev/null rm -rf "$temp"c/* ; rmdir "$temp"c 2> /dev/null rm -rf $temp* ; rmdir $temp 2> /dev/null exit 1 ;; esac cd .. } #nacte nazvy adresaru, kterej se jmenuji stejne jako nejaky soubor najdi_dupl(){ vysl="" slozky=`diff -aqrNl "$temp$nazev1/" "$temp$nazev2/" | grep "^File .*" | sed "s#^File $temp$nazev1\/\(.*\).* is a .* while .* is a.*#\1#"` slozky=${slozky} #projdeme vsechny shody for slozka in "$slozky" ; do slozka=$(echo "$slozka" | sed "s/^\( *\)//g" | sed '/^$/d') if [ "$slozka" != "" ] ; then #testujeme v kterem archivu je soubor a v kterem adresar ls -ld "$temp$nazev1/$slozka" | grep -q "^d.*" if [ $? -eq 0 ] ; then vysl="$vysl "$(find -L "$temp$nazev1/$slozka" | sed "s#$temp$nazev1\/##g") fi ls -ld "$temp$nazev2/$slozka" | grep -q "^d.*" if [ $? -eq 0 ] ; then vysl="$vysl "$(find -L "$temp$nazev2/$slozka" | sed "s#$temp$nazev2\/##g") fi fi done #ltrim vysl=$(echo "$vysl" | sed "s/^\( *\)//g" | sed '/^$/d') echo "$vysl" } #zobrazi seznam vsech souboru, ktere jsou v danych archivech odlisne rozdilne_soubory(){ vysl=$(najdi_dupl) #zobrazi ostatni rozdilne soubory vysl="$vysl "$(diff -aqrNlP $temp$nazev1/ $temp$nazev2/ | grep "^Files .*" | sed "s#Files $temp$nazev1\/\(.*\) and .*#\1#") #ltrim vysl=$(echo "$vysl" | sed "s/^\( *\)//g" | sed '/^$/d') echo -n "$vysl" } ####################################################################################### ###################################</DEFINICE FUNKCI>################################## #zpracovani parametru while getopts ":lcpro:" param ; do case "$param" in l) vypis=true ;; c) rozdil=true ;; p) patch=true ;; r) reverze=true ;; o) vystup="$OPTARG" ;; [?]) napoveda=true ;; esac done #nebyly zadany zadne parametry if [ $# -eq 0 ] ; then napoveda=true fi if [ "$napoveda" = false ] ; then #nacteme nazvy archivu shift $(($OPTIND - 1)) soubor1=$1 soubor2=$2 #rozbalim oba soubory do docasnych adresaru rozbal "$soubor1" "$nazev1" rozbal "$soubor2" "$nazev2" fi #parametr -l if [ "$vypis" = true -a "$rozdil" = false -a "$patch" = false -a "$reverze" = false -a "$vystup" = "" -a "$napoveda" = false ] ; then rozdilne_soubory #parametry -c -o elif [ "$vypis" = false -a "$rozdil" = true -a "$patch" = false -a "$reverze" = false -a "$vystup" != "" -a "$napoveda" = false ] ; then #zjistime rozdilne soubory seznam=$(rozdilne_soubory) soubory="" #presuneme se do temp adresare aktual=$(pwd) cd $temp mkdir c echo "$seznam" | while read pol ; do #pokud se v ceste k souboru nachazi alespon jedna slozka echo "$pol" | grep -q "/" if [ $? -eq 0 ] ; then #vyrizneme jeji nazev a vytvorime k ni cestu slozka=$(echo "$pol" | sed "s/\(.*\)\/.*$/\1/g") mkdir -p "c/$slozka" fi #zapiseme zmeny jednotlivych souboru diff -auN "$nazev1/$pol" "$nazev2/$pol" > "c/$pol.patch" 2> /dev/null done stejne=$(najdi_dupl) #prepise hlavicku diff souboru echo "$stejne" | while read pol ; do if [ -s "a/$pol" -a ! -d "a/$pol" ] ; then diff -au "a/$pol" "/dev/null" | sed "s#\([+-][+-]*\) /dev/null\([^0-9]*\)\(.*\)#\1 b/${pol}\21970-01-01 01:00:00.000000000 +0100#g" > "c/$pol.patch" fi if [ -s "b/$pol" -a ! -d "b/$pol" ] ; then diff -au "/dev/null" "b/$pol" | sed "s#\([+-][+-]*\) /dev/null\([^0-9]*\)\(.*\)#\1 a/${pol}\21970-01-01 01:00:00.000000000 +0100#g" > "c/$pol.patch" fi done zabal $vystup #vysledny archiv presuneme na pozadovane umisteni cd $aktual cp "$temp""vystupni.archiv" "$archiv" rm "$temp""vystupni.archiv" rm -rf "$temp"c/* ; rmdir "$temp"c #parametry -p -o elif [ "$vypis" = false -a "$rozdil" = false -a "$patch" = true -a "$vystup" != "" -a "$napoveda" = false ] ; then #parametr -r (pokud neni zadan) if [ "$reverze" = false ] ; then aktual=$(pwd) #odskocime do docasneho adresare cd $temp slozky=$(find "b/" -type f) #projdeme vsechny soubory, na originalni soubor aplikujeme patch echo "$slozky" | while read slozka ; do slozka=$(echo "$slozka" | sed "s#b\/##") orig=$(echo "$slozka" | sed "s/\.patch$//g") cesta=$(echo "$orig" | grep "/" | sed "s/\(.*\)\/.*$/\1/g") mkdir -p "$a/$cesta" 2> /dev/null patch -fs "a/$orig" "b/$slozka" done #obsah noveho archivu zkopirujeme, funkce zabal tvori archiv ze slozky c mkdir c cp -r a/* c zabal $vystup cd $aktual #uklid docasnych souboru cp "$temp""vystupni.archiv" "$archiv" rm "$temp""vystupni.archiv" rm -rf "$temp"c/* ; rmdir "$temp"c else #reverzni mod znova_sl="" aktual=$(pwd) #odskocime do docasneho adresare cd $temp slozky=$(find "b/" -type f) #nejprve se patch aplikuje na vsechny soubory, ktere jsou soubory v obou archivech echo "$slozky" | while read slozka ; do slozka=$(echo "$slozka" | sed "s#b\/##g") orig=$(echo "$slozka" | sed "s/.patch$//g") if [ -f "a/$orig" -a -f "b/$slozka" ] ; then adresar=$(echo "$orig" | grep "/" | sed "s/\(.*\)\/.*$/\1/g") mkdir -p "a/$adresar" 2>/dev/null touch "a/$orig" patch -fsR "a/$orig" "b/$slozka" 2>/dev/null else #ukladame cestu pro soubor/slozka problem znova_sl="$znova_sl $slozka" fi #je to potreba si data ze subshellu ulozit echo "$znova_sl" > seznam.slozek done znova_sl=$(cat seznam.slozek) rm seznam.slozek #nyni pouzijeme patch na zbyvajici soubory znova_sl=$(echo "$znova_sl" | sed "1d") echo "$znova_sl" | while read znova ; do orig=$(echo "$znova" | sed "s/.patch$//g") patch -fsR "a/$orig" "b/$znova" 2>/dev/null done #obsah noveho archivu zkopirujeme, funkce zabal tvori archiv ze slozky c mkdir c cp -r a/* c zabal $vystup cd $aktual #uklid docasnych souboru cp "$temp""vystupni.archiv" "$archiv" rm "$temp""vystupni.archiv" rm -rf "$temp"c/* ; rmdir "$temp"c fi #neplatna kombinace parametru else echo "ardiff vypisuje zmeny archivu, vytvari rozdilovy archiv nebo aplikuje rozdilovy archiv na zdrojovy archiv. Pouziti: ardiff [volby] archiv1 archiv2 Volby: -o SOUBOR Pokud je cilem skriptu vytvorit archiv, bude vytvoren do souboru se jmenem SOUBOR (plati pro -c a -p). -l Vypis seznamu souboru, ktere se v zadanych archivech lisi. -c Vytvoreni rozdiloveho archivu. -p Aplikace rozdiloveho archivu (argument archiv2) na zdrojovy archiv (argument archiv1). -r Prepnuti do reverzniho rezimu (plati pro -p)." #pokud byly vytvoreny docasne soubory, je nutne je smazat rm -rf $temp$nazev1/* ; rmdir $temp$nazev1 2> /dev/null rm -rf $temp$nazev2/* ; rmdir $temp$nazev2 2> /dev/null rm -rf "$temp"c/* ; rmdir "$temp"c 2> /dev/null rm -rf $temp* ; rmdir $temp 2> /dev/null exit 1 fi #uklid docasnych souboru rm -rf $temp$nazev1/* ; rmdir $temp$nazev1 2> /dev/null rm -rf $temp$nazev2/* ; rmdir $temp$nazev2 2> /dev/null rm -rf $temp* ; rmdir $temp 2> /dev/null exit 0 |
Projekt č. 1 – hltrace
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | #!/bin/sh export LC_ALL=C # IOS - Projekt 1, skript hltrace # Autor: Milan Seitler (xseitl01@stud.fit.vutbr.cz) # # Popis skriptu: Skript hltrace slouzi jako textovy filtr, ktery zvyraznuje # syntaxi vystupu z programu strace a uklada ji jako webovou stranku #"vynulujeme" syscall syscall="&!#" napoveda=false #nacteni parametru if [ $# -eq 1 ] || [ $# -gt 2 ] ; then napoveda=true fi if [ $# -eq 2 ] ; then if [ $1 != "-s" ] ; then napoveda=true else syscall=$2 fi fi #pri neplatne kombinaci vypiseme napovedu if [ $napoveda = true ] ; then echo "hltrace zvyrazni syntax stopy od strace. Pouziti: hltrace [volby] <stopa.strace >stopa.html Volby: -s SYSCALL Specialne zvyrazni volani SYSCALL." 1>&2 exit 1 else #vypiseme hlavicku echo "<html> <style> .pid { color:darkred; } .ts { color:navy; } .number { color:red; } .const { color:green; } .string { color:blue; } .hlcall { text-decoration:none; font-weight:bold; color:black; } .call { text-decoration:none; color:olive; } </style> <body><pre>" #ze standardniho vstupu nacteme text a postupne filtrujeme cat /dev/stdin | sed "s/&/\&/g" | sed "s/</\</g" | sed "s/>/\>/g" | #nahrazeni <>& sed "s/\(\"[^\"]*\"\)/<span class=\"string\">\1<\/span>/g" | #retezce sed "s/\([[| ,({=]\)\([A-Z][A-Z0-9_]*\)\([]} |,()]\)/\1<span class=\"const\">\2<\/span>\3/g" | #konstanty sed "s/\([[| ,({=]\)\([A-Z][A-Z0-9_]*\)\([]} |,()]\)/\1<span class=\"const\">\2<\/span>\3/g" | #konstanty sed "s/\([ (]\)\(0x[a-f0-9]*\)/\1<span class=\"number\">\2<\/span>/g" | sed "s/ = \([-0-9][0-9]*\)/ = <span class=\"number\">\1<\/span>/g" | #hexa a cisla s = sed "s/(\([-0-9][0-9]*\)/(<span class=\"number\">\1<\/span>/g" | sed "s/ \([-0-9][0-9]*\)\([,)]\)/ <span class=\"number\">\1<\/span>\2/g" | #decimalni cisla sed "s/\($syscall\)(/<a href=\"http:\/\/www.kernel.org\/doc\/man-pages\/online\/pages\/man2\/\\1.2.html\" class=\"hlcall\">\1<\/a>(/g" | #nahradi hlcall sed "s/\([0-9a-z_][0-9a-z_]*\)(/<a href=\"http:\/\/www.kernel.org\/doc\/man-pages\/online\/pages\/man2\/\\1.2.html\" class=\"call\">\1<\/a>(/" | #ostatni volani sed "s/^\([0-9][0-9]*\)\([ ][ ]*\)\([0-9][0-9\.]*\)/<span class=\"pid\">\1<\/span>\2<span class=\"ts\">\3<\/span>/g" | #nahrazuje pid a ts sed "s/^\([0-9][0-9]*\)\([ ][ ]*\)/<span class=\"pid\">\1<\/span>\2/g" | sed "s/^\([0-9][0-9\.]*\)/<span class=\"ts\">\1<\/span>/g" #zbyva vypsat paticku echo "<:/pre></body></html>" fi exit 0 |
Projekt č. 2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 | /****************************************************** ******************IOS - projekt c. 2******************* ** Autor: Milan Seitler (xseitl01@stud.fit.vutbr.cz) ** Datum vytvoreni: duben 2011 ** ** Popis programu: Progrsm demonstruje synchronizaci procesu ** pri problemu spiciho holice. S vyuzitim semaforu a sdilene ** pameti zabranuje synchronizacnim problem jako deadlock ci ** hladoveni. ** ** Parametry programu: barbers Q GenC GenB N F ** Q - pocet zidli v cekarne ** GenC - rozsah pro generovani zakazniku [ms] ** GenB - rozsah pro generovani doby obsluhy [ms] ** N - pocet vygenerovanych zakazniku ** F - nazev vystupniho souboru, v pripade "-" -> stdout ** ** ** Literatury precteno: mnoho, probdeno noci: 0 ** propadnuto zoufalstvi: 2x, pouzito tuzky a papiru: mnohokrat ******************************************************/ #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <ctype.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/wait.h> #include <semaphore.h> #include <pthread.h> #include <unistd.h> #include <time.h> #include <fcntl.h> #include <sys/stat.h> #include <sys/mman.h> #include <string.h> #define E_OK 0 #define E_SEM 1 #define E_SHM 2 #define E_PARAM 3 typedef struct parametry { int q; // pocet zidli int GenC, GenB; // rozsah pro generovani zakazniku a doby obsluhy (O-Gen[BC]) int N; // pocet zakazniku char *F; // nazev vystupniho souboru, pokud je "-" => vypise na stdout } Tparam; // deklarujeme promenne pro vsechny semafory sem_t *s_cekarna, *s_holic, *s_zakaznici, *s_strihani, *s_citac, *s_citac_z, *s_zapis, *s_zidle; FILE *vypis = NULL; // a taky ukazatel na soubor int barber_pid = 0; // budeme ukladat id procesu holice // ukazatele na sdilenou pamet int *cislo_procesu = NULL, *cislo_zakaznika = NULL, *volne_zidle = NULL, *pocet_hotovych = NULL; // pro navratove funkce shmget int shm_cp_id = 0, shm_cz_id = 0, shm_zidle_id = 0, shm_hotovo_id = 0; // deklarace funkci int nacti_parametry(int argc, char *argv[], Tparam *x); void holic(Tparam param); void zakaznik(); int zvys_cislo_akce(int *cislo); // zvysi pocitadlo o jednicku, vraci hodnotu pred zvysenim int nacti_zdroje(void); // alokuje pamet, inicializuje semafory void uvolni_zdroje(void); // uvolni sdilenou pamet, znici semafory void ukonci_program(int sig); // v pripade preruseni bezpecne ukonci program int main(int argc, char *argv[]) { pid_t pid_holice, pid_zakaznika; Tparam param; // struktura pro ulozeni parametru programu int i = 0; // pruchod poctem zakazniku N int rozsah = 0; // promenna pro generovani nahodne doby obsluhy // handlery pro zachyceni signalu signal(SIGTERM, ukonci_program); signal(SIGINT, ukonci_program); srand(time(0)); // abychom generovali opravdu nahodna cisla // parametry ukladame do struktury if(nacti_parametry(argc, argv, ¶m) == E_PARAM) { return E_PARAM; } int potomci[param.N]; // otevreme vystupni soubor, v pripade chyby vypis na stdout if(strcmp(param.F, "-") != 0) { if((vypis = fopen(param.F, "w+")) == NULL) { fprintf(stderr, "Nepovedlo se otevrit vystupni soubor. Program bude ukoncen.\n"); uvolni_zdroje(); return EXIT_FAILURE; } } else { vypis = stdout; } // pro spravny zapis do souboru setbuf(vypis, NULL); // alokace pameti a inicializace semaforu int zdroje = nacti_zdroje(); if(zdroje != E_OK) { if(zdroje == E_SEM) { fprintf(stderr, "Nastala chyba pri vytvareni semaforu. Program bude ukoncen.\n"); } else { fprintf(stderr, "Nastala chyba pri alokaci pameti. Program bude ukoncen.\n"); } uvolni_zdroje(); return EXIT_FAILURE; } // nastavime citace *cislo_procesu = 1; *cislo_zakaznika = 1; *volne_zidle = param.q; *pocet_hotovych = 0; // spustime proces holice pid_holice = fork(); if(pid_holice == 0) { // potomek, tedy holic holic(param); } else if (pid_holice > 0) { pid_holice = pid_holice; // proces rodice for(i = 0; i < param.N; i++) { // spoustime procesy zakazniku // generujeme prodlevu mezi zakazniky if(param.GenC != 0) { rozsah = (random() % (param.GenC + 1)); } else { rozsah = 0; } usleep(rozsah * 1000); pid_zakaznika = fork(); if(pid_zakaznika == 0) { // proces zakaznika zakaznik(); } else if(pid_zakaznika > 0) { // pokracovani procesu rodice (hlavniho procesu) potomci[i] = pid_zakaznika; } else { fprintf(stderr, "Nepovedlo se vytvorit zakaznika. Program bude ukoncen.\n"); ukonci_program(0); } } } else { fprintf(stderr, "Nepovedlo se vytvorit holice. Program bude ukoncen.\n"); uvolni_zdroje(); exit(EXIT_FAILURE); } // pockame na zakazniky for(i = 0; i < param.N; i++) { waitpid(potomci[i], NULL, 0); } // pozor na zombie holice! if(param.q == 0) { kill(barber_pid, SIGTERM); } uvolni_zdroje(); return EXIT_SUCCESS; } int nacti_parametry(int argc, char *argv[], Tparam *x) { int error = E_OK; char *stop = NULL; // celkem 6 parametru (5 + nazev programu) if(argc == 6) { // postupne overime jednotlive parametry if(isdigit(*argv[1])) { x->q = strtoul(argv[1], &stop, 10); } else { error = E_PARAM; } if(isdigit(*argv[2])) { x->GenC = strtoul(argv[2], &stop, 10); } else { error = E_PARAM; } if(isdigit(*argv[3])) { x->GenB = strtoul(argv[3], &stop, 10); } else { error = E_PARAM; } if(isdigit(*argv[4])) { x->N = strtoul(argv[4], &stop, 10); } else { error = E_PARAM; } x->F = argv[5]; // konec overovani parametru } else { error = E_PARAM; } if(error == E_PARAM) { printf("Byla zadana neplatna kombinace parametru. Program bude ukoncen.\n"); } return error; } void holic(Tparam param) { int rozsah = 0; // proces holice provadi jen urcity pocet iteraci while(*pocet_hotovych < param.N) { fflush(vypis); sem_wait(s_zapis); fprintf(vypis, "%d: barber: checks\n", zvys_cislo_akce(cislo_procesu)); sem_post(s_zapis); sem_wait(s_zakaznici); sem_wait(s_cekarna); // pokud je v cekarne zakaznik, uvolnime jedno misto a pustime jej dale if(*volne_zidle < param.q) { (*volne_zidle)++; } sem_wait(s_zapis); fprintf(vypis, "%d: barber: ready\n", zvys_cislo_akce(cislo_procesu)); sem_post(s_zapis); fflush(vypis); sem_post(s_holic); sem_wait(s_zidle); sem_post(s_cekarna); // nyni probihani strihani vlasu if(param.GenB != 0) { rozsah = (random() % (param.GenB + 1)); } else { rozsah = 0; } usleep(rozsah * 1000); sem_wait(s_zapis); fprintf(vypis, "%d: barber: finished\n", zvys_cislo_akce(cislo_procesu)); sem_post(s_zapis); fflush(vypis); sem_post(s_strihani); (*pocet_hotovych)++; // poznacime "uspokojeneho" zakaznika } exit(0); } void zakaznik() { int lok_cislo = 0; // ulozime si cislo zakaznika do pomocne promenne sem_wait(s_citac_z); // je treba si ulozit cislo zakaznika do lokalni promenne, aby nedoslo ke kolizim lok_cislo = *cislo_zakaznika; (*cislo_zakaznika)++; sem_post(s_citac_z); sem_wait(s_zapis); fprintf(vypis, "%d: customer %d: created\n", zvys_cislo_akce(cislo_procesu), lok_cislo); sem_post(s_zapis); fflush(vypis); sem_wait(s_cekarna); sem_wait(s_zapis); fprintf(vypis, "%d: customer %d: enters\n", zvys_cislo_akce(cislo_procesu), lok_cislo); sem_post(s_zapis); fflush(vypis); // pokud je v cekarne jeste misto, zakaznik se posadi if(*volne_zidle > 0) { (*volne_zidle)--; sem_post(s_zakaznici); sem_post(s_cekarna); sem_wait(s_holic); sem_wait(s_zapis); fprintf(vypis, "%d: customer %d: ready\n", zvys_cislo_akce(cislo_procesu), lok_cislo); sem_post(s_zapis); sem_post(s_zidle); // zakaznik useda do holicskeho kresla fflush(vypis); sem_wait(s_strihani); sem_wait(s_zapis); fprintf(vypis, "%d: customer %d: served\n", zvys_cislo_akce(cislo_procesu), lok_cislo); sem_post(s_zapis); fflush(vypis); } else { // pokud v cekarne neni misto, zakaznik odchazi sem_wait(s_zapis); fprintf(vypis, "%d: customer %d: refused\n", zvys_cislo_akce(cislo_procesu), lok_cislo); sem_post(s_zapis); fflush(vypis); sem_post(s_cekarna); (*pocet_hotovych)++; // i odmitnuty zakaznik je pro nase potreby "uspokojeny" } exit(0); } int zvys_cislo_akce(int *cislo) { // funkce zajistuje bezpecne navyseni pocitadla akci int puvodni = 0; sem_wait(s_citac); puvodni = *cislo; (*cislo)++; sem_post(s_citac); return puvodni; } int nacti_zdroje(void) { int error = E_OK; // -------------------- inicializace semaforu ----------------------- // s_holic = semafor holice // s_zakaznici = semafor zakazniku // s_strihani = semafor oznamuje zakaznikovi konec strihani // s_cekarna = semafor cekarny // s_citac = vylucny pristup k citaci akci // s_citac = vylucny pristup k citaci zakazniku // s_zapis = vylucny pristup k souboru // s_zidle = semafor hlida, aby se nepredbihali zakaznici na ceste do kresla if((s_holic = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0)) == MAP_FAILED) { error = E_SEM; } if((s_zakaznici = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0)) == MAP_FAILED) { error = E_SEM; } if((s_strihani = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0)) == MAP_FAILED) { error = E_SEM; } if((s_cekarna = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0)) == MAP_FAILED) { error = E_SEM; } if((s_citac = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0)) == MAP_FAILED) { error = E_SEM; } if((s_citac_z = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0)) == MAP_FAILED) { error = E_SEM; } if((s_zapis = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0)) == MAP_FAILED) { error = E_SEM; } if((s_zidle = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, 0, 0)) == MAP_FAILED) { error = E_SEM; } if(error == E_OK) { if(sem_init(s_holic, 1, 0) == -1) { error = E_SEM; } if(sem_init(s_zakaznici, 1, 0) == -1) { error = E_SEM; } if(sem_init(s_strihani, 1, 0) == -1) { error = E_SEM; } if(sem_init(s_cekarna, 1, 1) == -1) { error = E_SEM; } if(sem_init(s_citac, 1, 1) == -1) { error = E_SEM; } if(sem_init(s_citac_z, 1, 1) == -1) { error = E_SEM; } if(sem_init(s_zapis, 1, 1) == -1) { error = E_SEM; } if(sem_init(s_zidle, 1, 0) == -1) { error = E_SEM; } } // -------------------- konec inicializace semaforu ----------------- if(error == E_OK) { // -------------------- alokace pameti ------------------------------ // shm_cp_id = id pameti pro cislo procesu // shm_cz_id = id pameti pro cislo zakaznika // shm_zidle_id = id pameti pro pocet volnych zidli // shm_hotovo_id = id pameti pro pocitani "hotovych" zakazniku if((shm_cp_id = shmget(IPC_PRIVATE, sizeof(int), IPC_CREAT | IPC_EXCL | 0666)) == -1) { error = E_SHM; } if((cislo_procesu = (int *) shmat(shm_cp_id, NULL, 0)) == NULL) { error = E_SHM; } if((shm_cz_id = shmget(IPC_PRIVATE, sizeof(int), IPC_CREAT | IPC_EXCL | 0666)) == -1) { error = E_SHM; } if((cislo_zakaznika = (int *) shmat(shm_cz_id, NULL, 0)) == NULL) { error = E_SHM; } if((shm_zidle_id = shmget(IPC_PRIVATE, sizeof(int), IPC_CREAT | IPC_EXCL | 0666)) == -1) { error = E_SHM; } if((volne_zidle = (int *) shmat(shm_zidle_id, NULL, 0)) == NULL) { error = E_SHM; } if((shm_hotovo_id = shmget(IPC_PRIVATE, sizeof(int), IPC_CREAT | IPC_EXCL | 0666)) == -1) { error = E_SHM; } if((pocet_hotovych = (int *) shmat(shm_hotovo_id, NULL, 0)) == NULL) { error = E_SHM; } // -------------------- konec alokace pameti ------------------------ } return error; } void uvolni_zdroje(void){ fclose(vypis); int error = E_OK; if(sem_destroy(s_holic) == -1) { error = E_SEM; } if(sem_destroy(s_zakaznici) == -1) { error = E_SEM; } if(sem_destroy(s_strihani) == -1) { error = E_SEM; } if(sem_destroy(s_cekarna) == -1) { error = E_SEM; } if(sem_destroy(s_citac) == -1) { error = E_SEM; } if(sem_destroy(s_citac_z) == -1) { error = E_SEM; } if(sem_destroy(s_zapis) == -1) { error = E_SEM; } if(sem_destroy(s_zidle) == -1) { error = E_SEM; } if(error == E_SEM) { fprintf(stderr, "Nepovedlo se smazat semafor.\n"); } if(shmctl(shm_cp_id, IPC_RMID, NULL) == -1) { error = E_SHM; } if(shmctl(shm_cz_id, IPC_RMID, NULL) == -1) { error = E_SHM; } if(shmctl(shm_zidle_id, IPC_RMID, NULL) == -1) { error = E_SHM; } if(shmctl(shm_hotovo_id, IPC_RMID, NULL) == -1) { error = E_SHM; } if(error == E_SHM) { fprintf(stderr, "Nepovedlo se uvolnit alokovanou pamet.\n"); } } void ukonci_program(int sig) { uvolni_zdroje(); kill(barber_pid, SIGTERM); kill(getppid(), SIGTERM); exit(EXIT_FAILURE); } |
Čti dál:
Vyjádři svůj názor
O mně
kategorie
SSME FI MUNI
FIT VUT
Odkazy
Kupte si odkaz! PR 3, SR 2
Kupte si odkaz! PR 3, SR 2
Kupte si odkaz! PR 3, SR 2
TAGS
Nejčtenější články
- 7 tipů Jak spát méně a efektivněji - 167 689 views
- První semestr na FIT VUT - 165 658 views
- Třetí semestr na FIT VUT - 146 693 views
- Jak v PHP nahradit zastaralé funkce ereg a eregi - 82 899 views
- Pátý semestr na FIT VUT - 57 952 views
- 7 tipů jak si usnadnit a urychlit práci s HTML a CSS - 56 889 views
- TEST: Kolik spánku je denně potřeba? - 53 107 views
- 9 nečekaně jednoduchých technik, které z vás udělají mistra komunikace - 43 797 views
- Čtvrtý semestr na FIT VUT - 40 102 views
- Druhý semestr na FIT VUT - 37 753 views
Nejnovější komentáře
- 5 nových tipů pro lepší spánek « Milan Seitler u 7 tipů Jak spát méně a efektivněji
- 5 nových tipů pro lepší spánek « Milan Seitler u TEST: Je možné spát 6 hodin denně? Tak určitě!
- David u 9 nečekaně jednoduchých technik, které z vás udělají mistra komunikace
- Petr u Bakalářské studium na FIT VUT
- Martin u Jak v PHP nahradit zastaralé funkce ereg a eregi
archiv
- Prosinec 2018
- Listopad 2015
- Září 2015
- Březen 2015
- Květen 2014
- Duben 2014
- Prosinec 2013
- Listopad 2013
- Červenec 2013
- Červen 2013
- Duben 2013
- Březen 2013
- Únor 2013
- Leden 2013
- Prosinec 2012
- Listopad 2012
- Říjen 2012
- Září 2012
- Srpen 2012
- Červenec 2012
- Červen 2012
- Květen 2012
- Březen 2012
- Únor 2012
- Leden 2012
- Listopad 2011
- Říjen 2011
- Srpen 2011
- Červen 2011
- Duben 2011
- Únor 2011
- Leden 2011