Difference between Pipes, Fork and Threads

Asked

Viewed 1,156 times

11

From of that question, I was curious to learn more about the subject, so researching further, I came across more doubt on the subject. Because I saw that there is a string of ways to use Threads.

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

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

Example of Fork:

$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]);
    }
}

1 answer

1


Fork

Effectively, you copy the entire memory stack of the program, creating two distinct processes. The code is executed on the next line by executing the command that created Fork. Usually, Forks are used when communication between executions is not so frequent, since communication between such processes can only occur through modes of inter-process communication.

Threads

The entire stack from program execution to thread creation is shared. This facilitates communication between threads, but makes it necessary to use mutual exclusion mechanisms (mutex) in some cases.

Pipes

Are actually Forks, with only one difference: It allows communication between processes with STDIN / STDOUT. *Note:: This difference only exists in PHP, since Pipes are actually a method of communication between processes.


Regarding the codes, it is not possible to compare them, since the 3 are completely different! If you 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);

que_a_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 full.
    • In the second case (Thread), the stack is shared, the only thing that is not shared and is unique to each run is the $sleep_timer variable.
    • In the third case (Pipes), each process has an entirely new memory stack.
  • The thread runs from the place specified to run, ("run()" function), already in Fork it executes in the command following the Fork command, in pipe at the beginning of the file.

In relation to use: There are no "cues" for when to use one and when to use the other. Before, when processes were treated differently from threads by the OS, it might even have, but nowadays there is no.
The general recommendation is: Need to communicate between codes? Threads. Don’t need? Fork or Threads.
The only note I need to leave is, don’t mix the two. If you thread, then Fork, Fork will copy things from the thread that shouldn’t be copied and in almost every language it sticks.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.