# Ćwiczenia 3, grupa cz. 10-12, 27 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!**
:::warning
Dzisiaj deklarujemy zadania 5-8 listy 3.
:::
:::danger
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| ----------------------:| ----- | --- | --- | --- | --- | --- | --- | --- |
Miriam Bouhajeb | ==X== | X | X | X | X | X | X | |
Kacper Chmielewski | X | X | X | X | X | X | | |
Jan Jankowicz | | | | | 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 | | |
Daniel Sarniak | X | X | X | X | X | X | X | X |
Paweł Tkocz | X | X | X | | X | X | X | |
Miłosz Urbanik | X | X | X | | X | X | X | |
Tomasz Wołczański | | | X | | X | X | X | |
Radosław Śliwiński | 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
Proces osierocony - taki którego rodzic został zabity, a on nadal żyje. zostaje on przepięty zazwyczaj do init 1
Zadanie drugoplanowe to takie zadanie ktore nie blokuje okna terminalu
`xterm -e 'bash -i`
`ps ax -o pid,ppid,command | grep xterm` PID
`sudo strace -e trace=signal -p PID`
`sleep 1000 &`
`ps ax -o pid,ppid,command | grep xterm` PID
`sudo kill -s 9 PID`
`ps ax -o pid,ppid,command | grep xterm` PID
Wszystkie procesy w sesji maja ten sam SID ktory jest ten sam jak PID procesu który użył funkcji setsid() czyli stał się liderem procesu.
Sesja to grupa procesow ktora jest pod kontrolą jednego użytkownika.



:::
## Zadanie 2
:::success
Autor: Jarosław Kadecki



In canonical mode input processing, terminal input is processed in units
of lines. A line is delimited by a newline '\n' character, an end-of-
file (EOF) character, or an end-of-line (EOL) character. A terminal device associated with a terminal device file may operate in full-duplex mode, so that data may arrive even while output is occurring. Each terminal device file has associated with it an input queue, into
which incoming data is stored by the system before being read by a
process.
When a process writes one or more bytes to a terminal device file, they are processed according to the c_oflag field. The implementation may provide a buffering mechanism; as such, when a call to write(2) completes, all of the bytes written have been
scheduled for transmission to the device, but the transmission will not
necessarily have been completed.


:::
## Zadanie 3
:::success
Autor: Radosław Śliwiński
Przykladowe wywolanie `stty -a`:

Sygnaly zwiazane z __zarzadzaniem zadaniami__:
* `intr` wysyla sygnal przerwania `SIGINT`
* `quit` wysyla sygnal zamkniecia `SIGQUIT`
* `susp` wysyła do terminala sygnał stop `SIGSTP`
Znaki, ktore terminal wykorzystuje do __edycji wiersza__:
* `erase` kasuje ostatni wprowadzony znak
* `kill` kasuje bieżącą linię
* `eof` wysyła znak końca pliku (końca wejścia)
* `eol` wysyła znak końca linii
* `werase` kasuje ostatnie wprowadzone słowo
* `rptnt` spowoduje ponowne wypisanie bieżącej linii
* `lnext` spowoduje, że następny znak będzie w cudzysłowie
Kernel zachowuje strukture `winsize` dla kazdego terminala i emulatora terminala:
```
struct winsize {
unsigned short ws_row; /* rows, in characters */
unsigned short ws_col; /* columns, in characters */
unsigned short ws_xpixel; /* horizontal size, pixels (unused) */
unsigned short ws_ypixel; /* vertical size, pixels (unused) */
};
```
Zeby zmienic rozmiar terminala program musi zaimplementowac obsluge sygnalu `SIGWINCH`.
Nowy rozmiar okna mozna wczytac procedura `ioctl`
:::
## Zadanie 4
:::success
Autor: Kacper Chmielewski

Prezentacja na żywo
:::
## Zadanie 5
:::success
Autor: Paweł Tkocz

