# Operating System Concepts, Ch. 3: Processes
## Process Concept
- General process memory layout. Also refer to [C Memory Layout](https://www.geeksforgeeks.org/memory-layout-of-c-program/).

- Process running state:

- OS-managed **Process Control Block (PCB)**. There are also CPU-scheduling information here.

## Process Scheduling
- **Degree of Multiprogramming**: the number of processes currently in memory.
- A process can either be **CPU-bound** or **I/O-bound**.
- A number of queues are used to manage processes.

- **CPU Scheduler** chooses processes to run from the wait queue with its strategies.
- **Swapping**: remove a process from memory for it to be run later (reducing the degree of multiprogramming).
- **Context Switch** is pure overhead. Its time depends heavily on hardware.
## Operations on Processes
- In Linux, the process `systemd` is the root of all processes directly created. Process listing requires a traversal of this tree.
- Child processes may need to request resources directly from the OS, or it may be restricted to use only a fraction of those of its parent's (thus preventing system overloading by #children).
- Parents can wait for their children to terminate, or run concurrently.
- Children may duplicate parent memory contents, or have new programs loaded.
- Children may terminate before its parent calls `wait` (e.g. to retrieve its status). In this case, the children's process table must remain, and the process is known as a **zombie process**.
- If instead, the parent never calls `wait` and exits, its children become **orphans**. Traditional UNIX deals with this situation by assigning orphans as the children of `init`, the root process. `init` periodically calls `wait` to terminate orphans.
- Android terminates un-important processes when resources are insufficient by their **importance order** (foreground > visible > ...). If development guidelines are followed, even if a process is terminated, a user can still resume its saved state.
## Inter-Process Communication
There are multiple reasons to support process cooperation,
- Information sharing (such as memory)
- Parellel speedup (for multiple cores)
- Modularity (a function is divided into several processes or threads)
There are generally two ways for IPC, (a) **Shared Memory**, and (b) **Message Passing**. Shared memory can be faster than message passing, but the latter is better at trasmitting small amounts of data, as no conflicts occur.

## IPC Implementations
- **Shared Memory**: Harder to control. Requires well-written programs, & well-behaving processes.
- **Excercise**: implement a circular queue with an array, a `QUEUE_SIZE`, and two integers `in` and `out`. The queue must hold a maximum of `QUEUE_SIZE` elements.
- **Message Passing**: no address sharing. useful in distributed environments.
- **Direct Comms**: Processes explicitly refer to each other. Pair-wise, unique links must be established. Links are symmetric. Hard-coded identifier.
- **Asymmetric Links**: Alternatively, only one process needs to name another. Hard-coded identifier.
- **Indirect Comms**: Adopt intermediate **mailboxes**, or **ports**. A process can access multiple mailboxes, but two process can communicate only if they have a shared one. A mailbox can be used by multiple pairs, and a pair can use mulitple mailboxes. Mailboxes attach to an owner (recipient) or the OS.
- In message passing, both `send` and `recv` can be **blocking** or **non-blocking**. A blocking `send` paired with a blocking `recv` results in a **rendezvous**, and a trivial situation in the producer-consumer problem.
- The message queue can have zero-capacity (always blocks), bounded-capacity (conditionally blocks), or unbounded-capacity (never blocks).
## IPC System Examples
### POSIX Shared Memory
- Create a shared memory mapped file with `shm_open`, and specify arguments including `name`, and configure its size with `ftruncate`. Finally, map it to a file with `mmap`.
- Shared Memory coding excercise at the end of this chapter.
### Mach Message Passing
- Mach uses unidirectional ports for transmitting messages (potentially multiple senders, but only one receiver).
- Port owner can set port permissions.
- Each task (process) has a port to send message to kernel, and a notify port to receive events from kernel.
- Each task can register its ports to a bootstrap server, for other tasks to look up and send messages (system-wide).
- Tries to avoid message copying (slows down message passing) with virtual memory techniques.
### Windows
- Provides several operating environments, or **subsystems** that applications can interact with via message passing.
- Message passing in Windows is called **Advanced Local Procedure Call (ALPC)**.
- **Connection Ports**: Owned by the server and public to all. Can be used to establish a channel.
- **Communication Ports**: A channel consists of two such private ports.
- Small messages are copied across processes. Medium messages pass through a shared **section object**. Large messages turns to shared memory.
- For application programmers, ALPC is not visible nor accessible at the surface level. Use standard RPC (Remote Procedure Call) instead.
- Many kernel services use ALPC.
### Pipes
- Early IPC mechanisms in Unix.
- Unidirectional / Bidirectional
- Half Duplex / Full Duplex ([Reference](https://zh.wikipedia.org/zh-tw/%E9%9B%99%E5%B7%A5))
- Parent-child Relationship?
- Networked Transmission / Same Machine?
- **Ordinary Pipes**: Unidirectional, standard P-C Problem. A parent should create a pipe to communicate with its children. Ceases to exist when processes die or the comms in finished. They are called **anonymous pipes** in Windows.
- **Named Pipes**: Can be bidirectional, multi-process usage (e.g. several writers), and can continue to exist after processes / comms end.
- They are called **FIFO** in Unix, and can be created with `mkfifo`. Bidirectional, half duplex. It only supports same-machine comms. Otherwise, use **sockets**.
- On Windows, they are full duplex, and processes can be on different machines.
## Communication in Client-Server Systems
### Sockets
**Socket**: An endpoint of communication (`<IP>:<PORT>`). Two processes hold one socket each. All connections are unique. They are considered rather low-level, as only byte streams are allowed.

### Remote Procedure Calls (RPCs)
- Each message is addressed to an RPC daemon listening to a port on a remote system. Each RPC contains the function name and parameters, and returns well-structured data.
- When a client invokes an RPC, the system calls the appropriate **stub**, and pass parameters to it. The stub locates the port and **marshals** the parameters. Afterwards, it transmits a messages to the server with message passing. A similar stub at the server then receives this message and invokes the actual procedure on the server.
- **Marshaling** addresses data representation disparities (such as **endianess**).
- Due to its nature, RPCs are more prone to failures and duplicates. ACK and timestamp mechanism can address such issues (exactly once & at most once).
- Two systems must bind with each other, usually with fixed port numbers. For more flexibility, **matchmakers** are used. A matchmaker reside on a fixed port, and can return port numbers when queried with an RPC name.
### Android RPCs
- In Android's **binder** framework, a process can request services of others iva RPCs.
- **Application Component**: The basic building block that provides utility to an app. They can be combined in an app. One such component running in the background is **services**.
- Clients can bind to services with `bindService()`, and the latter provides a one-way `Messenger` so that the client can send messages.
- To create RPCs, the service can instead return a interface to a method call (a stub, actually).