# Lista 1
###### tags: `SO`
## Zadanie 1

PID - identyfikator procesu
PPID - identyfikator rodzica
PGID - identyfikator grupy
USER - właściciel procesu
Rodzicem procesu ```init``` jest proces o id 0 (a nie ma takiego).
Wątki jądra są dziećmi procesu o PID 2.
Znaczenie symboli:


```{takie}``` zadania są wątkami
```n*[{cos takiego}]``` oznacza, że proces jest n-wątkowy.

## Zadanie 2
**sierota** - proces, który nie ma rodzica
**zombie** - proces, który się skończył, ale wciąż pochłania zasoby systemu.
**Jak jądro systemu reaguje na sytuację kiedy proces staje się sierotą?**
Ubije je proces ```init```.
**W jaki sposób pogrzebać
proces, który wszedł w stan zombie?**
W idealnym przypadku grzebie go jego rodzic, który czeka na jego zakończenie za pomocą ```wait``` lub ```waitpid```.
W przeciwnym wypadku to co w pytaniu 1.
**Czemu proces nie może sam siebie pogrzebać?**
Gdy rodzic wywołuje ```wait```, sygnalizuje, że nie będzie już więcej nim zainteresowany, a więc jego PID może zostać użyte ponownie. Gdyby dziecko samo się pogrzebało, nie moglibyśmy tego wywnioskować. Dodatkowo często oczekujemy, że będziemy w stanie dowiedzieć się czegoś o zakończonym procesie, przeanalizować pewne jego elementy.
**Co złego mogłoby się
stać, gdyby znieść to ograniczenie?**
**a) dziecko może czekać na zmianę stanu swojego
rodzica**
Rodzic i dziecko mogą wzajemnie czekać na zakończenie swoich procesów.
**b) wiele procesów oczekuje na zmianę stanu jednego procesu**
Kto ma ubić proces? Kogo powiadamiać po zakończeniu procesu?
## Zadanie 6
**Czemu ```user``` $+$ ```sys``` $\ne$ ```real```, a nawet ```user``` $+$ ```sys``` $\gt$ ```real``` ?**
Ponieważ kod może być wykonywany na wielu procesorach, a więc w praktyce zająć sumarycznie więcej czasu niż ten, który rzeczywiście upłynął.

wysyłane do procesu -> SIGXCPU - zapewnia odrobinę czasu procesora na wygenerowanie sygnału
SIGKILL - ubija
https://www.ibm.com/docs/en/zos/2.3.0?topic=descriptions-ulimit-set-process-limits
## Zadanie 7
```c=
#include "csapp.h"
static char buf[256];
#define LINE1 49
#define LINE2 33
#define LINE3 78
static void do_read(int fd) {
/* TODO: Spawn a child. Read from the file descriptor in both parent and
* child. Check how file cursor value has changed in both processes. */
pid_t pid = Fork();
if(pid == 0) {
Read(fd, buf, 10);
int off = Lseek(fd, 0, SEEK_CUR);
printf("PID %d: Cursor at %d\n", getpid(), off);
}
else {
Read(fd, buf, 15);
int off = Lseek(fd, 0, SEEK_CUR);
printf("PID %d: Cursor at %d\n", getpid(), off);
Wait(NULL);
}
exit(0);
}
static void do_close(int fd) {
/* TODO: In the child close file descriptor, in the parent wait for child to
* die and check if the file descriptor is still accessible. */
pid_t pid = Fork();
if(pid == 0) {
Close(fd);
printf("PID %d: Closed file descriptor\n", getpid());
exit(0);
}
else {
printf("PID %d: Waiting for child\n", getpid());
Wait(NULL);
printf("PID %d: Trying to read from file\n", getpid());
Read(fd, buf, 10);
printf("PID %d: Read: %s\n", getpid(), buf);
}
exit(0);
}
static void do_close2(int fd) {
/* TODO: In the child close file descriptor, in the parent wait for child to
* die and check if the file descriptor is still accessible. */
pid_t pid = Fork();
if(pid == 0) {
printf("PID %d: Waiting for parent\n", getpid());
sleep(1);
printf("PID %d: Trying to read from file\n", getpid());
Read(fd, buf, 10);
printf("PID %d: Read: %s\n", getpid(), buf);
}
else {
Close(fd);
printf("PID %d: Closed file descriptor\n", getpid());
Wait(NULL);
exit(0);
}
exit(0);
}
int main(int argc, char **argv) {
if (argc != 2)
app_error("Usage: %s [read|close]", argv[0]);
int fd = Open("test.txt", O_RDONLY, 0);
if (!strcmp(argv[1], "read"))
do_read(fd);
if (!strcmp(argv[1], "close"))
do_close(fd);
if (!strcmp(argv[1], "close2"))
do_close2(fd);
app_error("Unknown variant '%s'", argv[1]);
}
```
# Zadanie 8
```c=
static int ndselect(int n) {
for (int i = 0; i < n; i++){
pid_t pid = Fork();
if(pid == 0){
return i;
}
else {
Waitpid(pid, NULL, 0);
}
}
exit(0);
}
```