Bieżąca konfiguracja terminala: stty -a
1.
sleep 1000
CTRL-Z (echo $? Da wynik 148. 148-128 = 20 czyli SIGSTP)
bg – przeniesie zadanie do wykonania w tle
2.
find /
CTRL+S - wykonuje stop wypisywania outputu (ale program wciąż się wykonuje)
CTRL+Q - sprawia, że wynik programu jest znowu wypisywany na ekran
Jest to implementacja tzw. software control flow, nie wiąże się z wysłaniem żadnego sygnału.
Geneza software control flow:
Jeśli np drukarka nie nadążała z drukowaniem wyniku (dostawała za szybko dane do wydruku), teleprinter mógł wysłać XOFF flow control command (CTRL+S), aby powiedzieć "przestań przesyłać dane na jakiś czas”. Następnie mógł wysłać XON flow control command (CTRL+Q), komunikując "nadrobiłem zaległości, możesz kontynuować”. Możliwości wysyłania tych komunikatów pozostały aż do dzisiejszych terminali.
3.
cat - &
cat z opcją - oznacza, że program będzie czytał ze standardowego wejścia i to co przeczyta, wypisze od razu na standardowe wyjście.
Jeżeli mamy wiele zadań aktywynych (drugoplanowych), które chcą czytać ze standardowego wejścia, pojawia się problem. Nie wiadomo które zadanie powinno otrzymać wpisywane znaki, nie powinno być wyścigu miedzy nimi. Aby uniknąć takich problemów, tylko zadanie pierwszoplanowe może czytać z STDIN terminala. Kiedy zadanie drugoplanowe próbuje czytać z STDIN to dostaje sygnał SIGTTIN i zostaje wstrzymane.
To właśnie stało się z cat - &
4.
Domyślna konfiguracja terminala jest taka, że zadanie drugoplanowe może pisać na standardowe wyjście (wpisy z różnych zadań drugoplanowych najwyżej będą się przeplatać). Jeśli tego nie chcemy, możemy włączyć flagę tostop poleceniem:
Stty tostop
Wtedy, kiedy jakiś drugoplanowy proces będzie próbował napisać coś na standardowe wyjście zostanie wstrzymane, wysłaniem sygnału SIGTTOU
Przed stty tostop komenda
cat /etc/shells &
wypisała na stdout, po włączeniu tostop nic nie wypisała i została wstrzymana
5.
stty -echoctl
Wyłączenie tej flagi powoduje jedynie, że sygnały są inaczej wypisywane na wyjście, robią jednak dokładnie to samo
Jeśli właczona jest flaga ECHO (domyślnie jest włacznona), to znaki kontrolne ASCII (od 0 do 37) inne niż ASCII TAB, ASCII NL, i START oraz STOP są wypisywane jako ^X , gdzie X to znak otrzymany przez dodanie ósemkowej 100 do znaku kontrolnego.
Zatem z flagą echoctl wypsanie CTRL+C spowoduje wypisanie "^C"
Natomiast z wyłączoną flagą echoctl CTRL+C spowoduje wypisanie znaku "?"
:::
## Zadanie 6
:::success
Autor: Zuzanna Kania

Procedura `Setjmp` zapisuje aktualny stan rejestrów do struktury `Jmpbuf`. Zauważmy, że zachowywane są jedynie rejestry *callee-saved*, czyli te, za których niezmienność odpowiada procedura wołana, oraz %rsp i %rip.
Procedura `Longjmp` przepisuje wartości zapamiętane w `Jmpbuf` do odpowiednich rejestrów i wraca w to samo miejsce, w które wraca `Setjmp`.
Na szczycie stosu przechowywany jest adres powrotu. W liniach 38 i 43 ustawiamy zatem adres powrotu na ten zapisany w kontekście `Setjmp` w liniach 15 i 23.
```c=1
/* Setjmp & longjmp implementation without sigprocmask */
typedef struct {
long rbx;
long rbp;
long r12;
long r13;
long r14;
long r15;
void *rsp;
void *rip;
} Jmpbuf[1];
int Setjmp(Jmpbuf env);
noreturn void Longjmp(Jmpbuf env, int val);
```
```=1
_JB_RBX = 0
_JB_RBP = 1
_JB_R12 = 2
_JB_R13 = 3
_JB_R14 = 4
_JB_R15 = 5
_JB_RSP = 6
_JB_RIP = 7
.text
.globl Setjmp
.type Setjmp,@function
Setjmp:
movq (%rsp),%r11
movq %rbx,(_JB_RBX * 8)(%rdi)
movq %rbp,(_JB_RBP * 8)(%rdi)
movq %r12,(_JB_R12 * 8)(%rdi)
movq %r13,(_JB_R13 * 8)(%rdi)
movq %r14,(_JB_R14 * 8)(%rdi)
movq %r15,(_JB_R15 * 8)(%rdi)
movq %rsp,(_JB_RSP * 8)(%rdi)
movq %r11,(_JB_RIP * 8)(%rdi)
xorl %eax,%eax
ret
.size Setjmp, . - Setjmp
.globl Longjmp
.type Longjmp,@function
Longjmp:
movq (_JB_RBX * 8)(%rdi),%rbx
movq (_JB_RBP * 8)(%rdi),%rbp
movq (_JB_R12 * 8)(%rdi),%r12
movq (_JB_R13 * 8)(%rdi),%r13
movq (_JB_R14 * 8)(%rdi),%r14
movq (_JB_R15 * 8)(%rdi),%r15
movq (_JB_RSP * 8)(%rdi),%rsp
movq (_JB_RIP * 8)(%rdi),%r11
movl %esi,%eax
testl %eax,%eax
jnz 1f
incl %eax
1: movq %r11,(%rsp)
ret
.size Longjmp, . - Longjmp
```
:::
## Zadanie 7
:::success
Autor: Jan Jankowicz

