Considere um programa que apresenta a sua saída página por página. Ao invés de reinventar a paginação feita por vários utilitários do sistema Unix, desejamos chamar o paginador favorito do usuário (more, less, …). Faça um programa que use um pipe para redirecionar a saída para o paginador. O programa recebe o nome do arquivo a ser mostrado como entrada e repassa linha a linha deste arquivo a um processo filho através de um pipe. O processo filho irá executar o paginador.
Vamos inicialmente conceituar alguns comandos a serem utiliados:
more - filtro de arquivo para leitura e visualização em monitores
Descrição: é um filtro para paginar textos em uma tela de cada vez. Este paginador é simples. Os usuários devem perceber que o comendo less (1) prover mais de emulação (1) e mais melhorias.
less - O oposto do more
Descrição: less é um programa semelhante ao more , mas que permite o movimento para trás no arquivo, bem como o movimento para frente. Além disso, menos não tem que ler o arquivo de entrada inteiro antes de começar, portanto, com grandes entradas começa-se mais rápido do que editores de texto como vi.
pipe - Cria um pipe
Descrição
O Pipe, utilizado através do comando “|” permite que a saída de um comando seja diretamente utilizado em outro comando. O pipe tem seu nome inspirado nos tubos (pipes), de transporte de fluídos. A ideia do PIPE é encadear um conjunto de processos, de modo que a saída de cada um seja a entrada do seguinte.
O exemplo abaixo mostra claramente como utilizar o Pipe:
$ ls -l | grep imagem | sort -r
O primeiro comando ls -l lista o conteúdo do diretório em formato longo, a seguir o comando Pipe faz com que a saída do primeiro comando entre no segundo comando, grep imagem que procura na listagem do diretório qualquer arquivo que possua a palavra imagem, por final, a saída do comando grep imagem é utilizada no comando sort -r que faz a classificação de forma crescent
Conding in C
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char *argv[]) {
int fd[2], pid1, pid2;
char *my_program1[3] = {“/bin/cat”, argv[1], NULL};
char *my_program2[2] = {“/bin/more”, NULL};
pipe(fd);
if((pid1 = fork()) == 0) {
close(STDOUT_FILENO);
dup(fd[1]);
close(fd[0]); close(fd[1]);
execv(my_program1[0], my_program1);
}
if((pid2 = fork()) == 0) {
close(STDIN_FILENO);
dup(fd[0]);
close(fd[0]); close(fd[1]);
execv(my_program2[0], my_program2);
}
close(fd[0]); close(fd[1]);
waitpid(pid1, NULL, 0);
waitpid(pid2, NULL, 0);
return 0;
}
Vamos ao Primeiro Código:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char *argv[]) {
int fd[2], pid1, pid2;
char *my_program1[3] = {“/bin/cat”, argv[1], NULL};
char *my_program2[2] = {“/bin/more”, NULL};
pipe(fd);
if((pid1 = fork()) == 0) {
close(STDOUT_FILENO);
dup(fd[1]);
close(fd[0]); close(fd[1]);
execv(my_program1[0], my_program1);
}
if((pid2 = fork()) == 0) {
close(STDIN_FILENO);
dup(fd[0]);
close(fd[0]); close(fd[1]);
execv(my_program2[0], my_program2);
}
close(fd[0]); close(fd[1]);
waitpid(pid1, NULL, 0);
waitpid(pid2, NULL, 0);
return 0;
}
Executando
Para executar o código, não se esqueça de gerar a compilação do arquivo, como por exemplo:
gcc -o CatMore CatMore.c
gcc -o CatMore CatMore.c
Após, para execução, o programinha espera que você passe o nome do arquivo que deve ser lido por parâmetro, por exemplo:
./CatMore CatMore.c
./CatMore CatMore.c
O resultado disso será a leitura do próprio arquivo CatMore.c.
Explicação do Primeiro Código
Este código está bem simples. Foi a primeira versão que fiz para atender ao problema, porém ainda não está completamente correto. Se vocês repararem no enunciado, tem o seguinte detalhe: ‘e repassa linha a linha deste arquivo a um processo filho através de um pipe’, o que quer dizer que não podemos usar o cat para ler o arquivo desejado, devemos fazer o código que percorrerá linha a linha do arquivo passado por parâmetro e jogar no pipe para que o more possa lê-lo da forma desejada.
Então, Vamos ao Segundo Código:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXLINE 4096
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXLINE 4096
int main(int argc, char *argv[]) {
int n, fd[2];
pid_t pid;
char line[MAXLINE];
char *my_program[2] = {“/bin/more”, NULL};
FILE *arquivo;
pid_t pid;
char line[MAXLINE];
char *my_program[2] = {“/bin/more”, NULL};
FILE *arquivo;
if (pipe(fd) < 0) {
fprintf(stderr, “pipe error”);
fprintf(stderr, “pipe error”);
}
if ((pid = fork()) < 0) {
fprintf(stderr, “fork error”);
} else if (pid > 0) {
if ((pid = fork()) < 0) {
fprintf(stderr, “fork error”);
} else if (pid > 0) {
/* parent */
close(fd[0]);
arquivo = fopen(argv[1],”r”);
while (fgets(line, MAXLINE, arquivo) != NULL)
{
write(fd[1], line , (strlen(line)));
}
arquivo = fopen(argv[1],”r”);
while (fgets(line, MAXLINE, arquivo) != NULL)
{
write(fd[1], line , (strlen(line)));
}
fclose(arquivo);
close(fd[1]);
waitpid(pid, NULL, 0);
exit(0);
} else {
/* child */
close(STDIN_FILENO);
dup(fd[0]);
close(fd[1]);
execv(my_program[0], my_program);
}
return 0;
}
Fontes:
http://www.vivaolinux.com.br/dica/Pipes-no-Linux; http://jairofranchi.wordpress.com/2011/03/24/utilizando-o-comando-pipe-linux/ http://www.quaddro.com.br/blog/programando-em-ansi-c/estudando-bibliotecas-de-c-stdio-h
http://joelsonlucena.wordpress.com/2012/09/19/desafio-em-c-no-unix-simulando-o-comando-cat-more/
Nenhum comentário:
Postar um comentário