# SO Lista 1 ### Zadanie 1 <!-- Gut --> ![](https://i.imgur.com/oG6GD4t.png) <b>Relacja rodzic-dziecko -></b> każdy proces (oprócz init i kthread) ma swojego rodzica tzn. jest jego subprocesem <b>Identyfikator procesu (PID) -></b> unikatowy numer przypisany do procesu <b>Identyfikator grupy procesów (PGID) -></b> unikatowy numer przypisany do grupy procesów, pomaga w zorganizowaniu drzewa procesów, sygnałów i komunikatów między nimi <b>Identyfikator rodzica (PPID) -></b> PID rodzica <b>Właściciel (User)-></b> kinda obvious <b>Kto jest rodzicem init?</b> Nikt (jego ojciec poszedł po mleko), jest to pierwszy proces jaki robi system <b>Wątki jądra -></b> operuje w kernelspace, są tworzone przez inne uprzywilejowane wątki <b>Wksaż wątki jądra w "ps" </b> Wszystkie dzieci kthread <b>Jakie jest znaczenie poszczególnych znaków w kolumnie STAT?</b> ![](https://i.imgur.com/rtT8kd6.png) <b>Które są wątkami?</b> Te w {} ![](https://i.imgur.com/AJ1nd4n.jpg) ![](https://i.imgur.com/18JRmAv.jpg) ### Zadanie 2 (początek wyżej) <!-- Gut --> ![](https://i.imgur.com/xtoCUUx.png) <b>Proces zombie -></b> proces zwolniony który dalej bierze zasoby systemu <b>Proces sierota -></b> proces którego rodzic skończył, ale ten proces mimo tego nadal działa. <b>Jak jądro reaguje na sytuację z sierotą?</b> Wtedy 'sierota' zostaje przygarnięta przez <b>init</b> lub najsilniejszy subproces <b>W jaki sposób pogrzebać proces który wszedł w stan zombie?</b> Albo parent musi wywołać wait()|waitpid() lub musi sam zterminować i wtedy init pogrzebie zombie <b>Czemu proces nie może sam siebie pogrzebać?</b> Bo nie może użyć wait() na sobie, poza tym exit() nie sprząta swojego stosu jądra, więc proces dalej zajmuje miejsce w pamięci <b>Co złego mogłoby się stać, gdy:</b> <li>Dziecko może czekać na zmianę stanu swojego rodzica </li> <ol> <li>infinity loop (przez 2 waity)</li> <li>mogą zajmować zasoby przez czekanie na init</li> </ol> <li>wiele procesów oczekuje na zmianę stanu jednego procesu</li> <ol> <li>infloop gdy dziecko czeka na wait rodzica rodzica</li> <li>moglibyśmy zmienić execution flow programu</li> </ol> ![](https://i.imgur.com/ZHQ14SC.jpg) ### Zadanie 3 <!-- Gut --> ![](https://i.imgur.com/VhMMaV6.png) <b>Do czego służy system plików proc(5) w systemie Linux?</b> <li>Jest interfejsem dla struktur jądra</li> <li>Jądro może zmieniać parametry procesu i zczytywać je</li> <li>Zawiera katalog dla kolejnego procesu na systemie</li> ![](https://i.imgur.com/Y64doHN.png) ![](https://i.imgur.com/FAISHTJ.jpg) ### Zadanie 4 <!-- Gut --> ![](https://i.imgur.com/KW6aXom.png) XORG 608? Adres wirtualny | rozmiar KB | uprawnienia | nazwa zmapowanego obiektu ![](https://i.imgur.com/DXN3IJK.png) <b>[anon] -></b> pamięć anonimowa (requestowana przez proces) <b>segmenty programu -></b> definiowane w elfie, zawierajace 1 lub więcej ładowalnych sekcji programu, mają swoje atrybuty i z reguły są ciągłe <b>pliki odwzorowane w pamięć -></b> segment w pamięci który ma bezpośrednie mapowanie w nazej pamięci (bajt do bajta) ![](https://i.imgur.com/UHxQCRR.jpg) ### Zadanie 5 <!-- Gut --> ![](https://i.imgur.com/Wg79RvY.png) <b>Zasoby plikopodobne -></b> zasób mający deskryptor pliku, ale nie będący zwykłym plikiem (np. socket sieciowy) <b>Co znaczą dane kolumny?</b> ![](https://i.imgur.com/0LUxelf.png) <b>Command -></b>oryginalna komenda związana z procesem <b>TID -></b> thread id <b>FD -></b> nr deskryptora pliku lub ![](https://i.imgur.com/d0d9oWO.png) <b>Device -></b> numery urządzenia oddzielone przecinliem dla katalogów, zwykłych plików lub plikó NFS (Network File System) <b>Size/off -></b> rozmiar pliku lub jego offset wbajtach <b>Node -></b> numer węzła lokalnego pliku zdefinowany w globalnej strukturze <b>Name -></b> nazwa punktu podłączenia i systemów plików w którym się znajduje <b>Pliki zwykłe REG-></b>? <b>Katalogi DIR-></b>? <b>Plik urządzenia CHR/BLK-></b> Specjalny plik służący do komunikacji programu z urządzeniem poprzez używanie jego sterowników (np. plik klawiatury) <b>Gniazdo unix (socket)-></b>pseudoplik służący do komunikacji sieciowej. Składa się z "2 końców", czyli urządzenia wysyłającego i otrzymującego dane, każdy socket musi mieć zdefiniowane: <li>jakim typem połączenia się posługuje (TCP/UDP</li> <li>domena w jakiej działa (rodzina protokołów jaką będzie się posługiwał)</li> <b>Potok (pipe) FIFO -></b> mechanizm komunikacji międzyprocesowej. Najczęściej łączy się stdin programu A z stdout B. ![](https://i.imgur.com/NlMLA22.jpg) ![](https://i.imgur.com/xj6glvF.jpg) ![](https://i.imgur.com/NrglHWj.jpg) ### Zadanie 6 <!-- Gut --> ![](https://i.imgur.com/f4hBDY2.png) <b>Real -></b> czas od początku do końca życia procesu <b>User -></b> czas jaki proces potrzebował na wykonanie kodu w userspace (tylko kiedy był aktywny) <b>Sys -></b> czas jaki proces potrzebował na wykonanie kodu po stronie kernela. Czas jaki przeznaczył na wykonanie syscalli. Liczy się tylko czas konkretnego procesu <b>Czemu suma czasów nie jest równa?</b> Ponieważ jeśli np. proces czeka na I/O <b>Czemu może być większy?</b> Bo wielowątkowość xD ulimit -t 2 && find / <b>Jaki sygnał wysłano?</b> Sigkill ![](https://i.imgur.com/4AeCgs7.jpg) ### Zadanie 7 ![](https://i.imgur.com/jB373UZ.png) ```c static void do_read(int fd) { /* TODO: Spawn a child. Read from the file descriptor in both parent and * child. Check how file cursor value has changed in both processes. */ pid_t pid; off_t cursor; pid = Fork(); if(pid == 0){ /* Child */ cursor = lseek(fd,0,SEEK_CUR); printf("File cursor position before read() @ %ld (pid:%d)\n",cursor,getpid()); if(read(fd,buf,20) != 20) app_error("read error"); cursor = lseek(fd,0,SEEK_CUR); printf("File cursor position after read() @ %ld (pid:%d)\n",cursor,getpid()); } else{ /* Parent */ cursor = lseek(fd,0,SEEK_CUR); printf("File cursor position before read() @ %ld (pid:%d)\n",cursor,getpid()); if(read(fd,buf,20) != 20) app_error("read error"); cursor = lseek(fd,0,SEEK_CUR); printf("File cursor position after read() @ %ld (pid:%d)\n",cursor,getpid()); } exit(0); } ``` ```c static void do_close(int fd) { /* TODO: In the child close file descriptor, in the parent wait for child to * die and check if the file descriptor is still accessible. */ pid_t pid; int child_status; pid = Fork(); if(pid == 0){ /* Child */ close(fd); printf("Closed fd @ %d (pid:%d)\n",fd,getpid()); } else{ /* Parent */ Wait(&child_status); if(fcntl(fd,F_GETFD) == -1) printf("Fd has been closed @ %d (pid:%d)",fd,getpid()); else printf("Fd is still open @ %d (pid:%d)\n",fd,getpid()); } exit(0); } ``` ![](https://i.imgur.com/RL03N92.jpg) ### Zadanie 8 <!-- Gut --> ![](https://i.imgur.com/GhKplyc.png) ```c int board[size],k = 0,selected; /* TODO: A loop is missing here that initializes recursive algorithm. */ while (k < size && k >= 0){ selected = ndselect(size); for(int i=0;i<k;i++) if(conflict(k,selected,i,board[i])) exit(0); board[k] = selected; k++; } ``` ```c static int ndselect(int n) { /* TODO: A loop is missing here that spawns processes and waits for them! */ pid_t pid; int child_status; for(int i=0;i<n;i++){ if((pid = Fork()) == 0) return i; else Waitpid(pid,&child_status,0); } exit(0); } ``` ![](https://i.imgur.com/QqVdoh5.jpg)