# SO Lista 3 ## Zadanie 1 Git ![](https://i.imgur.com/eXHeTB1.png) ### Osierocony rodzic padł, ale proces żyje (było wcześniej) ### Zadanie drugoplanowe proces lub grupa procesów działąjąca w tle ### Lider sesji zazwyczaj shell, program zarządzający grupami procesów, czyli <b>sesją</b>. Kooperuje z kernelem za pomocą sygnałów, syscalli <a class="anchor hidden-xs" href="#Terminal-sterujący" title="Terminal-sterujący" smoothhashscroll=""><span class="octicon octicon-link"></span></a> ### Termianl sterujący urządzenie znakowe, odpowiada za efekt wpisywanych przez nas komend do emulatora, porozumiewa się z procesami, zarządza uprawnieniami (r/w), mówi które są pierwszoplanowe i drugoplanowe (tldr terminal z którego startuje proces) ### Kto jest rodzicem sleepa? bash -i (interaktywny bash) ### Co się dzieje z sesją która utraci terminal sterujący? Wszystkie procesy sesji dostają sygnał SIGHUP ### Steps 1. xterm -e 'bash -i' 2. sleep 1000 & ps ax -o pid,ppid,command | grep sleep 3. kill -s SIGKILL [PID] 4. ps ax -o pid,ppid,command | grep sleep 5. Widać że teraz ma systemd ## Zadanie 2 Git ![](https://i.imgur.com/IDFhBB7.png) ### Jak zachowuje się sterownik terminala działającego w trybie kanonicznym? Tryb kanoniczny powoduje, że wejście terminala jest przetwarzane w liniach Znakiem linii może być: <ul> <li>'\n' -> end line</li> <li>EOF -> End Of File</li> <li>EOL -> End Of Line</li> <li>CR -> Carrige Return</li> </ul> Zatem wiemy że program nie zacznie wykonywać naszych poleceń dopóki nie damy końca linii ### Posługując się rysunkiem wytłumacz w jaki sposób przetwarza on znaki (w tym kody sterujące) wchodzące do kolejki wejściowej i kolejki wyjściowej ![](https://i.imgur.com/SXqfpTR.png) 1. Jeśli echo jest włączone to jest połączenie między kolejką wejścia i wyjścia 2. Size jest skończony max(max_canon, max_input) 3. Większość procesingu w tym module implementuje <b>terminal line discipline</b> 4. Specjalne znaki są interpretowane na wejściu w inpucie w odpowiedni sposób wg flag ### Jaką konfigurację terminala powinien zmienić program na czas wpisywania hasła przez użytkownika? Echo off, wtedy nie widać co piszemy ### Czemu edytory takie jak vi, konfiguruja sterownik terminala do pracy w trybie niekanonicznym? 1. Niektóre komendy vima są zbindowane pod te same znaki co <b>special chars</b> (np. ?) 2. komendy mogą być nieoddzielone przez '\n' ## Zadanie 3 Git ![](https://i.imgur.com/IpqF4kJ.png) ![](https://i.imgur.com/xh2OLUe.png) ### Sygnały związane z zarządaniem zadaniami <ul> <li><b>intr -> </b> wysyła sygnał przerwania</li> <li><b>quit -> </b> wysyła sygnał zamknięcia</li> <li><b>switch -></b> włącza iną warstwę powłoki</li> <li><b>susp -></b> wysyła sygnał stop</li> </ul> ### Sygnały związane z edycją wiersza <ul> <li><b>erase -></b> kasuje ostani wprowadzony znak</li> <li><b>kill</b></li> <li><b>eof -></b> wysyła znak końca pliku</li> <li><b>eol -></b> wysyła znak końca wiersza</li> <li><b>werase -></b> kasuje ostatnio wprowadzone słowo</li> <li><b>rprnt -></b> powtarza bieżący wiersz</li> <li><b>lnext -></b> wprowadza kolejny znak w cudzysłow</li> <li><b>start/stop -></b> wznawia/zatrzymuje wyświetlanie</li> </ul> ### Jaką procedurę obsługi błędu musi zainstalować terminal? SIGWINCH ### Jaką procedurą można wczytać nowy rozmiar okna? ioctl(), struktura winsize ## Zadanie 4 Git ![](https://i.imgur.com/8j5kJZ8.png) ### Urządzenie terminala to samo co controlling terminal(?) [] <a href="#Termianl-sterujący" title="Terminal-sterujący" smoothhashscroll>patrz zad 1</a> ### Działanie znaków sterujących switch "-e" w echo pozwala na interpretację znaków po '\\' jako bajtów więc możemy używać kodów sterujących echo -e '\\007' -> w xterime odpal dzwonek (nie działa w kitty) [kitty -> free and open-source graphics processing unit (GPU)-accelerated terminal emulator for Linux and macOS focused on performance and features] echo -e '\\008' -> backspace echo -e '\\0x0a' -> newline Działa w programach C, shellu, pythonie itd ### Sekwencje CSI '\\033[...]' -> zaczęcie sekwencji '5A' -> Rusza kursor o 5 komórek w górę ![](https://i.imgur.com/l4m8JWM.png) ### Czemu zachowanie cat jest inne niż powłoki poleceń? Pewnie dlatego że cat nie interpretuje domyślnie w szczególny sposób naszych znaków z '\\' jako bajtów, ale np esc na klawiaturze już działa ## Zadanie 5 Git ![](https://i.imgur.com/UEpU4vo.png) stty -a 1. sleep 1000; ctrl+z; bg 1; sygnał to SIGTSTP 2. Ctrl+s wstrzymuje output, ctrl+q wznawia, nie ma to nic wspólnego z procesem 3. SIGTTIN, pewnie dlatego, że miał odpalonego read() i przenieśliśmy go do bg (lub SIGSTOP) 4. «to stop» powoduje, że SIGTTOU zostanie wysłany jeśli bg process będzie pisał do stdout 5. Znaki kontrolne są przetwarzane "surowo", tzn. w outpucie są raw bajty, a nie notacja np. Ctrl+c = '^C' lub esc = '^\[' 6. cat | xxd ## Zadanie 6 Git ![](https://i.imgur.com/UWYCNdk.png) ![](https://i.imgur.com/X5xiOFg.png) ### Czemu longjmp zapisuje wartość na stos przed retem? Bo w r11 wcześniej wstawiliśmy RIP z Jmpbuf ### Dlaczego Jmpbuf nie ma wszystkich rejestrów procesora? Bo jest funckją jak każda inna (setjmp), dokumentacja mówi że caller saved mogą być używane przez funckje wołane, więc zapisujemy tylko callee saved (bo mamy pewność, że są prawdziwe) ```c /* 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); ``` ```clike= _JB_RBX = 0 _JB_RBP = 1 # poczatek stosu _JB_R12 = 2 _JB_R13 = 3 _JB_R14 = 4 _JB_R15 = 5 _JB_RSP = 6 # biezaca lokalizacja na stosie _JB_RIP = 7 # wskaznik instrukcji .text .globl Setjmp .type Setjmp,@function Setjmp: # int Setjmp(Jmpbuf env (%rdi)): movq (%rsp),%r11 # przenosimy adres powrotu do r11 (kopia zapasowa) movq %rbx,(_JB_RBX * 8)(%rdi) # przenosimy rejestry do jmp_buf 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: # noreturn void Longjmp(Jmpbuf env (%rdi), int val (%esi)): movq (_JB_RBX * 8)(%rdi),%rbx # przywracamy rejestry z jmp_buf 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 # przenosimy drugi argument do %rax, jesli jest rowny # 0, to zmieniamy go na 1 testl %eax,%eax jnz 1f # if (!eax) eax = 1; else goto 1; incl %eax 1: movq %r11,(%rsp) # umieszczenie starego %rip (z %r11) na stos ret .size Longjmp, . - Longjmp ``` ## Zadanie 7 Git ![](https://i.imgur.com/lEXO8W4.png) ```c static void signal_handler(int signo) { /* TODO: Something is missing here! */ siglongjmp(env,signo); } /* 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]; int n,val; /* TODO: Something is missing here! Use Read() to get line from user. */ if(!(val = sigsetjmp(env,1))){ alarm(5); n = Read(STDIN_FILENO,line,sizeof(line)); alarm(0); line[n] = '\0'; *num_p = atoi(line); } return val; } ``` ### Czemu po zmianie przestał działać? Bo przekazujemy mu starą maskę z zablokowanym sigalarm ## Zadanie 8 Git ![](https://i.imgur.com/PeAsuWL.png) ```c static noreturn void coro_switch(int v) { coro_t *curr = running; /* TODO: Use description above to implement the body. */ /* TAILQ_HEAD(HEADNAME, TYPE) head; TAILQ_REMOVE(TAILQ_HEAD *head, TYPE *elm, TAILQ_ENTRY NAME); The macro TAILQ_REMOVE() removes the element elm from the tail queue. */ if(v == EOF) TAILQ_REMOVE(&runqueue,curr,co_link); if(TAILQ_EMPTY(&runqueue)) Longjmp(dispatcher,1); if(TAILQ_NEXT(curr,co_link)==NULL) running = TAILQ_FIRST(&runqueue); else running = TAILQ_NEXT(curr,co_link); Longjmp(running->co_ctx,v); } ```