Enviado em 06/03/2016 - 16:54h
Eu estou procurando entender para que server os pipes e como posso utiliza-los em C/C++, Se quiser me mande m tutorial gigantesco ou apenas um arquivo .pdf, desde já agradeço...
Enviado em 06/03/2016 - 16:54h
Enviado em 07/03/2016 - 11:59h
/* Gera arquivo comprimido com linhas que contam de 0 a 99. */
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
const char OUTPUT_FILE[]="/tmp/saida.gz";
int main(void){
int pipe_fds[2];
if(pipe(pipe_fds)==-1){
fprintf(stderr, "Falha ao tentar criar pipe: %s.\n", strerror(errno));
return 1;
}
/*
Neste ponto, tenho o pipe criado. pipe_fds[0] é a ponta de leitura,
e pipe_fds[1], a de escrita.
*/
pid_t child=fork();
if(child==-1){
fprintf(stderr, "Falha ao criar processo filho: %s.\n", strerror(errno));
return 1;
}
if(child==0){
/* Processo filho (child==0). */
/*
O processo filho recebe uma cópia de todos os descritores de arquivo
do processo pai. Isso significa que, neste momento, tanto o pai quanto
o filho podem tanto escrever quanto ler do pipe.
Como o filho não vai escrever no pipe, é NECESSÁRIO fechar aqui
a ponta de escrita.
*/
close(pipe_fds[1]);
/*
Pai e filho executam ao mesmo tempo, mas depois que o pai tiver
fechado a ponta de leitura, de fato teremos um "tubo" que tem
realmente apenas um descritor associado à ponta de entrada (no
pai, que escreve em pipe_fds[1]) e um à de saída (no filho, que lê
de pipe_fds[0]).
*/
/*
Como o gzip vai ler da entrada padrão, vamos copiar o descritor
de leitura do pipe por cima da entrada padrão, e depois fechar
o descritor original.
*/
if(dup2(pipe_fds[0], STDIN_FILENO)==-1){
fprintf(stderr, "Falha ao associar pipe com entrada padrão: %s.\n", strerror(errno));
_exit(1);
}
close(pipe_fds[0]);
if(freopen(OUTPUT_FILE, "wb", stdout)==NULL){
fprintf(stderr, "Falha ao criar arquivo de saída: %s.\n", strerror(errno));
_exit(1);
}
execlp("gzip", "gzip", "-9", NULL);
fprintf(stderr, "Erro ao executar gzip: %s.\n", strerror(errno));
_exit(1);
}
/* Processo pai (child>0). */
/*
O processo filho recebe uma cópia de todos os descritores de arquivo
do processo pai. Isso significa que, neste momento, tanto o pai quanto
o filho podem tanto escrever quanto ler do pipe.
Como o pai não vai ler do pipe, é NECESSÁRIO fechar aqui a ponta de
leitura.
*/
close(pipe_fds[0]);
/*
Pai e filho executam ao mesmo tempo, mas depois que o filho tiver
fechado a ponta de escrita, de fato teremos um "tubo" que tem
realmente apenas um descritor associado à ponta de entrada (no
pai, que escreve em pipe_fds[1]) e um à de saída (no filho, que lê
de pipe_fds[0]).
*/
FILE *send2gzip=fdopen(pipe_fds[1], "w");
if(send2gzip==NULL){
fprintf(stderr, "Falha ao associar stream à entrada do pipe: %s.\n", strerror(errno));
return 1;
}
/*
Ignoro o sinal enviado em caso de falha de escrita no PIPE, fazendo com
que, em caso de erro, as operações de escrita retornem com erro, em vez
de matar o processo.
*/
struct sigaction sa;
memset(&sa, 0, sizeof sa);
sa.sa_handler=SIG_IGN;
sigaction(SIGPIPE, &sa, NULL);
int n;
for(n=0; n<100; n++){
errno=0;
fprintf(send2gzip, "%d\n", n);
if(errno!=0){
fprintf(stderr, "Falha ao escrever \"%d\" no pipe: %s.\n", n, strerror(errno));
return 1;
}
}
if(fclose(send2gzip)==EOF){
fprintf(stderr, "Falha ao escrever no pipe: %s.\n", strerror(errno));
return 1;
}
int status;
waitpid(child, &status, 0);
if(status!=0){
fprintf(stderr, "Processo filho terminou com erro (status=%d).\n", status);
return 1;
}
return 0;
}
Enviado em 07/03/2016 - 14:30h
/* Gera arquivo comprimido com linhas que contam de 0 a 99. */
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
const char OUTPUT_FILE[]="/tmp/saida.gz";
int main(void){
int pipe_fds[2];
if(pipe(pipe_fds)==-1){
fprintf(stderr, "Falha ao tentar criar pipe: %s.\n", strerror(errno));
return 1;
}
/*
Neste ponto, tenho o pipe criado. pipe_fds[0] é a ponta de leitura,
e pipe_fds[1], a de escrita.
*/
pid_t child=fork();
if(child==-1){
fprintf(stderr, "Falha ao criar processo filho: %s.\n", strerror(errno));
return 1;
}
if(child==0){
/* Processo filho (child==0). */
/*
O processo filho recebe uma cópia de todos os descritores de arquivo
do processo pai. Isso significa que, neste momento, tanto o pai quanto
o filho podem tanto escrever quanto ler do pipe.
Como o filho não vai escrever no pipe, é NECESSÁRIO fechar aqui
a ponta de escrita.
*/
close(pipe_fds[1]);
/*
Pai e filho executam ao mesmo tempo, mas depois que o pai tiver
fechado a ponta de leitura, de fato teremos um "tubo" que tem
realmente apenas um descritor associado à ponta de entrada (no
pai, que escreve em pipe_fds[1]) e um à de saída (no filho, que lê
de pipe_fds[0]).
*/
/*
Como o gzip vai ler da entrada padrão, vamos copiar o descritor
de leitura do pipe por cima da entrada padrão, e depois fechar
o descritor original.
*/
if(dup2(pipe_fds[0], STDIN_FILENO)==-1){
fprintf(stderr, "Falha ao associar pipe com entrada padrão: %s.\n", strerror(errno));
_exit(1);
}
close(pipe_fds[0]);
if(freopen(OUTPUT_FILE, "wb", stdout)==NULL){
fprintf(stderr, "Falha ao criar arquivo de saída: %s.\n", strerror(errno));
_exit(1);
}
execlp("gzip", "gzip", "-9", NULL);
fprintf(stderr, "Erro ao executar gzip: %s.\n", strerror(errno));
_exit(1);
}
/* Processo pai (child>0). */
/*
O processo filho recebe uma cópia de todos os descritores de arquivo
do processo pai. Isso significa que, neste momento, tanto o pai quanto
o filho podem tanto escrever quanto ler do pipe.
Como o pai não vai ler do pipe, é NECESSÁRIO fechar aqui a ponta de
leitura.
*/
close(pipe_fds[0]);
/*
Pai e filho executam ao mesmo tempo, mas depois que o filho tiver
fechado a ponta de escrita, de fato teremos um "tubo" que tem
realmente apenas um descritor associado à ponta de entrada (no
pai, que escreve em pipe_fds[1]) e um à de saída (no filho, que lê
de pipe_fds[0]).
*/
FILE *send2gzip=fdopen(pipe_fds[1], "w");
if(send2gzip==NULL){
fprintf(stderr, "Falha ao associar stream à entrada do pipe: %s.\n", strerror(errno));
return 1;
}
/*
Ignoro o sinal enviado em caso de falha de escrita no PIPE, fazendo com
que, em caso de erro, as operações de escrita retornem com erro, em vez
de matar o processo.
*/
struct sigaction sa;
memset(&sa, 0, sizeof sa);
sa.sa_handler=SIG_IGN;
sigaction(SIGPIPE, &sa, NULL);
int n;
for(n=0; n<100; n++){
errno=0;
fprintf(send2gzip, "%d\n", n);
if(errno!=0){
fprintf(stderr, "Falha ao escrever \"%d\" no pipe: %s.\n", n, strerror(errno));
return 1;
}
}
if(fclose(send2gzip)==EOF){
fprintf(stderr, "Falha ao escrever no pipe: %s.\n", strerror(errno));
return 1;
}
int status;
waitpid(child, &status, 0);
if(status!=0){
fprintf(stderr, "Processo filho terminou com erro (status=%d).\n", status);
return 1;
}
return 0;
}
Entre na sua conta para responder.