---
# System prepended metadata

title: 'Ćwiczenia 1, grupa cz. 10-12, 13 października 2022'
tags: [SO22, pwit, ćwiczenia]

---

# Ćwiczenia 1, grupa cz. 10-12, 13 października 2022

###### tags: `SO22` `ćwiczenia` `pwit`

## Deklaracje

Gotowość rozwiązania zadania należy wyrazić poprzez postawienie X w odpowiedniej kolumnie! Jeśli pożądasz zreferować dane zadanie (co najwyżej jedno!) w trakcie dyskusji oznacz je znakiem ==X== na żółtym tle.

**UWAGA: Tabelkę wolno edytować tylko wtedy, gdy jest na zielonym tle!**


:::danger
|                        | 1     | 2   | 3   | 4   | 5   | 6   | 7   | 8   |
| ----------------------:| ----- | --- | --- | --- | --- | --- | --- | --- |
Miriam Bouhajeb          |   X    |     |  X   | X    | X    | X    |  X   |     |  
Kacper Chmielewski       |   X   |  X  |  X  |  X  |  X  |  X  |     |     |
Jakub Kaczmarek          |       |     |     |     |     |     |     |     |
Jarosław Kadecki         |   X   |  X  |  X  |  X  |     |  X  |  X  |     |
Zuzanna Kania            |   X    |     |     |     |  X   | X    | X    | X    |
Julia Konefał            |   X   |     |   X |  X  |     |   X |     |     |
Daniel Sarniak           |    X   |     |   X  |  X   |  X   |  X   |  X   |  X   |
Paweł Tkocz              |   X    |     |  X   |  X   |  X   |   X  |     |     |
Adrian Walczak           |       |     |     |     |     |     |     |     |
Miłosz Urbanik           |   X   |  X  |     |     |     |  X  |  X  |     |
Tomasz Wołczański        |   X   |  X  |  X  |  X  |     |  X  |     |     |
Radosław Śliwiński       |   X   |  X  |  X  |  X  |  X  |==X==|     |     |
:::





:::info
**Uwaga:** Po rozwiązaniu zadania należy zmienić kolor nagłówka na zielony.
:::



## Zadanie 1
:::success
Autor: Miriam Bouhajeb	
:::
Rodzic-dziecko
Relacja wyglądająca tak, że proces, który tworzy nowy proces 
(poprzez inwokowanie funkcji fork() ) nazywamy rodzicem, a stworzony proces nazywany dzieckiem.

PID - indentyfikator procesu; unikalna liczba służąca do rozróżniania procesu
PGID - identyfikator grupy procesów; zbiór procesów który służy między innymi do sterowania dystrybucją sygnału który jest kierowany do każdego z procesów z tej grupy
PPID - identyfikator rodzica; identyfikator procesu który za pomocą fork() stworzył konkretny proces
Właściciel procesu - użytkownik który utworzył proces i posiada do niego pełne uprawnienia
Wątki jądra - wątki wykonujące kod kernela, całkowicie odrębnione od przestrzeni użykowników, nie mają w niej zaalokowanej pamięci, dlatego w outpucie -ps mają 0 KiB. Także w kolumnie cmd mają nawiasy kwadratowe gdyż nie jest znana nazwa komendy która je utworzyła

