contente
1. Introdução ao pipeline anônimo
3. Os processos pai e filho se comunicam por meio de pipes anônimos
1. Introdução aos pipes nomeados
(3) protótipo da função mkfifo()
3. Abra o arquivo de pipe nomeado FIFO
4. Regras abertas para pipes nomeados
1. O que é um pipeline
Pipes são a forma mais antiga de comunicação entre processos no Unix. Chamamos um fluxo de dados conectado de um processo a outro de "pipe".
Os tubos são half-duplex e os dados só podem fluir em uma direção. Quando duas partes precisam se comunicar, dois canais precisam ser estabelecidos. Ele só pode ser usado para comunicação entre processos pai e filho ou entre processos irmãos (processos com afinidade).
Normalmente, um pipe é criado por um processo e, em seguida, o processo chama fork, após o qual o pipe pode ser usado entre os processos pai e filho. Ou seja, a criação do pipeline é realizada antes de fork().
2. Pipeline Anônimo (PIPE)
1. Introdução ao pipeline anônimo
Um pipe anônimo também é um pipe anônimo. Um pipe pode ser criado através da função pipe(), e os pipes anônimos só podem se comunicar em processos relacionados. O que está relacionado? Como processo pai e processo filho ou dois processos filho criados pelo mesmo processo pai.
Como o pipe anônimo é half-duplex, para realizar a comunicação entre dois processos, é necessário criar dois pipes, um com a direção pai->filho e outro com filho->pai.
2, função de tubo ()
A função da função pipe() é criar um pipe sem nome.A seguir está o protótipo da função pipe().
#include <unistd.h> //Arquivo de cabeçalho
int pipe(int pipefd[2]);
parâmetro:
pipefd[2]: Array de descritores de arquivo, pipefd[0] representa o final da leitura e pipefd[1] representa o final da gravação.
valor de retorno:
Retorna 0 em caso de sucesso, -1 em caso de falha.
O código a seguir usa a função pipe() para testar a comunicação entre os processos pai e filho por meio de pipes anônimos.
3. Os processos pai e filho se comunicam por meio de pipes anônimos
(1) Análise de demanda
1. Dois pipelines precisam ser preparados, pai -> filho, filho -> pai.
2. Pai->filho pipeline, o pai quer enviar dados, então feche o final de leitura, e o filho quer receber dados, então feche o final de gravação.
3. Filho -> pipeline do pai, o pai quer receber dados, então feche o final de gravação, e o filho quer enviar dados, então feche o final de leitura.
4. Os processos pai e filho precisam ler ou enviar informações por meio do loop while.
(2) Implementação do código
#include <iostream>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
using namespace std;
int main()
{
//pipe匿名管道:1、没有名字 2、是用在由同一个进程fork具有亲缘关系的子进程
int pid = 0;
int fatherTochild[2] = { 0 };//父到子文件描述符数组
int childTofather[2] = { 0 };//子到父文件描述符数组
//管道创建要在进程之前,管道一定是放在进程里面使用的,所以管道要在进程创建前创建
if (pipe(fatherTochild) < 0 || pipe(childTofather) < 0)
{
perror("pipe open error");//管道创建失败
}
else
{
cout << "管道开启成功" << endl;
pid = fork();
//子进程
if (pid == 0)
{
char resbuf[255] = { 0 };
close(fatherTochild[1]);//子进程 父到子 关闭写端
close(childTofather[0]);//子进程 子到父 关闭读端
while (1)
{
read(fatherTochild[0], resbuf, sizeof(resbuf));//接收父亲发过来的信息
if (strlen(resbuf) != 0)
{
cout << "父亲对儿子说:" << resbuf << endl;
}
bzero(resbuf, sizeof(resbuf));//清空数组
cout << "儿子:";
fgets(resbuf, sizeof(resbuf), stdin);//控制台输入
write(childTofather[1], resbuf, sizeof(resbuf));//给父亲发信息
bzero(resbuf, sizeof(resbuf));//清空数组
}
}
else if (pid > 0)//父进程
{
char sendbuf[255] = { 0 };
close(fatherTochild[0]);//父进程 父到子 关闭读端
close(childTofather[1]);//父进程 子到父 关闭写端
while (1)
{
cout << "父亲:";
fgets(sendbuf, sizeof(sendbuf), stdin);//控制台输入
write(fatherTochild[1], sendbuf, sizeof(sendbuf));//给孩子发信息
bzero(sendbuf, sizeof(sendbuf));//清空数组
read(childTofather[0], sendbuf, sizeof(sendbuf));//接收孩子发过来的信息
if (strlen(sendbuf) != 0)
{
cout << "儿子对父亲说:" << sendbuf << endl;
}
bzero(sendbuf, sizeof(sendbuf));//清空数组
}
}
}
return 0;
}
(3) Resultados do teste
Através dos resultados dos testes, pode-se constatar que o pai digitou as informações primeiro, pois o filho lê() primeiro, e a função read() é uma função de bloqueio, que termina quando a informação é lida. Depois que o filho recebe a informação, o filho executa read(), e então executa write(). Ao mesmo tempo, depois que o pai envia a informação, ele executa write(), e então executa read(), esperando o filho para enviar as informações. Desta forma, a informação é enviada e recebida ciclicamente, e a comunicação entre os processos pai e filho é realizada.
3. Tubos Nomeados (FIFO)
1. Introdução aos pipes nomeados
Os pipes anônimos acima só podem alcançar a comunicação entre processos com parentesco, se quisermos trocar dados entre processos não relacionados, podemos usar arquivos FIFO para fazer o trabalho, que geralmente são chamados de pipes nomeados.
Um pipe nomeado é um tipo especial de arquivo, existe na forma de um arquivo, mas não é um arquivo real e não retém dados, mas apenas desempenha um papel na transmissão de dados.
2. Crie um pipe nomeado
(1) Modo de linha de comando
mkfifo xxx.fifo
(2) Método de código
umask(0);
mkfifo("/root/projects/test.fifo", 0777);
(3) protótipo da função mkfifo()
Função: Criar arquivo de pipeline .fifo
#include <sys/types.h> //Arquivo de cabeçalho
#include <sys/stat.h> //Arquivo de cabeçalhoint mkfifo(const char *pathname, mode_t mode);
parâmetro:
nome do caminho: caminho do arquivo
modo: permissões de arquivo
valor de retorno:
Retorna 0 em caso de sucesso, -1 em caso de falha.
3. Abra o arquivo de pipe nomeado FIFO
1. FIFO é diferente do pipe criado pela chamada do pipe, é um arquivo com nome e representa um descritor de arquivo aberto.
2. Deve ser aberto antes de ler ou escrever nele.
3. O arquivo FIFO também deve ser aberto ou fechado com as funções de abrir e fechar, exceto por algumas funções adicionais, todo o processo de operação é o mesmo que a operação de arquivo.
4. O nome do caminho de um arquivo FIFO passado para a chamada aberta não é o nome do caminho de um arquivo normal.
4. Regras abertas para pipes nomeados
1. Se a operação de abertura atual for abrir o FIFO para leitura, se um processo correspondente já tiver aberto o FIFO para escrita, a operação de abertura atual retornará com sucesso; caso contrário, poderá bloquear até que um processo correspondente abra o FIFO para escrita ( atualmente A operação de abertura ativa o sinalizador de bloqueio, ou seja, apenas O_RDONLY é definido, ao contrário, se a operação de abertura atual não definir o sinalizador de não bloqueio, ou seja, O_NONBLOCK, ela retornará sucesso.
2. Se a operação de abertura atual for abrir o FIFO para escrita, se um processo correspondente já tiver aberto o FIFO para leitura, a operação de abertura atual retornará com sucesso; caso contrário, poderá bloquear até que um processo correspondente abra o FIFO para leitura ( atualmente O sinalizador de bloqueio está definido para a operação de abertura); ou um erro ENXIO é retornado (o sinalizador de bloqueio não está definido para a operação de abertura atual).
3. Em termos leigos, para abrir um arquivo pipe nomeado FIFO, um processo precisa abri-lo para escrita e outro processo precisa abri-lo para leitura. Somente quando há leitura aberta e escrita aberta, o pipe nomeado pode ser aberto com sucesso . Assim como um cano de água, a entrada e a saída do cano de água precisam estar abertas ao mesmo tempo para que a água flua.
A originalidade não é fácil, por favor indique a fonte ao reimprimir.
Se for útil para você, você pode curtir, coletar + seguir, e será atualizado continuamente (hee hee).