```c=1
static void signal_handler(int signo) {
siglongjmp(env, signo); // skaczemy do ustawionego w readnum() miejsca skoku z numerem przechwyconego sygnału
}
/* If interrupted by signal, returns signal number. Otherwise converts user
* provided string to number and saves it under num_p and returns zero. */
static int readnum(int *num_p) {
char line[MAXLINE]; // bufor do czytania liczb podawanych przez użytkownika
int n; // ilość przeczytanych znaków
int jmp_sig = sigsetjmp(env, 1); // ustawiamy punkt skoku ze środowiskiem env z zachowaną maską sygnałów
if (jmp_sig) { // jeśli skoczyliśmy do tego miejsca za pomocą siglongjmp
return jmp_sig; // zwracamy numer przechwyconego sygnału
}
alarm(1); // nastawiamy alarm
n = Read(STDIN_FILENO, line, MAXLINE); // pobieramy liczbę od użytkownika
line[n] = '\0'; // kończymy przeczytaną linię znakiem NULL
alarm(0); // resetujemy alarm (inaczej zostałby wysłany sygnał SIGALRM po poprawnym przekazaniu liczby)
*num_p = atoi(line);
return 0;
}
```
Użycie do wykonania nielokalnych skoków funkcji setjmp(env) i longjmp(env) spowoduje, że program przestanie się poprawnie zachowywać. Jest to spowodowane niezachowaniem maski sygnałów.
Naturalnym zachowaniem podczas przechwycenia sygnału przez handler jest ustawienie w masce sygnałów blokady na aktualnie obsługiwany sygnał. Ponieważ wykonujemy jednak skok do procedury readnum(), a nie powrót z metody obsługującej sygnał, to ciągle mamy do czynienia z np. zablokowanym sygnałem SIGALRM, co uniemożliwia obsługę tego sygnału w przyszłości (chyba że odblokujemy go manualnie w kodzie w innym miejscu), a tym samym powoduje niepoprawne działanie programu. Stąd konieczność przywracania w czasie skoku starej maski sygnałów, co jest możliwe dzięki metodom z prefiksem 'sig'.
:::
## Zadanie 8
:::success
Autor: Daniel Sarniak

```c=
static noreturn void coro_switch(int v) {
coro_t *curr = running;
/* TODO: Use description above to implement the body. */
if (v == EOF) {
TAILQ_REMOVE(&runqueue, running, co_link);
}
if (TAILQ_EMPTY(&runqueue)) {
Longjmp(dispatcher, 1);
}
if (TAILQ_NEXT(curr, co_link)) {
running = TAILQ_NEXT(curr, co_link);
} else {
running = TAILQ_FIRST(&runqueue);
}
Longjmp(running->co_ctx, v);
}
```
**Zmiana kontekstu** to proces przechowywania stanu procesu lub wątku, dzięki czemu można go przywrócić i wznowić wykonanie w późniejszym momencie, a następnie przywrócić inny, wcześniej zapisany stan. Pozwala to wielu procesom współużytkować jedną jednostkę centralną (CPU).
**Wielozadaniowość kooperacyjna** to technika wielozadaniowości, która umożliwia dwóm lub większej liczbie programów współdzielenie czasu przetwarzania i zasobów procesora. W tej technice programy w kolejce przetwarzania muszą równomiernie alokować zasoby procesorów między sobą.
:::