Processes

Program vs. Process

Viewing Processes

ps -a -l
  UID   PID  PPID        F CPU PRI NI        SZ    RSS       TTY       TIME CMD
    0 13215 83470     4106   0  31  0 408655632   9504   ttys001    0:00.02 login -pfl gvwilson /
  501 13216 13215     4006   0  31  0 408795632   5424   ttys001    0:00.04 -bash
  501 13569 13216     4046   0  31  0 408895008  20864   ttys001    0:00.10 python -m http.server
    0 13577 13216     4106   0  31  0 408766128   1888   ttys001    0:00.01 ps -a -l

Exercise

  1. What does the top command do? What does top -o cpu do?

  2. What does the pgrep command do?

Parent and Child Processes

Signals

[% table slug=process_signals tbl="signals.tbl" caption="Signals" %]

import signal
import sys

COUNT = 0

def handler(sig, frame):
    global COUNT
    COUNT += 1
    print(f"interrupt {COUNT}")
    if COUNT >= 3:
        sys.exit(0)

signal.signal(signal.SIGINT, handler)
print("use Ctrl-C three times")
while True:
    signal.pause()
python src/catch_interrupt.py
use Ctrl-C three times
^Cinterrupt 1
^Cinterrupt 2
^Cinterrupt 3

Background Processes

import time

for i in range(3):
    print(f"loop {i}")
    time.sleep(1)
print("loop finished")
python src/show_timer.py &
ls site
$ src/show_timer.sh
birds.csv       cert_authority.srl  sandbox         server.pem      species.csv
cert_authority.key  motto.json      server.csr      server_first_cert.pem   yukon.db
cert_authority.pem  motto.txt       server.key      server_first_key.pem
loop 0
$ loop 1
loop 2
loop finished
$ python src/show_timer.py
loop 0
^Z
[1]+  Stopped                 python src/show_timer.py
$ jobs
[1]+  Stopped                 python src/show_timer.py
$ bg
[1]+ python src/show_timer.py &
loop 1
$ loop 2
loop finished
[1]+  Done                    python src/show_timer.py

Killing Processes

$ python src/show_timer.py
loop 0
^Z
[1]+  Stopped                 python src/show_timer.py
$ kill %1
[1]+  Terminated: 15          python src/show_timer.py
$ python src/show_timer.py
loop 0
^Z
[1]+  Stopped                 python src/show_timer.py
$ kill -s INT %1
[1]+  Stopped                 python src/show_timer.py
$ fg
python src/show_timer.py
Traceback (most recent call last):
  File "/tut/sys/src/show_timer.py", line 5, in <module>
    time.sleep(1)
KeyboardInterrupt

Fork

import os

print(f"starting {os.getpid()}")
pid = os.fork()
if pid == 0:
    print(f"child got {pid} is {os.getpid()}")
else:
    print(f"parent got {pid} is {os.getpid()}")
starting 41618
parent got 41619 is 41618
child got 0 is 41619

Unpredictability

Flushing I/O

import os
import sys

print(f"starting {os.getpid()}")
sys.stdout.flush()
pid = os.fork()
if pid == 0:
    print(f"child got {pid} is {os.getpid()}")
else:
    print(f"parent got {pid} is {os.getpid()}")
starting 41536
parent got 41537 is 41536
child got 0 is 41537

Exec

import os
import sys

print(f"starting {os.getpid()}")
sys.stdout.flush()
pid = os.fork()
if pid == 0:
    os.execl("/bin/echo", "echo", f"child echoing {pid} from {os.getpid()}")
else:
    print(f"parent got {pid} is {os.getpid()}")
starting 46713
parent got 46714 is 46713
child echoing 0 from 46714

Exercise

  1. What are the differences between os.execl, os.execlp, and os.execv? When and why would you use each?