Znaczenie poszczególnych znaków w kolumnie STAT możemy poznać, przez użycie `man ps`
![](https://i.imgur.com/D2pHhcq.png)


Proces init() rozpoznamy przez to, że PID jego rodzica = 0, czyli jego PPID = 0. Jest to PID kernela.

![](https://i.imgur.com/3p65but.png)

Procesy które są wątkami jądra nie używają pamięci użytkownika, więc można je rozpoznać po tym, że gdy dodamy vsz do polecenia ps, to wartości w kolumnie VSZ będą równe 0.
![](https://i.imgur.com/DIg8htt.png)

pstree:

![](https://i.imgur.com/9w3td0p.png)


## Zadanie 2
:::success
Autor: Miłosz Urbanik	

![](https://i.imgur.com/239GLyh.png)
:::

* **sierota** - proces, którego proces-rodzic został zakończony.
* Gdy proces zostanie osierocony jądro wykonuje reparenting i jako *PPID* procesu wpisuje 1 - proces init.
* **zombie** - proces, który zakończył się, ale jego wpis w tablicy procesów nie został jeszcze usunięty przez jego rodzica.
* W celu pogrzebania procesu jego rodzic używa systemcall `wait()`. 
* Proces nie może sam siebie pogrzebać, bo nie może zwolnić swojego stosu jądra (robi to rodzic), a usunięcie wpisu tablicy procesów spowodowałoby utracenie informacji o przebiegu wykonania procesu
* Gdyby dzieci mogły czekać na rodzica, to mógłby utworzyć się cykl blokujących wywołań `wait()` - dochodzi do zakleszczenia i blokowania zasobów. Co więcej `wait(int *wstatus)` pozwala na dostęp informacji o procesie, czyli kernel musiałby utrzymywać tę informację, do czasu, aż ostatnie z dzieci jej nie odbierze.
* Gdyby proces mógł czekać na dowolny inny, to kończący się proces musiałby mieć informację o wszystkich procesach, które na niego czekają, aby wysłać odpowiedni sygnał i na dodatek mieć do tego uprawnienia. Znów mamy tu problem, który z czekających procesów jest tym ostatnim, który odbierze informację o statusie.


## Zadanie 3
:::success
Autor: Paweł Tkocz	
![](https://i.imgur.com/YB49N3y.png)

System plików proc jest wirtualnym systemem plików i interfejsem pewnych struktur danych jądra systemu operacyjnego. Zawiera informacje o obecnie istniejących procesach. Większość plików w proc jest tylko do odczytu, ale niektóre jego części można zmieniać (np. niektóre zmienne), wpływając w ten sposób na zachowanie niektórych części jądra systemu.

Zawartość katalogu /proc/66:
![](https://i.imgur.com/aMypvsR.png)

Plik zawierający argumenty programu:
![](https://i.imgur.com/tzUbulz.png)

Plik zawierający zmienne środowiskowe:
![](https://i.imgur.com/LUhlyi3.png)

Znaczenie pól pliku status:
Uid – Identyfikator użytkownika
Gid – Identyfikator grupy użytkowników
Groups – lista grup procesów, które należą do tego procesu
VmPeak – największe zarejestrowane użycie pamięci wirtualnej przez proces
VmSize – rozmiar pamięci wirtualnej procesu
VmRSS – rozmiar zbioru rezydentnego (resident set size)
Threads – liczba wątków w procesie
Voluntary_ctxt_switches – liczba dobrowolnych zmian kontekstu (proces nie ma nic do roboty, bo np. oczekuje na dane albo ukończenie operacji I/O i z tego powodu dobrowolnie zwalnia procesor)
Nonvoluntary_ctxt_switches – liczba niedobrowolnych zmian kontekstu (skończył się kawałek czasu, który procesor przydzielił procesowi i z tego powodu następuje zamiana kontekstu – kolejny w kolejce proces trafia do procesora)


:::

## Zadanie 4
:::success
Autor: Jarosław Kadecki	
![](https://i.imgur.com/OVLDgz9.png)
:::
ps -e | grep X
szukamy Xorg
sudo pmap [PID Xorga]
elementy sekcji można znaleźć w /proc/PID/maps
![](https://i.imgur.com/71DoqOG.png)
![](https://i.imgur.com/HBUz6M6.png)
![](https://i.imgur.com/ogwkWj9.png)

55a7fd838000-55a7fd875000 r--p 00000000 103:03 12191696        /usr/lib/xorg/Xorg - RODATA
55a7fd875000-55a7fda07000 r-xp 0003d000 103:03 12191696        /usr/lib/xorg/Xorg - TEXT
55a7fda07000-55a7fda80000 r--p 001cf000 103:03 12191696          /usr/lib/xorg/Xorg - RODATA
55a7fda80000-55a7fda84000 r--p 00247000 103:03 12191696         /usr/lib/xorg/Xorg - RODATA

Segmenty programu – bloki pamięci o takim samych uprawnieniach i podobnym przeznaczeniu. Jeden segment może zawierać wiele sekcji.

Segment kodu to obszar pamięci zawierający kod maszynowy programu. Segmenty programu są zmapowane do Xorg.

Pamięć anonimowa to pamięć niebędąca powiązana z żadnym plikiem ani obiektem. Powszechnym anonimowym mapowaniem jest stos i sterta wspomniane powyżej. Jest ona oznaczona jako [anon]

Pliki odwzorowane w pamięć (ang. memory-mapped file) to segment pamięci wirtualnej mający bezpośrednie mapowanie co do bajta z jakimś plikiem lub zasobem. Dzięki temu unika się stosowania funkcji systemowych na plikach takich jak read() lub write(), gdyż proces adresuje plik bezpośrednio. Plik może być traktowany jak ciągły obszar w pamięci procesu, dostępny poprzez bezpośrednie operacje pobrania i podstawienia wartości. W pmapie można je znaleść po rozszerzeniu .so.

Kolumny wydruku:

adress – adres początkowy
Kbytes – rozmiar
Mode – uprawnienia rwx
Mapping – plik na jaki zmapowana jest pamięć lub [anon]  / [stack]



## Zadanie 5
:::success
Autor: Kacper Chmielewski	
![](https://i.imgur.com/uyq181m.png)

1. Na początku szukamy pid firefoxa
```
    ps -eo user,pid,ppid,pgid,tid,pri,stat,wchan | grep firefox
```
2. Następnie wywołujemy lsof ze znalezionym pid
```
lsof -p [pid]
```
Oznaczenia w pliku lsof:
 - plik zwykły - REG
 - katalogi - DIR
 - gniazda - np IPv4
 - potoki - FIFO

Kolumna FD:
- cwd - current working directory;
- Lnn - library references (AIX);
- err - FD information error (see NAME column);
- jld - jail directory (FreeBSD);
- ltx - shared library text (code and data);
- Mxx - hex memory-mapped type number xx.
- m86 - DOS Merge mapped file;
- mem - memory-mapped file;
- mmap - memory-mapped device;
- pd - parent directory;
- rtd - root directory;
- tr - kernel trace file (OpenBSD);
- txt - program text (code and data);
- v86 - VP/ix mapped file;

:::

## Zadanie 6
:::success
Autor: Radosław Śliwiński
![](https://i.imgur.com/ACSqjP3.png)

`czas wykonania`: czas spedzony na wykonaniu zadania

`ograniczenie czasu wykonania`: limit nalozony na czas wykonania

Wydruk polecenia `time find /usr`: 0.34s user 0.72s system 84% cpu 1.249 total

Zauwazmy, ze `0.34 + 0.72 != 1.249`. Zeby dowiedziec sie dlaczego tak sie dzieje, warto wiedziec co oznacza `user`, `system` i `total`.

`user`: czas przeznaczony w trybie uzytkownika na wykonanie procesu w poleceniu `time`

`system`: czas przeznaczony na wykonywanie roznych `syscall` wywolanych przez proces bedacy argumentem `time`

`total`: rzeczywisty czas od rozpoczecia do zakonczenia procesu

Teraz jak juz wiemy, co oznacza wydruk, mozemy dojsc do pewnych wnioskow. Czas `total` jest wiekszy niz suma `user` i `system` poniewaz w `total` wlicza sie czas uzyty przez inne procesy, oraz czas w ktorym proces ktorego czas wykonania miezymy jest zablokowany (np przez czekanie na I/O). Moze tez dojsc do sytuacji w ktorej czas `user` jest wiekszy od `total`. Moze sie tak stac, gdy aplikacja uzywa wielu watkow procesora, a dla kazdego watku, czas `user` jest liczony osobno, i na koniec sumowany.

Po nalozeniu limitu wykonania, proces jest zabijany sygnalem `SIGXCPU` 
:::

## Zadanie 7
:::success
Autor: Zuzanna Kania	

![](https://i.imgur.com/Qos7DtO.png)

![](https://i.imgur.com/C8S6uhs.jpg)

Offset jest przechowywany bezpośrednio przy otwartym pliku, a file descriptory procesów pokrewnych wskazują na tę samą instancję otwartego pliku zatem offset mają "wspólny". Funkcja close natomiast zwalnia tylko file descriptor konkretnego procesu, a instancję otwartego pliku usuwa tylko wtedy, gdy zamykany file descriptor jest ostatnim wskazującym na tę instancję.

Kod funkcji:
```lang=c
static void do_read(int fd)
{
    pid_t pid;
    size_t to_read;
    pid = Fork();
    if (pid == 0)
        to_read = LINE2;
    else
        to_read = LINE1;
    printf("In process of pid: %d | Current position: %ld\n", getpid(), lseek(fd, 0, SEEK_CUR));
    Read(fd, buf, to_read);
    printf("Read text: %s\n", buf);

    exit(0);
}

static void do_close(int fd)
{
    Fork();
    if (fcntl(fd, F_GETFD) != -1)
    {
        close(fd);
        printf("In process of pid: %d | File was open, now closed\n", getpid());
    }
    else
    {
        printf("In process of pid: %d | File already closed\n", getpid());
    }

    exit(0);
}
```
:::

## Zadanie 8
:::success
Autor: Daniel Sarniak	

![](https://i.imgur.com/o0ALeMt.png)

```lang=c
#include "csapp.h"

static int conflict(int x1, int y1, int x2, int y2) {
  return x1 == x2
    || y1 == y2
    || x1 + y1 == x2 + y2
    || x1 - y1 == x2 - y2;
}

static void print_line_sep(int size) {
  for (int i = 0; i < size; ++i) 
    printf("+---");
  printf("+\n");
}

static void print_board(int size, int board[size]) {
  for (int i = 0; i < size; ++i) {
    print_line_sep(size);
    for (int j = 0; j < size; ++j)
      printf("|%s", board[i] == j ? " Q " : "   ");
    printf("|\n");
  }
  print_line_sep(size);
  printf("\n");
}

static int ndselect(int n) {
  /* TODO: A loop is missing here that spawns processes and waits for them! */
  if (n == 0)
  {
    return 0;
  }

  pid_t pid;
  pid = fork();
  if (pid < 0)
  {
    app_error("%d: fork error", pid);
  }
  else if(pid != 0)                   /*parent*/
  {
    Waitpid(pid, NULL, 0);
    return n;
  }
  else
  {
    return ndselect(n-1);     /*child*/
  }
    
}


int main(int argc, char **argv) {
  if (argc != 2)
    app_error("Usage: %s [SIZE]", argv[0]);

  int size = atoi(argv[1]);

  if (size < 3 || size > 9)
    app_error("Give board size in range from 4 to 9!");

  int board[size];

  /* TODO: A loop is missing here that initializes recursive algorithm. */

  for (int i = 0; i < size; i++) 
  {
        board[i] = ndselect(size-1);
        
        for (int j = 0; j < i; j++)
        {
          if (conflict(i, board[i], j, board[j]))
            {
              exit(0);
            }
        }
        
  }
  printf("\n[%d]: \n", getpid());
  print_board(size, board);

  return 0;
}

```
![](https://i.imgur.com/nV97WBb.png)

Na powyższym obrazku, w czerwonych okręgach widać proces budowania następującego ułożenia hetmanów.

![](https://i.imgur.com/FHudMjm.png)
![](https://i.imgur.com/Okw23h1.png)

:::