ICS --Process control
learn from process control code
fork
1 | if ((pid = fork()) < 0){ |
get pid and get parent pid
1 | pid_t getpid(void); |
Three states:
- running
- stopped: suspended and will not be scheduled. Until it received SigCont
- terminated: signal, call exit, return from main routine
1 | void exit(int status); |
1 | pid_t fork(void); |
each process of the parent and the child share the same stack, code, variables
Reaping child processes💀
1 | pid_t waitpid(pid_t pid, int *statusp,int option); |
wait set: determined by pid. -1 for all children, or a child pid
options:
- default option: 0 -> if child in wait set already terminated, return immediately; else wait for a child terminated
- WNOHANG: return immediately if none child has terminated
- WUNTRACED: return when child is terminated or stopped
- WCONTINUED: until terminated or child received a SIGCONT
status of a reaped child: statusp - WIFEXITED(status)
- WEXITSTATUS(status)
- …
error condition:
calling process has no child -> return -1 and set errno to ECHILD
waitpid is interrupted -> return -1 and set errno to EINTR
1 | pid_t wait(int *statusp); == waitpid(-1,&status, 0); |
a typical example of using waitpid
1 | int main(){ |
more utils
1 | unsigned int sleep(unsigned int secs); |
1 | int pause(void) |
1 | int execve(const char* file, const char *argv[], |
Signal 😰😰😰
Overview
send by kernel
- illegal instruction => SIGILL
- illegal memory reference => SIGSEGV
- Ctrl + C => SIGINT to each process in the foregound process group
- Ctrl + Z => SIGTSTP to each process in the foregound
- kill -9 pid => SIGKILL
- a child process terminates or stops => SIGCHILD
Sending Signal
Kernel detected some system event
OR a process invoke a kill function
Process group
1 | pid_t getpgrp(void); |
kill
1 | /bin/kill -9 15213 //sending SIGKILL to process 15213 |
Receiving Signal
Sighandler
Received : being handled now
Pending : waiting to be handled. Only ONE per signal. a bit for each signal
Blocked : a mask to block certain signal
check (pending & ~blocked) bit vector
Synchronous Signals : generated by process itself. divide by ZERO. alarm
Asynchronous Signals : be sent from other processes or OS. Ctrl+C
1 | typedef void (*sighandler_t)(int); |
blocking signal
1 | int sigprocmask(int how, const sigset_t *set, sigset_t *oldset); |
a typical structure to block
1 | sigset_t mask, prev_mask; |
How to write a safe signal handler
- simple
- async-siganl-safe function: no printf, sprintf, malloc, exit
- save and restore
errno
- when access to a global data structure, should block all signals
- declare global variables with
volatile
, make the compiler not to optimize - declare global flag with
volatile sig_atomaic_t flag
, atomic for read OR write
signals cannot be used to count the occurrence of events in other processes
right version of signal handler
1 | void handler2(int sig){ |
Tricky example about racing
Wrong example: deletejob before addjob
1 | void handler(int sig){ |
![[Pasted image 20241207111723.png]]