Menu

Paralelismus v shellu

Jak jsme se dozvěděli v kapitolce o práci s procesy, pomocí & můžeme spouštět programy na pozadí. Toho můžeme vhodně využít k psaní paralelních programů. V shellovém neinteraktivním skriptu nelze použít příkazy fg a bg, obejdeme se však bez nich.

Příklad použití

Tento skript odpočítá čísla od jedné do deseti, jedno za vteřinu a vytvoří kvůli tomu deset samostatných procesů.

#!/bin/sh
sleep_and_echo() {
    sleep $1
    echo $1
}

for i in $(seq 1 10); do
    sleep_and_echo $i &
    echo "Spuštěn proces č. $i s PID $!"
done

wait

Co říká POSIX

  • Proces (klidně i vlastní funkci) na pozadí spustíme pomoc &
  • PID posledního na pozadí spuštěného příkazu obsahuje proměnná $!
  • Na skončení procesu můžeme počkat pomocí wait $PID (PID může být i více – pak se čeká na dokončení všech procesů).
  • Příkaz wait bez parametrů počká na ukončení všech procesů běžících na pozadí.

Jak je to v reálných linuxových shellech

  • Spouštění na pozadí i $! fungují jak bylo popsáno výše.
  • Příkaz wait funguje pouze na potomky. Nejjednodušší způsob, jak může jeden proces čekat na druhý, pokud není jeho předkem je nekonečná vyčkávací smyčka, ve které příkazem ps testujeme, zda proces stále existuje. Další možností je synchronizace pomocí souborů, obzvláště vhodné jsou pro tento účel pojmenované roury.

Vyčkávací smyčka

Pokud bychom chtěli zpracovat velké množství záznamů, ale vždy maximálně 10 najednou, můžeme použít vyčkávací smyčku. Pomocí příkazu jobs zjistíme kolik nám aktuálně běží procesů na pozadí a další proces spustíme až tehdy, když tento počet klesne pod 10:

for vec in $veci; do
    while [ $(jobs | wc -l) -ge 10 ]; do
        sleep 1
    done
    zpracuj $vec &
done