Difference between Pipes, Fork and Threads

11

From this question , I came to the curiosity of wanting to learn more about the subject, then researching more deeply, I came across with more doubt on the subject. I've seen a string of ways to use Threads.

We can see the threads as small processes. The big difference from threads is that they share the same resources and memory addressing. That is, it is as if we have a process that is divided into smaller processes, where there is a switch between them, each one running a bit (as it happens in the processes), but now they share the same data and resources, work together. And I found it curious, since sometimes I had to catch enough to improve the performance of complex systems that are still very slow, and that they need to use sub systems to improve their performance.

Considering my case, in a future implementation, I would like to know what exactly changes between the three examples below, and when should I use one or the other and vise versa:

Fork example:

$pid = pcntl_fork();

if ($pid == -1) {
     die('Erro ao lançar thread');
} else if ($pid) {
     // thread principal
     //aguardamos a thread child terminar
     pcntl_wait($status); 
     echo "Processo child terminado\n";
     exit(0);

} else {
     //thread secundario
     //mudamos para um usuário não privilegiado
     posix_setuid(1000);
     posix_setgid(1000);
     //colocamos a thread para fazer algo,
     //ate que uma condição seja satisfeita e ela termine
    $i=0;
    while(true){    

           if (file_exists('/tmp/stop')){
        echo "Terminado thread";
        exit(0);
       }
       echo "Iteração : ". ++$i . "\n";
       sleep(2);
    }
}

Thread Example:

// Classe que aguarda um tempo aleatorio e depois imprime algo na tela
class AguardaRand extends Thread {

    // ID da thread (usado para identificar a ordem que as threads terminaram)
    protected $id;

    // Construtor que apenas atribui um ID para identificar a thread
    public function __construct($id) { 
        $this->id = $id;
    }

    // Metodo principal da thread, que sera acionado quando chamarmos "start"
    public function run() {
        // Sortear um numero entre 1 e 4
        $tempo_rand = mt_rand(1, 4);

        // Aguardar o tempo sorteado
        sleep($tempo_rand);

        // Imprimir quem e' a thread e quanto tempo ela aguardou
        printf(
            "Sou a thread %d e aguardei %d segundos\n",
            $this->id,
            $tempo_rand
        );
    }
}

//Execucao do codigo

// Criar um vetor com 10 threads do mesmo tipo
$vetor = array();
for ($id = 0; $id < 10; $id++) {
    $vetor[] = new AguardaRand($id);
}

// Iniciar a execucao das threads
foreach ($vetor as $thread) {
    $thread->start();
}

// Encerrar o script
exit(0);

Pipe example:

for ($i=0; $i<10; $i++) {
    // abre 10 processos
    for ($j=0; $j<10; $j++) {
        $pipe[$j] = popen('script2.php', 'w');
    }

    // espera a finalização do processo
    for ($j=0; $j<10; ++$j) {
        pclose($pipe[$j]);
    }
}
    
asked by anonymous 02.08.2016 / 15:47

1 answer

1

Fork

In effect, you copy the entire memory stack of the program, creating two distinct processes. The code then runs on the next line executing the command that created the fork. Usually, forks are used when communication between executions is not so frequent, since communication between such processes can only occur through modes of communication between processes .

Threads

The entire stack of program execution until the threads are created are shared. This makes it easier to communicate between threads, but it does require the use of mutex mechanisms in some cases.

Pipes

In fact they are forks , with only one difference: It allows the communication between the processes with the STDIN / STDOUT. * Note :: This difference only exists in PHP, since pipes are actually a method of communication between processes.

Regarding the codes, you can not compare them, since the 3 are completely different! If they rewrite them to make them with the same goal (Sleep a random time, then close), then yes it will be possible.

Fork

$pid = pcntl_fork();
$pid2 = pcntl_fork();

if ($pid == -1) {
    die('Error.');
} else if ($pid) {
    pcntl_wait($status);
    printf("Processo child terminado (PID: %d, PID2: %d)\n", $pid, $pid2);
    exit(0);
} else {
    // Processo filho
    posix_setuid(1000); // Diminui as permissões do processo
    posix_setgid(1000);

    $sleep_timer = mt_rand(1, 4);
    sleep($sleep_timer);

    printf("Pronto... (PID: %d, PID2: %d) - Dormi: %d\n", $pid, $pid2, $sleep_timer);
}

Thread

class AguardaRand extends Thread {
    protected $id;

    public function __construct($id) { 
        $this->id = $id;
    }

    public function run() {
        $sleep_timer = mt_rand(1, 4);
        sleep($sleep_timer);

        printf("Pronto... - Dormi: %d", $sleep_timer);
    }
}

$vetor = array();
for ($id = 0; $id < 4; $id++) {
    $vetor[] = new AguardaRand($id);
}

foreach ($vetor as $thread) {
    $thread->start();
}

exit(0);

Pipe

dorme_nenem.php

$sleep_timer = mt_rand(1, 4);
sleep($sleep_timer);

printf("Pronto... - Dormi: %d\n", $sleep_timer);

who_to_cuca_ja_vem.php

for ($j=0; $j<4; $j++) {
    $pipe[$j] = popen('php dorme_nenem.php', 'w');
}

for ($j=0; $j<4; ++$j) {
    pclose($pipe[$j]);
}

Now that you have the same codes, you can compare the differences.

  • The memory stacks are different. In the three:
    • In the first case (Fork), the stack is copied in whole.
    • In the second case (Thread), the stack is shared, the only thing that is not shared and is proper to each execution is the $ sleep_timer variable.
    • In the third case (Pipes), each process has an entirely new memory stack.
  • The thread executes from the place indicated to run, (for "run ()"), in the fork it executes in the command following the fork command, in the pipe at the beginning of the file.

In relation to use: There are no "indications" when to use one and when to use the other. Before, when processes were treated differently than threads by the OS, it might even have, but nowadays there are no. The general recommendation is: Do you need to have communication between codes? Threads. Do not you? Fork or Threads. The only note I need to leave is: Do not mix the two. If you do threads, then fork, fork will copy things from the thread that should not be copied and in almost all sticky languages.

    
15.12.2016 / 23:10