# Lista 8
###### 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!**
- 28 kwietnia: zadania 1-3
- 5 maja: zadania 4-6
:::danger
| | 8-1 | 8-2 | 8-3 | 8-4 | 8-5 | 8-6 |
| ---------------------:| --- | --- | --- | --- | --- | --- |
| Jacek Bizub | X | X | X | X | X | X | 6
| Wojciech Jasiński | X | | X | | | | 2
| Artur Juraszek | X | |==X==| | X | X | 4
| Michał Myczkowski | | | | | | | 0
| Michał Odorczuk | X | X | X | X | X | | 5
| Damian Ratajski | | | | | | | 0
| Łukasz Siudek | | | | | | | 0
| Błażej Sowa |==X==| X | X | X |==X==| X | 6
| Andrzej Turko | X | X | X | X | X | X | 6
| Maksymilian Zawartko | X | | | X | X | X | 4
:::
## Zadanie 8-1
:::info
Autor: Błażej Sowa
:::
> Przedstaw przebieg obsługi wywołania systemowego [read(2)] na pliku należącego do systemu plików [DTYPE_VNODE]. Zacznij od implementacji [sys_read], poprzez procedurę [dofileread(9)], zestaw operacji [vnfileops(9)], a kończąc na wywołaniu wirtualnego systemu plików [VOP_READ(9)]. Co robią procedury [fd_getfile] i [fd_putfile]? Co przechowują pola `«f_offset»` i `«f_flag»` struktury **otwartego pliku** [file(9)]? Co się dzieje z tymi polami na analizowanej ścieżce kodu?
**Wskazówka**: Znajdź miejsca użycia symbolu `«fo_read»`.
[read(2)]: http://man.netbsd.org/read.2
[DTYPE_VNODE]: https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/sys/file.h?r=1fe5c4da#DTYPE_VNODE
[sys_read]: https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/sys_generic.c?r=1fe5c4da#sys_read
[dofileread(9)]: http://man.netbsd.org/dofileread.9
[vnfileops(9)]: http://man.netbsd.org/vnfileops.9
[VOP_READ(9)]: http://man.netbsd.org/VOP_READ.9
[fd_getfile]: https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#fd_getfile
[fd_putfile]: https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#418
[file(9)]: http://man.netbsd.org/file.9
1. [sys_read]
1. Pobiera deskryptor pliku
1. [fd_getfile]
1. Pobiera tablicę deskryptorów należącą do procesu
2. Pobiera strukturę [fdfile] dla deskryptora
3. Zwiększa licznik referencji dla struktury [fdfile]. Jeśli proces działa wielowątkowo (tablica deskryptorów ma wiele referencji), robi to atomowo.
4. Pobiera strukturę otwartego pliku [file] i ją zwraca.
3. Jeśli plik nie został otwarty w trybie read (odpowiednia flaga w masce `f_flag`), uruchamia [fd_putfile]:
1. Pobiera strukturę [fdfile] dla deskryptora (z tablicy deskryptorów).
2. Jeśli deskryptor pliku jest aktualnie zamykany, uruchamia [fd_close], żeby dokończyć operację lub powiadomić wątek, który czeka na zwolnienie wszystkich referencji.
3. W p.p. zmniejsza licznik referencji dla struktury [fdfile].
4. W p.p. przechodzi do [dofileread]:
1. Tworzy strukturę [uio] dla operacji read.
2. Uruchamia operację `fo_read` na którą wskazuje strukture [fileops] dla pliku. W tym przypadku (deskryptor typu [DTYPE_VNODE]) będzie to procedura [vn_read]:
1. Ustawia odwiednie flagi ioflag na podstawie pole `f_flag`.
2. Uruchamia procedurę wirtualnego systemu plików [VOP_READ], która wywołuje procedurę read z wektora operacji dla odpowiedniego systemu plików.
[fdfile]: https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/sys/filedesc.h?r=1fe5c4da&fi=fdfile_t#106
[dofileread]: https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/sys_generic.c?r=1fe5c4da#126
[file]: https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/sys/file.h?r=1fe5c4da#127
[fd_close]: https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#fd_close
[uio]: https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/sys/uio.h?r=1fe5c4da#81
[fileops]: https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/sys/file.h?r=1fe5c4da#82
[vn_read]: https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/vfs_vnops.c?r=1fe5c4da#vn_read
[VOP_READ]: https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/vnode_if.c?r=1fe5c4da&fi=VOP_READ#VOP_READ
## Zadanie 8-2
:::success
Autor: Michał Odorczuk
:::
[filedesc(9)]: http://man.netbsd.org/filedesc.9
[fd_copy]: https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#fd_copy
[fd_closeexec]: https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#fd_closeexec
[fd_dup]: https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#fd_dup
[fd_free]: https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#fd_free
[closef]: https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#closef
[f_count]: https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/sys/file.h?r=1fe5c4da#f_count
[kern]: https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/
---
[fd_copy] --
> Copy the file descriptor table from the current process and return a pointer to the copy. The returned file descriptor is guaranteed to have a reference count of one. All file descriptor state is maintained. The reference counts on each file entry referenced by the file descriptor table is incremented accordingly.
Użycia:
- [fork1](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_fork.c?r=1fe5c4da#394)
- [fd_closeexec](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#1726)
---
[fd_closeexec] --
> Close any files for the current process that are marked ``close on exec''. This operation is performed by invoking fd_close() on the appropriate file descriptor.
Użycia:
- [execve_runproc](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_exec.c?r=1fe5c4da#1248)
---
[fd_dup] --
> Duplicate file descriptor fp for the current process. The fd picked will be at least minfd. The resulting descriptor is given in newp.
Użycia:
- [fd_dupopen](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#1689)
- [sys_dup](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/sys_descrip.c?r=1fe5c4da#103)
- [sys_fcntl](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/sys_descrip.c?r=1fe5c4da#412)
---
[fd_free] --
> Decrement the reference count on the file descriptor table for the current lwp and release the file descriptor table if the reference count drops to zero.
Użycia:
- [fd_closeexec](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#1727)
- [exit1](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_exit.c?r=1fe5c4da#300)
- [lwp_exit](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_lwp.c?r=1fe5c4da#1108)
Dekrementuje [f_count] dla wszystkich plików skojarzonych ze strukturami otwartego pliku trzymanymi przez tablicę deskryptorów.
---
[closef]
> The internal form of close(2) which decrements the reference count on file entry fp. The closef() function release all locks on the file owned by lwp l, decrements the reference count on the file entry, and invokes ffree() to free the file entry.
[Użycia](https://mimiker.ii.uni.wroc.pl/source/search?project=NetBSD&full=&defs=&refs=closef&path=/sys/kern&hist=&type=&xrd=&nn=1&si=path&si=path)
Dekrementuje [f_count] dla pliku.
---
> The descriptor table of a process (and thus access to the objects to which the descriptors refer) is inherited from its parent, so several different processes may reference the same file entry. Thus, each file entry has a reference count, f_count. Each time a new reference is created, the reference count is incremented. When a descriptor is closed, the reference count is decremented. When the reference count drops to zero, the file entry is freed.
## Zadanie 8-3
:::success
Autor: Artur Juraszek
:::
[`fd_allocfile`](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#fd_allocfile) - o ile nie nastąpią błędy, chcielibyśmy, aby funkcja ta zwróciła (poprzez argumenty-wskaźniki):
- [pointer na instancję `file_t`](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/sys/file.h?r=1fe5c4da#127) - struktury przechowującej "otwarcie" pewnego pliku
- deskryptor pliku, rozumiany tu jako liczba, wpisana do tablicy przypisanej wywołującemu procesowi
- [wywołujemy `fd_alloc`](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#1089), który zajmie się przydziałem liczby-deskryptora oraz, w razie braku miejsca [powiększamy tablicę deskryptorów](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#1093) - aby uniknąć niespodzianek wynikłych z sytuacji wyścigu, dopuszczamy kilkukrotne powiększenie tablicy (`while`)
- [`fd_alloc`](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#860) zaczyna pracę od zajęcia muteksa, którego nie odda do momentu zakończenia swojego działania - zarówno [poprawnego](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#901) jak i [oznaczającego błąd](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#906)
- następnie [dzieje się dużo rzeczy](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#866), które można streścić jako znalezienie "mniej-więcej pierwszego" wolnego slotu w [tablicy](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/sys/filedesc.h?r=1fe5c4da&fi=fdtab_t#126) przechowującej deskryptory [(wraz z ich opakowaniem)](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/sys/filedesc.h?r=1fe5c4da&fi=fdtab_t#106)
- do przyspieszenia całego procesu używana jest [dwupoziomowa bitmapa](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#870)
- [po znalezieniu] satysfakcjonującego wolnego miejsca [inicjujemy przydzielony wpis](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#893) oraz zapalamy odpowiednie bity w użytej wcześniej bitmapie
- [zrzekamy się muteksu](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#901) - dopiero wtedy, gdy skończyliśmy już modyfikacje na tablicy
Jednak co w przypadku, [gdy miejsca w tablicy zabrakło](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#885)?
[Powiększamy ją!](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#992)
- [algorytm powiększający](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#1006) (poza pierwszym zwiększeniem rozmiaru) podwaja rozmiar tablicy
- [alokujemy](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#1011) potrzebną pamięć [tutaj](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#915)
- jeśli zachodzi taka potrzeba, to [znajdujemy](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#fd_map_alloc) nowe miejsce na bitmapy
- [zajmujemy muteks](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#1016) - wszystko, co działo się w tej funkcji przed tym momentem nie miało potencjalnych konsekwencji dla innych, wykorzystujących tę samą tablicę deksryptorów wątków/procesów
- możliwe, że ktoś nas uprzedził i zwiększył tablicę - wtedy [wycofujemy się](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#1019) i próbujemy zaalokować liczbę-deskryptor jeszcze raz
- kopiujemy [zawartość starej tablicy](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#1030)
- ...i, być może, [również bitmap](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#1049)
- [podmieniamy](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_descrip.c?r=1fe5c4da#1071) wskaźnik w strukturze opisującej tablicę i oddajemy muteks
## Zadanie 8-4
:::info
Autor: Andrzej Turko
:::
[vnodeops](http://man.netbsd.org/vnodeops.9) -- wektor operacji (wskaźniki na procedurę) dozwolonych na pliku skojarzonym z danym vnode. System utrzymuje taką tablicę dla każdego typu systemu plików. W tym zadaniu skupiamy sie na operacji VOP_OPEN.
[devfs_open](https://mimiker.ii.uni.wroc.pl/source/xref/FreeBSD/sys/fs/devfs/devfs_vnops.c?r=80f39bd9#devfs_open)
1. Znajdujemy device switch table
2. Otwieramy plik (operacja z device switch table) open lub fdopen.
3. finit() inicjalizuje operacje na pliku (file ops), dane i typ.
[devfs_read_f](https://mimiker.ii.uni.wroc.pl/source/xref/FreeBSD/sys/fs/devfs/devfs_vnops.c?r=80f39bd9#devfs_read_f) z [devfs_ops_f](https://mimiker.ii.uni.wroc.pl/source/xref/FreeBSD/sys/fs/devfs/devfs_vnops.c?r=80f39bd9#2025)czyta dane z pliku urządzenia
1. devfs_fp_check znajduje urządzenie i tablicę operacji urządzenia (dev, dsw)
2. czytam dane z urządzenia za pomocą procedury z device switch table
## Zadanie 8-5
:::info
Autor: Błażej Sowa
:::
> W tablicy [sys_kfilters] zdefiniowano zdarzenia, które można dodawać do [kqueue(2)]. Żeby z danym zdarzeniem powiązać **bilecik** (ang. `knote`) należy wywołać procedurę [kqueue_register], która z kolei zawoła odpowiednią procedurę `«f_attach»`. Zaprezentuj uczestnikom zajęć ścieżkę rejestracji zdarzenia aż do [pipe_kqfilter] włącznie.
[sys_kfilters]: https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_event.c?r=1fe5c4da#sys_kfilters
[kqueue(2)]: http://man.netbsd.org/kqueue.2
[kqueue_register]: https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_event.c?r=1fe5c4da#kqueue_register
[pipe_kqfilter]: https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/sys_pipe.c?r=1fe5c4da#pipe_kqfilter
[kqueue_register]
1. Alokujemy (i zerujemy) pamięć na bilecik `knote`.
2. Wyciągamy strukturę `kfilter` dla `keventa` który chcemy zarejestrować. Jeśli żądany filtr nie istnieje lub nie jest zaimplementowany, wychodzimy.
3. Sprawdzamy czy istnieje już bilecik (`knote`) w `kqueue` dla tego `kevent`. (Jeśli filtr jest skojarzony z deskryptorem pliku, pobieramy strukturę otwartego pliku przy pomocy [fd_getfile]).
4. Jeśli nie znaleźliśmy bilecika:
1. tworzymy go (wypełniamy strukturę).
2. Dodajemy go do listy bilecików we wpisie w tablicy deskryptorów dla pliku i zwiększamy `fd_lastkqfile`.
3. Uruchamiamy procedurę `f_attach` z wektora filtops. Dla filtrów `EVFILT_READ` i `EVFILT_WRITE`, będzie to [filt_fileattach]:
1. Uruchamiamy `fo_kqfilter` z wektore fileops. Dla pliku potoku, będzie to [pipe_kqfilter]:
1. Zmieniamy wektor filtops na [pipe_rfiltops] lub [pipe_wfilops] w zależności od rodzaju filtra. Nowy wektor nie bedzie posiadał operacji `f_attach`, ale będzie potrafił reagować na zdarzenie i odpinać się.
2. Wrzucamy bilecik na listę w strukturze [selinfo] skojarzoną z tym potokiem.
[filt_fileattach]: https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_event.c?r=1fe5c4da#466
[pipe_rfiltops]: https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/sys_pipe.c?r=1fe5c4da#1097
[pipe_wfiltops]: https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/sys_pipe.c?r=1fe5c4da#1104
[selinfo]: https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/sys/selinfo.h?r=1fe5c4da#73
## Zadanie 8-6
:::info
Autor: Jacek Bizub
:::
> W wyniku odczytu z potoku przy pomocy [pipe_read](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/sys_pipe.c?r=1fe5c4da#pipe_read) wołana jest procedura [pipeselwakeup](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/sys_pipe.c?r=1fe5c4da#pipeselwakeup). Prześledź jak dojdzie do wykonania procedury [filt_piperead](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/sys_pipe.c?r=1fe5c4da#filt_piperead). Jakie informacje zostaną skojarzone z powiadomieniem o dostępności potoku do odczytu? Na podstawie [kevent(2)](http://man.netbsd.org/kevent.2) powiedz jak odczytać te informacje w przestrzeni użytkownika.
[pipe_read](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/sys_pipe.c?r=1fe5c4da#552): Czytamy z pipe'a. Wołamy pipeselwakeup, aby powiadomić, że można już pisać do pipe'a.
[pipeselwakeup](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/sys_pipe.c?r=1fe5c4da#pipeselwakeup)
[selnotify](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/sys_select.c?r=1fe5c4da#765): wołamy knote'a (funkcję) na liście knote'ów (struktur) pipe'a, do którego można pisać.
[knote](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/kern_event.c?r=1fe5c4da#1814) -- filtrujemy knote'y. Te, które czekają na odpowiednie zdarzenie, są aktywowane. Podczas filtrowania zostanie zawołane **filt_piperead**
[filt_piperead](https://mimiker.ii.uni.wroc.pl/source/xref/NetBSD/sys/kern/sys_pipe.c?r=1fe5c4da#filt_piperead) -- sprawdzamy liczbę znaków w buforze (w pipe), jeśli jest dodatnia zgłaszamy wydarzenie. Ta liczba jest zapisywana w strukurze kevent, którą potem dostanie użytkownik.
W rozpatrywanym przypadku (EVFILT_READ na potoku) -- zapytanie zwraca liczbę bajtów, które są do odczytu z pipe'a. Jest ona zapisana w strukturze kevent, z którą zawołaliśmy kevent(). Po za tym otrzymamy informację (EOF) w polu flags, jeśli pisarze odłączyli się od potoku.