---
# System prepended metadata

title: Lista 7
tags: [sju21, ćwiczenia]

---

# Lista 7

###### tags: `sju21` `ćwiczenia`

## Deklaracje

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

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

:::danger
|                       | 7-1 | 7-2 | 7-3 | 7-4 | 7-5 | 7-6 |
| ---------------------:| --- | --- | --- | --- | --- | --- |
|           Jacek Bizub |  X  |  X  |  X  |  X  |  X  |  X  | 6
|     Wojciech Jasiński |  X  |  X  |  X  |     |     |     | 3
|        Artur Juraszek |     |     |     |     |     |     | 0
|     Michał Myczkowski |     |     |     |     |     |     | 0
|       Michał Odorczuk |  X  |  X  |  X  |  X  |  X. |  X. | 6
|       Damian Ratajski |     |     |     |     |     |     | 0
|         Łukasz Siudek |     |     |     |     |     |     | 0
|           Błażej Sowa |  X  |  X  |==X==|     |  X. |     | 4
|         Andrzej Turko |  X  |==X==|  X  |  X  |  X  |  X  | 6
|  Maksymilian Zawartko |  X  |  X  |     |     |  X. |  X. | 4
:::

## Zadanie 7-1

:::info
Autor: Wojciech Jasiński
:::
  * jakie funkcje pełni terminal działający w trybie kanonicznym?
    - wejście przetwarzane w liniach (kończone '\n', EOF lub EOL)
      - wczytywanie blokuje aż cała linia zostanie wczytana (<= `MAX_CANON` znaków)
      - znaki specjalne: `ERASE` (ostatni znak w aktualnej linii), `KILL` (cała aktualna linia)
    - wyjście:
      - może buforować (zależnie od implementacji)
      - może podmieniać znaki (np. <TAB> na spacje albo CR -> NL)
  * wytłumacz w jaki sposób sterownik terminala przetwarza znaki (w tym kody sterujące) wchodzące do kolejki wejściowej i wyjściowej.
    1) terminal -> proces
       1. sterownik sprawdza, czy znak jest specjalny (i czy odpowiednia opcja jest włączona)
       2. sterownik wykonuje specjalną akcję lub zapisuje znak (może zmodyfikowany) do kolejki wejściowej
       3. proces odbiera znak z kolejki (przez stdin)
    2) proces -> terminal
       1. jakiś proces pisze do kolejki wyjściowej przez stdout
       2. sterownik dostaje znak, być może go tłumaczy
       3. sterownik decyduje, czy pora wypisać kolejkę wyjściową do urządzenia
  * wskaż kody sterujące w wydruku polecenia `stty -a` i wyjaśnij jaką pełnią funkcję
      ```
         eof = ^D; eol = <undef>; eol2 = <undef>; erase = ^?; intr = ^C;
         kill = ^U; lnext = ^V; quit = ^\; rprnt = ^R;
         start = ^Q; stop = ^S; susp = ^Z; swtch = <undef>; werase = ^W
      ```
      Funkcje: [man termios(4)](http://man.netbsd.org/termios.4): Special Characters, `man stty(1)`: Special characters

## Zadanie 7-2

:::info
Autor: Maksymilian Zawartko
:::

Sterownik terminala zapewnia dostęp do urządzeń terminalowych (lokalnych i zdalnych). Odpowiada zarówno za przepływ danych, jak i ich format.

Polecenia do modyfikacji `termios` i `winsize`:
1. `TIOCSETA struct termios *term` - ustawia `termios`; jest wołane przez `tcsetattr(3)` z opcją `TCSANOW`. `TCSANOW` - zmiana jest dokonywana od razu.
2. `TIOCSETAW struct termios *term` - czeka na zakończenie wyjścia i ustawia `termios`; jest wołane przez `tcsetattr(3)` z opcją `TCSADRAIN`. `TCSADRAIN` - zmiana jest dokonywana po przetransmitowaniu całego outputu zapisanego do deksryptora pliku do terminala. `TCSADRAIN` powinno być używane przy zmianie parametrów wyjścia.
3. `TIOCSETAF struct termios *term` - czeka na zakończenie wyjścia i wyczyszczenie wejścia, następnie ustawia `termios`; jest wołane przez `tcsetattr(3)` z opcją `TCSAFLUSH`. `TCSAFLUSH` - j.w., przy czym to, co zostało wpisane, ale jeszcze nie zatwierdzone, jest odrzucane.
4. `TIOCSFLAGS int *state` - bity inta pod wskaźnikiem `state` kodują stan portu szeregowego:
	* `TIOCFLAG_SOFTCAR` - ignore hardware carrier.
	* `TIOCFLAG_CLOCAL` - ustaw flagę `CLOCAL` przy otwarciu.
	* `TIOCFLAG_CRTSCTS` - ustaw flagę `CRTSCTS` przy otwarciu.
	* `TIOCFLAG_MDMBUF` - ustaw flagę `MDMBUF` przy otwarciu.
5. `TIOCSWINSZ struct winsize *ws` - ustawia rozmiar okna.

Niektóre porty szeregowe mogą nie obsługiwać `TIOCSFLAGS`.
				 
Są 3 (1, 2 i 3 są bardzo podobne) polecenia do ustawiania konfiguracji terminala, bo 1, 2, 3 operują bezpośrednio na strukturze `termios`, 4 - na trochę innym poziomie abstrakcji, a 5 - na `winsize`.

input flags:
```bash=
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany -imaxbel -iutf8
```

output flags:
```bash=
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
```

control flags:
```bash=
-parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
```

local flags:
```bash=
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke -flusho -extproc
```

`ICRNL` - zamień CR na NL przy wejściu.
`ONLCR` - zamień NL na CR-NL przy wyjściu.
`ISIG` - po wpisaniu jednego ze znaków `INTR`, `QUIT`, `[D]SUSP` generowany jest odpowiedni sygnał (`SIGINT`, `SIGQUIT`, `SIGTSTP`).
`ECHOCTL` - wypisuj otrzymywane znaki kontrolne jako `^(Char)`.

## Zadanie 7-3

:::info
Autor: Błażej Sowa
:::

> **Urządzenie terminala** zajmuje się interpretacją [znaków i sekwencji sterujących](https://en.wikipedia.org/wiki/ANSI_escape_code) oraz przetwarzaniem zdarzeń od użytkownika, które zostają zamienione na znaki lub sekwencje znaków. Posługując się poleceniem `«echo -e ’sterujacy’; read»` zaprezentuj działanie znaków sterujących oraz sekwencji `«CSI»`. Uruchom polecenie `«cat»` i sprawdź jak zachowuje się naciśnięcie klawiszy funkcyjnych i kursora. Czemu w tym przypadku zachowanie programu «cat» jest inne niż powłoki poleceń?
Następnie ściągnij i zainstaluj bibliotekę [python-evdev] i przeczytawszy rozdział `„Quick start”` napisz prosty programik, przy pomocy którego zaprezentujesz dane zwracane przez pliki urządzenia myszki i klawiatury dostępne w katalogu `«/dev/input/by-path»`.

[python-evdev]: https://python-evdev.readthedocs.io/en/latest/

Znaki sterujące:
```bash
# Backspace
echo -ne 'asdf\010\010  '; read
# Form Feed
echo -ne 'asdf\014asda'; read
# Carriage Return
echo -ne 'asdf\015asda'; read
```
Sekwencje sterujące CSI (`\033` to znak ESC):
```bash
# Erase in Line
echo -ne 'asdf\033[1Kfdsa'; read
# Slow Blink
echo -ne 'asdf\033[5mfdsa'; read
# Cursor down
echo -ne 'asdf\033[5Bfdsa'; read
# Cursor position
echo -ne 'asdf\033[20;20Hfdsa'; read
# Set Background color
echo -ne 'asdf\033[42m fdsa'; read
```

Co się dzieje jak uruchomimy `cat` i naciśniemy klawisze funkcyjne?:
```
^[[D^[[C^[[A^[[D^[[B^[[A^A^K^K
```
Program `cat` nie obsługuje znaków i sekwencji sterujących. Przy włączonej opcji `ECHOCTL`, po naciśnięciu klawiszy funkcyjnych dostaje na wejściu ciąg znaków przetłumaczony przez sterownik terminala i nie interpretuje ich.

programik:
```python=
#!/usr/bin/env python3
from evdev import InputDevice
from selectors import DefaultSelector, EVENT_READ

mouse = InputDevice('/dev/input/by-path/platform-AMDI0010:03-event-mouse')
keyboard = InputDevice('/dev/input/by-path/platform-i8042-serio-0-event-kbd')

selector = DefaultSelector()
selector.register(mouse, EVENT_READ)
selector.register(keyboard, EVENT_READ)

while True:
    for key, _ in selector.select():
        device = key.fileobj
        for event in device.read():
            if device.fd == mouse.fd:
                print("MOUSE: ", end='')
            else:
                print("KEYBOARD: ", end='')
            print(event)
```

## Zadanie 7-4

:::info
Autor: Michał Odorczuk
:::

```
// Setting up pipe
rpipe = fp->f_pipe;
lock = rpipe->pipe_lock;
error = 0;
mutex_enter(lock);
wpipe = rpipe->pipe_peer;

/*
* Detect loss of pipe read side, issue SIGPIPE if lost.
*/
if (wpipe == NULL || (wpipe->pipe_state & PIPE_EOF) != 0) {
    mutex_exit(lock);
    return EPIPE;
}
```

```
while (uio->uio_resid) /*	remaining bytes	to copy	*/
```

```
space = bp->size - bp->cnt;
// If not enough space and less than PIPE_BUF remains, wait
if ((space < uio->uio_resid) && (uio->uio_resid <= PIPE_BUF))
    space = 0;
```

Jeśli space > 0 to uiomove, w przeciwnym wypadku czekamy aż zwolni się miejsce

```
/*
* Transfer size is minimum of uio transfer
* and free space in pipe buffer.
*/
if (space > uio->uio_resid)
	size = uio->uio_resid;
else
	size = space;
segsize = bp->size - bp->in;
if (segsize > size)
	segsize = size;

/* Transfer first segment */
mutex_exit(lock);
// Support atomic write for up to segment size
error = uiomove((char *)bp->buffer + bp->in, segsize,
	uio);
// We do not have to keep atomicity now
if (error == 0 && segsize < size) {
	error = uiomove(bp->buffer, size - segsize, uio);
}
mutex_enter(lock);

bp->in += size; // Move forward by size bytes
if (bp->in >= bp->size) {
	KASSERT(bp->in == size - segsize + bp->size);
	bp->in = size - segsize;
}

bp->cnt += size;
```
else
```
/*
* If the "read-side" has been blocked, wake it up now.
*/
cv_broadcast(&wpipe->pipe_rcv);

/*
* We have no more space and have something to offer,
* wake up select/poll.
*/
if (bp->cnt)
    pipeselwakeup(wpipe, wpipe, POLL_IN);
pipeunlock(wpipe);
// Wait for write-pipe to have any interaction
// It may mean that there is enough space now
error = cv_wait_sig(&wpipe->pipe_wcv, lock);
(void)pipelock(wpipe, false);
/*
* If read side wants to go away, we just issue a signal
* to ourselves.
*/
if (wpipe->pipe_state & PIPE_EOF) {
    error = EPIPE; // SIGPIPE once again
    break;
}
```


## Zadanie 7-5

:::info
Autor: Andrzej Turko
:::

> Przeprowadź  uczestników  zajeć  przez  proces  odczytu  rekordu  zdarzenia  z **pliku urządzenia znakowego** myszy  w  systemieNetBSD.  Plik  ten  jest  przechowywany  w  systemie  plików  `specfs`,  który zajmuje się wyłącznie przechowywaniem plików urządzeń.


> Należy  zacząć  w  implementacji  wywołania  systemowego [sys_read](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/sys_generic.c?r=1fe5c4da#sys_read) i  poprzez  operacje  plikowe  opisane w [file(9)](http://man.netbsd.org/file.9) dotrzeć  do  procedury  wchodzącej  do  system  plików  przy  użyciu [VOP_READ(9)](http://man.netbsd.org/VOP_READ.9).  Przy  założeniu,  że  typ  v-węzła  systemu  plików  to  `VCHR`,  należy  kontynuować  przez [spec_read](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/miscfs/specfs/spec_vnops.c?r=1fe5c4da#spec_read) do **tablicy funkcji pliku urządzenia** (ang. device switch table) myszki [ms_cdevsw](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/arch/amiga/dev/ms.c?r=1fe5c4da#ms_cdevsw). Stamtąd należy osiągnąć miejsce użycia [uiomove(9)](http://man.netbsd.org/uiomove.9) w funkcji [ev_read](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/arch/amiga/dev/event.c?r=1fe5c4da#ev_read), gdzie następuje wkopiowanie zdarzenia do przestrzeni użytkownika.

---

**Plik urządzenia** – specjalny plik reprezentujący zasób (urządzenie). Dzięki takiemu zabiegowi zostaje znacznie uproszczona komunikacja z urządzeniem, np. chcąc wykonać kopię partycji, wystarczy skopiować plik, który ją przedstawia.

**Urządzenie znakowe** (ang. character device) – służy do odczytywania/zapisywania danych z/do urządzenia znak po znaku; w większości przypadków pojęcie znak jest równoznaczne z pojęciem bajt.

Urządzenia znakowe z zasady nie są buforowane i służą do komunikacji o charakterze strumieniowym. 

---

**The device switch tables** are arrays of operational pointers. Each entry in the table consists of a subarray of jump points. The routines pointed to are entered in a documented order and cover actions such as open, close, read, write, and several more.

---

1. [sys_read](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/sys_generic.c?r=1fe5c4da#121) -- pobieramy referencję na urządzenie
2. [dofileread](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/sys_generic.c?r=1fe5c4da#156) -- tworzymy uio, wołamy reada odpowiedniego dla tego pliku, po powrocie zwalniamy usuwamy referencję z 1.
3. [vn_read](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/vfs_vnops.c?r=1fe5c4da#552) -- przepisujemy flagi i przekazujemy sterowanie dalej...
4. ...[spec_read](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/miscfs/specfs/spec_vnops.c?r=1fe5c4da#713) -- wołamy cdev_read 
5. [cdev_read](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/subr_devsw.c?r=1fe5c4da&fi=cdev_read#903) -- szukamy device switch table (specyficzne dla character device, poprzedni struct był wspólny dla wszystkich plików) i wołamy ms_read z tego structa.
6. [ms_cdevsw](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/arch/amiga/dev/ms.c?r=1fe5c4da#136)
7. [ms_read](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/arch/amiga/dev/ms.c?r=1fe5c4da#487) -- znajdujemy kolejkę zdarzeń myszy i wołamy ev_read.
8. [ev_read](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/arch/amiga/dev/event.c?r=1fe5c4da#140) -- zapisujemy wydarzenia do uio z 2.


## Zadanie 7-6

:::info
Autor: Jacek Bizub
:::

> Na podstawie [1, 8.3], [1, 8.4] i [4, 10.1.2] uzasadnij potrzebę umieszczenia funkcji `d_open` i `d_close` w tabelach funkcji urządzeń `cdevsw` i `bdevsw` systemu NetBSD. Następnie zreferuj co robi implementacja tych funkcji w sterowniku stacji dyskietek [fd_cdevsw](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/arch/amiga/dev/fd.c?r=1fe5c4da#fd_cdevsw). Jakie zadania pełni funkcja `d_strategy` w tablicy funkcji pliku **urządzenia blokowego** (ang. block device switch table) [fd_bdevsw](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/arch/amiga/dev/fd.c?r=1fe5c4da#fd_bdevsw)?

---

**Urządzenie blokowe** (ang. block device) – pozwala na odczytywanie/zapisywanie danych blokami, czyli większymi grupami bajtów mającymi postać: sektorów, kilobajtów czy klastrów. W większości przypadków konieczność operowania na blokach wymuszona jest fizyczną budową urządzenia.

Urządzenia blokowe różnią się od znakowych tym, mogą być buforowane i pozwalają na swobodny dostęp do danych na nich zgromadzonych.


---

A device driver for a character device is defined by its entries in a cdevsw structure:

*open*
Opens the device in preparation for I/O operations. A device’s open entry point will be called for each open system  call  on  a  special-device  file  or,  internally,  when  a  device  is  prepared  for mounting a filesystem with the mount system call. The open() routine will commonly verify the integrity  of  the  associated  medium.  For  example,  it  will  verify  that  the  device  was  identified during the autoconfiguration phase and, for  disk drives, that a medium is present and ready to accept commands.


*close*
Closes  a  device.  The close()  routine  is  called  after  the  final  client  interested  in using  the  device terminates.  These  semantics  are  defined  by  the  higher-level  I/O  facilities.  Disk  devices  have nothing  to  do  when  a  device  is  closed  and  thus use  a  null close()  routine.  Devices  that  support access to only a single client must mark the device as available once again.

---

*strategy*
Starts  a  read  or  write  operation,  and  return  immediately.  I/O  requests  to  or  from  filesystems located on a device are translated by the system into calls to the block I/O routines bread() and bwrite(). These block I/O routines in turn call the device’s strategy routine to read or write data not in the memory cache. Each call to the strategy routine specifies a pointer to a buf structure containing  the  parameters  for  an  I/O  request.  If  the  request  is  synchronous,  the  caller  must sleep (on the address of the buf structure) until I/O completes.

---

[open](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/arch/amiga/dev/fd.c?r=1fe5c4da#fdopen) sterownika `fd.c` waliduje dane, w razie potrzeby alokuje bufor dla cache'u i ładuje dysk.

[close](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/arch/amiga/dev/fd.c?r=1fe5c4da#fdclose) flushuje bufory, odłącza partycję i jeśli to możliwe to wyłącza silnik dyskietki (lub czeka aż to będzie możliwe)
