36
Ejercicio 1 Realice un programa en C que en ejecución resulten dos procesos, uno padre y otro hijo. Dicho programa tomará un único argumento del intérprete de órdenes, que se trata de un entero. El proceso padre incrementará dicho valor en 2 y lo mostrará por pantalla. El hijo lo decrementará en 4 y lo mostrará también por pantalla. Solución: --Jatenor 10:38 24 nov 2010 (UTC) #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include <stdio.h> int main(int argc, char *argv[]) { if(argc != 2) { printf("Numero de parametros incorrectos. Uso: %s [entero]\n",argv[0]); exit(EXIT_FAILURE); } int var=atoi(argv[1]); printf("Entrada: %d\n",var); int ret; ret=fork(); if(ret>0) { var+=2; printf(" %d\n",var); wait(NULL); } else if(ret == 0) { var-=4; printf("%d\n",var); exit(EXIT_SUCCESS); } else if(ret == -1) { perror("Fallo en fork()\n"); exit(EXIT_FAILURE); }

Ejercicio Fork

Embed Size (px)

Citation preview

Page 1: Ejercicio Fork

Ejercicio 1

Realice un programa en C que en ejecución resulten dos procesos, uno padre y otro hijo. Dicho programa tomará un único argumento del intérprete de órdenes, que se trata de un entero. El proceso padre incrementará dicho valor en 2 y lo mostrará por pantalla. El hijo lo decrementará en 4 y lo mostrará también por pantalla.

Solución: --Jatenor 10:38 24 nov 2010 (UTC)

#include <stdlib.h>#include <unistd.h>#include <sys/types.h>#include <sys/wait.h>#include <stdio.h> int main(int argc, char *argv[]) { if(argc != 2)

{printf("Numero de parametros incorrectos. Uso: %s [entero]\n",argv[0]);exit(EXIT_FAILURE);

} int var=atoi(argv[1]);

printf("Entrada: %d\n",var); int ret;

ret=fork();if(ret>0) {

var+=2;printf(" %d\n",var);wait(NULL);

}else if(ret == 0) {

var-=4;printf("%d\n",var);

exit(EXIT_SUCCESS); }

else if(ret == -1) {perror("Fallo en fork()\n");exit(EXIT_FAILURE);

}}

Solución para comprobar que lo que le pasamos como argumento es un número

--Raumatbel 14:22 24 nov 2010 (UTC)

#include <stdlib.h>

Page 2: Ejercicio Fork

#include <unistd.h>

#include <sys/types.h>

#include <sys/wait.h>

#include <stdio.h>

#include <string.h> // para calcular el tamaño del argumento strlen(const char *s)

#include <ctype.h> // para comprobar si el argumento que le pasamos es un numero isdigit(char c)

int main(int argc, char *argv[]){

if(argc!=2){

printf("Numero de parametros incorrectos. Uso: %s [entero]\n",argv[0]);

exit(EXIT_FAILURE);

}

int ret;

// int atoi(char* cadena) pasa de ASCII a INTEGER

int valor=atoi(argv[1]);

char c;

int i;

/*Mostrar el tamaño del argumento*/

Page 3: Ejercicio Fork

printf("el tamaño de %s es: %d\n",argv[1],strlen(argv[1]));

/*Comprobar que lo que le pasamos como argumento (argv[1]) es un numero*/

for(i=0; i<strlen(argv[1]); i++){

c=argv[1][i];

if(isdigit(c)==0){ /* is digit(char c) comprueba si el caracter es un digito (de 0 a 9).

** Los valores devueltos son no-cero si el caracter c está dentro del rango (0-9),

** y cero si no.

*/

perror("fallo al insertar el argumento, debe de ser un numero");

exit(EXIT_FAILURE);

}

}

ret=fork();

if(ret==-1){

perror("fallo en el fork");

exit(EXIT_FAILURE);

}

else if(ret>0){

valor+=2;

Page 4: Ejercicio Fork

printf("El valor del padre es %d\n",valor);

wait(NULL);

}

else if(ret==0){

valor-=4;

printf("El valor del hijo es %d\n",valor);

exit(EXIT_SUCCESS);

}

}

Ejercicio 2

Realice un programa en C que genere la siguiente configuración de procesos:

padre / | \ / | \ / | \ / | \ / | \ hijo1 hijo2 hijo3

Además, cada hijo deberá mostrar el mensaje "Yo soy el hijo 1, mi padre es PID=1450, yo soy

PID=1453".

Solución:

--Markest 11:32 1 dic 2010 (UTC)

#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>

#include <sys/types.h>

#include <sys/wait.h>

Page 5: Ejercicio Fork

#include <errno.h>

 

#define NUM_HIJOS 3 /* número de hijos a crear. */

 

int main(void)

{

int ret, i;

 

for (i=0; i<NUM_HIJOS; i++) {

ret = fork();

if (ret == 0) {

/* estamos en alguno de los hijos. */

printf("Yo soy el hijo %d, mi padre es PID= %d, yo

soy PID= %d\n", i,getppid(), getpid());

exit(EXIT_SUCCESS);

} else if (ret == -1) {

perror("fallo en fork");

exit(EXIT_FAILURE);

}

}

ret = wait(NULL);

while (ret > 0) {

ret = wait(NULL);

}

/* si hay error, ignoramos si no hay más hijos a esperar. */

if (ret == -1 && errno != ECHILD) {

perror("fallo en wait");

exit(EXIT_FAILURE);

}

}

Ejercicio 3

Realice un programa en C que genere la siguiente configuración de procesos:

padre | | | hijo1 | | | hijo2 | ...

Page 6: Ejercicio Fork

| hijoN

Además, cada hijo deberá mostrar el mensaje "Yo soy el hijo 1, mi padre es PID=1450, yo soy

PID=1453". Use para este ejemplo N=3

Solución:

--Pedleogom 11:35 1 dic 2010 (UTC)

#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>

#include <sys/types.h>

#include <sys/wait.h>

#include <errno.h>

 

#define NUM_HIJOS 3 /* número de hijos a crear. */

 

int main(void) {

int ret, i;

 

for (i=0; i<NUM_HIJOS; i++) {

ret = fork();

if (ret == 0) {

/* estamos en alguno de los hijos. */

printf("Yo soy el hijo %d, mi padre es

PID= %d, yo soy PID= %d\n",i,getppid(),getpid());

//notese que NO usamos el

exit(EXIT_SUCCESS)

//a diferencia del ejercicio con hijos en

paralelo

//para que el hijo "i" se convierta en el

padre del hijo "i+1"

} else if (ret > 0) {

/* tratamiento del padre */

ret = wait(NULL);

while (ret > 0) {

ret = wait(NULL);

}

if (ret == -1 && errno != ECHILD) {

perror("fallo en wait");

exit(EXIT_FAILURE);

}

exit(EXIT_SUCCESS);

} else if (ret == -1) {

Page 7: Ejercicio Fork

perror("fallo en fork");

exit(EXIT_FAILURE);

}

}

 

}

Ejercicio 4

Realice un programa en C que genere la siguiente configuración de procesos:

padre / \ / \ / \ / \ / \ hijo1 hijo2 | | | hijo3

Además, cada hijo deberá mostrar el mensaje "Yo soy el hijo 1, mi padre es PID=1450, yo soy

PID=1453".

Solución:

--J.J. Alcázar 11:36 1 dic 2010 (UTC)

#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>

#include <sys/types.h>

#include <sys/wait.h>

#include <errno.h>

 

#define NUM_HIJOS 2 /* número de hijos a crear. */

 

void lanzahijo3(int i)

{

int ret;

ret = fork();

if (ret > 0) {

wait(NULL);

} else if (ret == 0) {

printf("Yo soy el hijo %d, mi padre es PID=%d, yo soy PID=

%d\n", i, getppid(), getpid());

Page 8: Ejercicio Fork

} else if (ret == -1) {

perror("fallo en fork");

exit(EXIT_FAILURE);

}

}

int main(void)

{

int ret, i;

 

for (i=0; i<NUM_HIJOS; i++) {

ret = fork();

if (ret == 0) {

/* estamos en alguno de los hijos. */

switch(i) {

case 0:

printf("Yo soy el hijo %d, mi padre

es PID=%d, yo soy PID=%d\n", i, getppid(), getpid());

exit(EXIT_SUCCESS);

case 1:

printf("Yo soy el hijo %d, mi

padre es PID=%d, yo soy PID=%d\n", i, getppid(), getpid());

lanzahijo3(i);

exit(EXIT_SUCCESS);

}

} else if (ret == -1) {

perror("fallo en fork");

exit(EXIT_FAILURE);

}

}

ret = wait(NULL);

while (ret > 0) {

ret = wait(NULL);

}

/* si hay error, ignoramos si no hay más hijos a esperar. */

if (ret == -1 && errno != ECHILD) {

perror("fallo en wait");

exit(EXIT_FAILURE);

}

}

Ejercicios sobre la llamada execEjercicio 1

Realice un programa en C que ejecute la orden ls -la. Nota: Realice la ejecución en un proceso

hijo.

Page 9: Ejercicio Fork

Solución: --Fmlopjur 09:33 1 dic 2010 (UTC)

#include <unistd.h>

#include <sys/types.h>

#include <sys/wait.h>

#include <stdio.h>

#include <stdlib.h>

 

int main(void)

{

int ret;

 

ret = fork();

if (ret > 0) {

/* tratamiento del padre. */

wait(NULL);

} else if (ret == 0) {

/* tratamiento del hijo. */

execlp ("ls", "ls", "-la", NULL);

perror("fallo en execlp");

exit(EXIT_FAILURE);

 

} else if (ret == -1) {

perror("fallo en fork");

exit(EXIT_FAILURE);

}

}

Ejercicio 2

Realice un programa en C que resulte en la siguiente configuración de procesos:

padre / \ / \ / \ / \ / \ hijo1 hijo2

El proceso hijo1 deberá ejecutar la orden ls -la cuya salida, en lugar de mostrar el resultado por

pantalla, se almacenará en el fichero hijo1.txt. El proceso hijo2 deberá ejecutar la orden ps -ef, de

igual manera se almacenará su salida en el fichero hijo2.txt.

Solución: --Jatenor 11:05 2 dic 2010 (UTC)

#include <unistd.h>

#include <stdlib.h>

Page 10: Ejercicio Fork

#include <stdio.h>

#include <sys/wait.h>

#include <errno.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

 

#define NUM_HIJOS 2 /* número de hijos a crear. */

 

void hijo1();

void hijo2();

 

int main(void)

{

int ret, i;

 

for (i=0; i<NUM_HIJOS; i++) {

ret = fork();

if (ret == 0) {

/* estamos en alguno de los hijos. */

switch(i) {

case 0:

/* tratamiento hijo 1. */

hijo1();

exit(EXIT_SUCCESS);

case 1:

/* tratamiento hijo 2. */

hijo2();

exit(EXIT_SUCCESS);

}

} else if (ret > 0) {

/* tratamiento del padre */

} else if (ret == -1) {

perror("fallo en fork");

exit(EXIT_FAILURE);

}

}

ret = wait(NULL);

while (ret > 0) {

ret = wait(NULL);

}

/* si hay error, ignoramos si no hay más hijos a esperar. */

if (ret == -1 && errno != ECHILD) {

perror("fallo en wait");

exit(EXIT_FAILURE);

Page 11: Ejercicio Fork

}

}

 

void hijo1() {

 

int fd;

 

fd = open("hijo1.txt", O_WRONLY | O_CREAT |O_TRUNC, 0660);

 

if(fd == -1){

perror("Fallo al abrir fichero hijo1.txt");

exit(EXIT_FAILURE);

}

 

dup2(fd, STDOUT_FILENO); /* La salida estandar ahora apunta a

hijo1.txt y no a la pantalla*/

 

if(close(fd)==-1){

perror("fallo en close hijo1.txt");

exit(EXIT_FAILURE);

}

 

execlp("ls","ls","-la",NULL);

 

perror("fallo en execlp");

}

 

void hijo2() {

 

int fd;

 

fd = open("hijo2.txt", O_WRONLY | O_CREAT | O_TRUNC, 0660);

 

if(fd == -1){

perror("Fallo al abrir fichero hijo2.txt");

exit(EXIT_FAILURE);

}

 

dup2(fd, STDOUT_FILENO); /* La salida estandar ahora apunta a

hijo2.txt y no a la pantalla*/

 

if(close(fd)==-1){

perror("fallo en close hijo2.txt");

exit(EXIT_FAILURE);

}

Page 12: Ejercicio Fork

 

execlp("ps","ps","-ef",NULL);

 

perror("fallo en execlp");

exit(EXIT_FAILURE);

}

Ejercicio 3

Ejercicio sobre tuberías

Ejercicio 1

Realice un programa en C que resulte en la siguiente configuración de procesos:

padre / \ / \ / \ / \ / \ hijo1 ------> hijo2 tubería

El proceso hijo1 tomará datos del teclado que enviará al proceso hijo2 a través de una tubería, este

último mostrará el mensaje recibido por pantalla. La ejecución de los procesos concluirá cuando el

proceso hijo1 reciba la cadena "fin".

Solución:

#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>

#include <sys/types.h>

#include <sys/wait.h>

#include <errno.h>

#include <string.h>

 

#define NUM_HIJOS 2 /* número de hijos a crear. */

 

void hijo1(int fds[2])

{

int numbytes;

char buf[4096];

 

close(fds[0]);

Page 13: Ejercicio Fork

numbytes = read(STDIN_FILENO, buf, sizeof(buf));

while (numbytes > 0) {

if (write(fds[1], buf, strlen(buf)) == -1) {

perror("fallo en write");

exit(EXIT_FAILURE);

}

if (strncmp("fin\n", buf, strlen("fin\n")) == 0)

break;

 

numbytes = read(STDIN_FILENO, buf, sizeof(buf));

}

if (numbytes == -1) {

perror("fallo en read");

exit(EXIT_FAILURE);

}

close(fds[1]);

}

 

void hijo2(int fds[2])

{

int numbytes;

char buf[4096];

 

close(fds[1]);

numbytes = read(fds[0], buf, sizeof(buf));

while (numbytes > 0) {

if (strncmp("fin\n", buf, strlen("fin\n")) == 0)

break;

 

if (write(STDOUT_FILENO, buf, strlen(buf)) == -1) {

perror("fallo en write");

exit(EXIT_FAILURE);

}

numbytes = read(fds[0], buf, sizeof(buf));

}

if (numbytes == -1) {

perror("fallo en read");

exit(EXIT_FAILURE);

}

close(fds[0]);

}

 

int main(void)

{

int ret, i, fds[2];

Page 14: Ejercicio Fork

 

if (pipe(fds) == -1) {

perror("fallo en pipe");

exit(EXIT_FAILURE);

}

for (i=0; i<NUM_HIJOS; i++) {

ret = fork();

if (ret == 0) {

/* estamos en alguno de los hijos. */

switch(i) {

case 0:

/* tratamiento hijo 1. */

hijo1(fds);

exit(EXIT_SUCCESS);

case 1:

/* tratamiento hijo 2. */

hijo2(fds);

exit(EXIT_SUCCESS);

}

} else if (ret > 0) {

/* tratamiento del padre */

} else if (ret == -1) {

perror("fallo en fork");

exit(EXIT_FAILURE);

}

}

// El padre cierra la tubería antes de esperar y salir

close(fds[0]);

close(fds[1]);

ret = wait(NULL);

while (ret > 0) {

ret = wait(NULL);

}

/* si hay error, ignoramos si no hay más hijos a esperar. */

if (ret == -1 && errno != ECHILD) {

perror("fallo en wait");

exit(EXIT_FAILURE);

}

}

Solución --Luís Mira Caballos 17:08 18 dic 2011 (UTC)

Solucionado si la primera palabra es "fin" => se termina.

Solucion limpieza del buffer antes de una lectura/escritura de palabras.

Page 15: Ejercicio Fork

#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>

#include <sys/types.h>

#include <sys/wait.h>

#include <errno.h>

#include <string.h>

 

#define NUM_HIJOS 2 /* número de hijos a crear. */

#define LECTURA 0

#define ESCRITURA 1

 

void hijo1(int fd[2]);

void hijo2(int fd[2]);

 

void main (void){

int ret,i,fd[2];

 

if(pipe(fd)==-1){

perror("Error en la creación de tubería.\n");

exit("EXIT_FAILURE");

}

 

for(i=0;i<NUM_HIJOS;i++){

ret=fork();

if(ret==0){

switch (i){

case 0:

hijo1(fd);

exit(EXIT_SUCCESS);

break;

case 1:

hijo2(fd);

exit(EXIT_SUCCESS);

break;

default:

perror("Error en el SWITCH.Se ha

entrado en DEFAULT.\n");

exit(EXIT_FAILURE);

break;

}

}

if(ret>0){

/*ejecución del padre*/

}

Page 16: Ejercicio Fork

if(ret==-1){

fprintf(stderr,"Error en el FORK.%s\

n",strerror(errno));

exit(EXIT_FAILURE);

}

}

/*cierre de la tubería en el padre*/

close(fd[LECTURA]);

close(fd[ESCRITURA]);

ret=wait(NULL);

/*el padre espera a la finalización de todos los hijos*/

while (ret>0){

ret=wait(NULL);

}

/* si hay error, ignoramos si no hay más hijos a esperar. */

if(ret==-1 && errno!=ECHILD){

perror("Error en el WAIT.\n");

exit(EXIT_FAILURE);

}

}

 

void hijo1(int fd[2]){

int fr;

char bf[4096]={};

 

if(close(fd[LECTURA])==-1){

perror("Error en el cierre de LECTURA del hijo1.\n");

exit(EXIT_FAILURE);

}

 

fr=read(STDIN_FILENO,bf,sizeof(bf));

while(fr>0){

if (strncmp(bf,"fin",3)==0){

break;

}

if(write(fd[ESCRITURA],bf,strlen(bf))==-1){

perror("Error en la escritura de tubería en

hijo1.\n");

exit(EXIT_FAILURE);

}

memset(bf,0,sizeof(bf));//coloca a 0 todos los elementos

del array "bf".0=vacio

fr=read(STDIN_FILENO,bf,sizeof(bf));

}

 

Page 17: Ejercicio Fork

if (fr==-1){

perror("Error en la lectura en hijo1");

exit(EXIT_FAILURE);

}

 

if(close(fd[ESCRITURA])==-1){

perror("Error en el cierre de ESCRITURA del hijo1.\n");

exit(EXIT_FAILURE);

}

}

 

void hijo2(int fd[2]){

int fr;

char bf[4096]={};

 

if(close(fd[ESCRITURA])==-1){

perror("Error en el cierre de lectura del hijo2.\n");

exit (EXIT_FAILURE);

}

 

fr=read(fd[LECTURA],bf,sizeof(bf));

while(fr>0){

if (strncmp(bf,"fin",3)==0){

break;

}

if(write(STDOUT_FILENO,bf,strlen(bf))==-1){

perror("Error en la escritura del hijo2.\n");

exit(EXIT_FAILURE);

}

memset(bf,0,sizeof(bf));//coloca a 0 todos los elementos

del array "bf".0=vacio

fr=read(fd[LECTURA],bf,sizeof(bf));

}

 

if(fr==-1){

perror("Error en la lectura de hijo2.\n");

exit(EXIT_FAILURE);

}

 

if(close(fd[LECTURA])==-1){

perror("Error en el cierre de lectura del hijo2.\n");

exit(EXIT_FAILURE);

}

}

Page 18: Ejercicio Fork

Ejercicio 2

Realice un programa en C que resulte en la ejecución de la siguiente orden:

ls -la | grep ^d

@Blindust: si subes una solución, los ejercicios tienen que compilar y enlazar por lo menos, de ahí

que haya borrado tu solución. --Pneira 12:39 14 dic 2010 (UTC)

#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>

#include <sys/types.h>

#include <sys/wait.h>

#include <errno.h>

#include <string.h>

 

#define NUM_HIJOS 2 /* número de hijos a crear. */

 

void hijo1(int fds[2])

{

close(fds[0]);

dup2(fds[1], STDOUT_FILENO);

close(fds[1]);

execlp("ls", "ls", "-la", NULL);

perror("fallo en execlp");

exit(EXIT_FAILURE);

}

 

void hijo2(int fds[2])

{

close(fds[1]);

dup2(fds[0], STDIN_FILENO);

close(fds[0]);

execlp("grep", "grep", "^d", NULL);

perror("fallo en execlp");

exit(EXIT_FAILURE);

}

 

int main(void)

{

int ret, i, fds[2];

 

if (pipe(fds) == -1) {

perror("fallo en pipe");

exit(EXIT_FAILURE);

Page 19: Ejercicio Fork

}

for (i=0; i<NUM_HIJOS; i++) {

ret = fork();

if (ret == 0) {

/* estamos en alguno de los hijos. */

switch(i) {

case 0:

/* tratamiento hijo 1. */

hijo1(fds);

exit(EXIT_SUCCESS);

case 1:

/* tratamiento hijo 2. */

hijo2(fds);

exit(EXIT_SUCCESS);

}

} else if (ret > 0) {

/* tratamiento del padre */

} else if (ret == -1) {

perror("fallo en fork");

exit(EXIT_FAILURE);

}

}

/* tratamiento del padre una vez lanzados ambos hijos. */

close(fds[0]);

close(fds[1]);

 

ret = wait(NULL);

while (ret > 0) {

ret = wait(NULL);

}

/* si hay error, ignoramos si no hay más hijos a esperar. */

if (ret == -1 && errno != ECHILD) {

perror("fallo en wait");

exit(EXIT_FAILURE);

}

}

Ejercicio 3

Realice un programa en C que resulte en la siguiente configuración de procesos:

padre / \ / \ / \

Page 20: Ejercicio Fork

/ \ / \ hijo1 ------> hijo2 tubería

El proceso hijo1 ejecutará la orden ls -la. El resultado de dicha ejecución, en lugar de ser mostrado

por pantalla, se comunicará al proceso hijo2 que lo almacenará en el fichero salida_ls_la.txt.

@Blindust: si subes una solución, los ejercicios tienen que compilar y enlazar por lo menos, de ahí

que haya borrado tu solución. --Pneira 12:40 14 dic 2010 (UTC)

Solución: --Fpalomares 16:55 14 dic 2010 (UTC)

#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>

#include <sys/types.h>

#include <sys/wait.h>

#include <errno.h>

#include <string.h>

#include <fcntl.h>

 

#define NUM_HIJOS 2 /* número de hijos a crear. */

 

void hijo1(int fds[2])

{

close(fds[0]);

dup2(fds[1], STDOUT_FILENO);

close(fds[1]);

execlp("ls", "ls", "-la", NULL);

perror("fallo en execlp");

exit(EXIT_FAILURE);

}

 

void hijo2(int fds[2])

{

int fd, numbytes;

char buf[4096];

close(fds[1]);

fd = open("./salida_ls_la.txt", O_WRONLY | O_CREAT | O_TRUNC,

0666);

if(fd==-1){

perror("Error en open");

exit(EXIT_FAILURE);

Page 21: Ejercicio Fork

}

numbytes = read(fds[0],buf,sizeof(buf));

while (numbytes > 0) {

if (write(fd, buf, strlen(buf)) == -1) {

perror("fallo en write");

exit(EXIT_FAILURE);

}

numbytes = read(fds[0], buf, sizeof(buf));

}

if (numbytes == -1) {

perror("fallo en read");

exit(EXIT_FAILURE);

}

close(fds[0]);

if(close(fd)){

perror("Error en close");

exit(EXIT_FAILURE);

}

}

 

int main(void)

{

int ret, i, fds[2];

 

if (pipe(fds) == -1) {

perror("fallo en pipe");

exit(EXIT_FAILURE);

}

for (i=0; i<NUM_HIJOS; i++) {

ret = fork();

if (ret == 0) {

/* estamos en alguno de los hijos. */

switch(i) {

case 0:

/* tratamiento hijo 1. */

hijo1(fds);

exit(EXIT_SUCCESS);

case 1:

/* tratamiento hijo 2. */

hijo2(fds);

exit(EXIT_SUCCESS);

}

} else if (ret > 0) {

/* tratamiento del padre */

} else if (ret == -1) {

Page 22: Ejercicio Fork

perror("fallo en fork");

exit(EXIT_FAILURE);

}

}

/* tratamiento del padre una vez lanzados ambos hijos. */

close(fds[0]);

close(fds[1]);

 

ret = wait(NULL);

while (ret > 0) {

ret = wait(NULL);

}

/* si hay error, ignoramos si no hay más hijos a esperar. */

if (ret == -1 && errno != ECHILD) {

perror("fallo en wait");

exit(EXIT_FAILURE);

}

}

Ejercicio 4

Realice un programa en C denominado ping-pong. Dicho programa consistirá en dos procesos

hijos. El proceso hijo1 enviará la cadena "ping" a lo que el proceso hijo2 responderá con la cadena

"pong". La ejecución se limitará a diez iteraciones, tras lo cual ambos procesos terminarán su

ejecución.

Solución: --marjimlao 00:18 16 dic 2010 (UTC)

#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>

#include <sys/types.h>

#include <sys/wait.h>

#include <errno.h>

#include <string.h>

 

#define NUM_HIJOS 2 /* número de hijos a crear. */

 

char *ping = "PING";

char *pong = "PONG";

 

int hijo1(int fds[2], int fds2[2])

{

char buf[4096];

int count = 0;

if(close(fds[0])==-1){

Page 23: Ejercicio Fork

perror("fallo al cerrar el primer pipe");

exit(EXIT_FAILURE);

}

if(close(fds2[1])==-1){

perror("fallo al cerrar el primer pipe");

exit(EXIT_FAILURE);

}

write(fds[1], ping,strlen(ping));

printf("%s\n", ping);

count++;

while(count < 10){

read(fds2[0], buf, sizeof(buf));

if((strcmp(buf, pong))==0){

printf("%s\n", ping);

write(fds[1], ping,strlen(ping));

count++;

}

 

}

if(close(fds2[0])==-1){

perror("fallo al cerrar el primer pipe");

exit(EXIT_FAILURE);

}

if(close(fds[1])==-1){

perror("fallo al cerrar el primer pipe");

exit(EXIT_FAILURE);

}

}

 

 

int hijo2(int fds[2], int fds2[2])

{

char buf[4096];

int count = 0;

if(close(fds2[0])==-1){

perror("fallo al cerrar el primer pipe");

exit(EXIT_FAILURE);

}

if(close(fds[1])==-1){

perror("fallo al cerrar el primer pipe");

exit(EXIT_FAILURE);

}

while(count < 10){

read(fds[0], buf, sizeof(buf));

if((strcmp(buf, ping))==0){

Page 24: Ejercicio Fork

printf("%s\n", pong);

write(fds2[1], pong,strlen(pong));

count++;

}

}

if(close(fds[0])==-1){

perror("fallo al cerrar el primer pipe");

exit(EXIT_FAILURE);

}

if(close(fds2[1])==-1){

perror("fallo al cerrar el primer pipe");

exit(EXIT_FAILURE);

}

}

 

int main(void)

{

int ret, i, fds[2], fds2[2];

 

if (pipe(fds) == -1) {

perror("fallo en pipe");

exit(EXIT_FAILURE);

}

if(pipe(fds2)==-1){

perror("fallo en pipe 2");

exit(EXIT_FAILURE);

}

for (i=0; i<NUM_HIJOS; i++) {

ret = fork();

if (ret == 0) {

/* estamos en alguno de los hijos. */

switch(i) {

case 0:

/* tratamiento hijo 1. */

hijo1(fds, fds2);

exit(EXIT_SUCCESS);

case 1:

/* tratamiento hijo 2. */

hijo2(fds, fds2);

exit(EXIT_SUCCESS);

}

} else if (ret > 0) {

/* tratamiento del padre */

} else if (ret == -1) {

perror("fallo en fork");

Page 25: Ejercicio Fork

exit(EXIT_FAILURE);

}

}

ret = wait(NULL);

while (ret > 0) {

ret = wait(NULL);

}

/* si hay error, ignoramos si no hay más hijos a esperar. */

if (ret == -1 && errno != ECHILD) {

perror("fallo en wait");

exit(EXIT_FAILURE);

}

}

Ejercicio 5

Realice un programa en C que resulte en la ejecución de la siguiente orden:

ls -la | grep ^d | tail -1

--Fmlopjur 08:29 15 dic 2010 (UTC)

Solución:

#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>

#include <sys/types.h>

#include <sys/wait.h>

#include <errno.h>

#include <string.h>

 

#define NUM_HIJOS 2 /* número de hijos a crear. */

 

void hijo1(int fds[2], int fds2[2])

{

close(fds2[0]);

close(fds2[1]);

close(fds[0]);

dup2(fds[1], STDOUT_FILENO);

close(fds[1]);

execlp("ls", "ls", "-la", NULL);

perror("fallo en execlp");

exit(EXIT_FAILURE);

Page 26: Ejercicio Fork

}

 

void hijo2(int fds[2], int fds2[2])

{

 

 

close(fds2[0]);

dup2(fds2[1], STDOUT_FILENO);

close(fds2[1]);

close(fds[1]);

dup2(fds[0], STDIN_FILENO);

close(fds[0]);

execlp("grep", "grep", "^d", NULL);

perror("fallo en execlp");

exit(EXIT_FAILURE);

}

void hijo3(int fds[2], int fds2[2])

{

close(fds[0]);

close(fds[1]);

close(fds2[1]);

dup2(fds2[0], STDIN_FILENO);

close(fds2[0]);

execlp("tail", "tail", "-1", NULL);

perror("fallo en execlp");

exit(EXIT_FAILURE);

}

 

int main(void)

{

int ret, i, fds[2], fds2[2];

 

if (pipe(fds) == -1) {

perror("fallo en pipe");

exit(EXIT_FAILURE);

}

if (pipe(fds2) == -1) {

perror("fallo en pipe");

exit(EXIT_FAILURE);

}

 

/*CREAR 3 HIJOS EN PARALELO*/

for (i=0; i<=NUM_HIJOS; i++) {

ret = fork();

if (ret == 0) {

Page 27: Ejercicio Fork

/* estamos en alguno de los hijos. */

switch(i) {

case 0:

/* tratamiento hijo 1. */

hijo1(fds, fds2);

exit(EXIT_SUCCESS);

case 1:

/* tratamiento hijo 2. */

hijo2(fds, fds2);

exit(EXIT_SUCCESS);

case 2:

/* tratamiento hijo 3. */

hijo3(fds, fds2);

exit(EXIT_SUCCESS);

}

} else if (ret > 0) {

/* tratamiento del padre */

} else if (ret == -1) {

perror("fallo en fork");

exit(EXIT_FAILURE);

}

}

/* tratamiento del padre una vez lanzados ambos hijos. */

close(fds[0]);

close(fds[1]);

close(fds2[0]);

close(fds2[1]);

 

ret = wait(NULL);

while (ret > 0) {

ret = wait(NULL);

}

/* si hay error, ignoramos si no hay más hijos a esperar. */

if (ret == -1 && errno != ECHILD) {

perror("fallo en wait");

exit(EXIT_FAILURE);

}

}

Ejercicio 6

Realice un programa en C que resulte en la siguiente configuración de procesos:

padre

Page 28: Ejercicio Fork

| | hijo1 | | hijo2

Los procesos hijo1 e hijo2 generarán un número aleatorio cada uno de ellos que comunicarán el

uno al otro. Ambos mostrarán el siguiente mensaje por pantalla:

Soy hijo1 con PID=1567, mi número aleatorio es 10 y el del otro proceso es 32Soy hijo2 con PID=1568, mi número aleatorio es 32 y el del otro proceso es 10

Para la generación de números aleatorios use la siguiente implementación:

#include <stdlib.h>

#include <time.h>

 

int aleatorio(void)

{

int semilla = (int)time(NULL);

srand(semilla);

}

que genera un número aleatorio.

Solución

El método de generar números aleatorios no funciona. He puesto números manualmente para

probar que el código funciona correctamente.

--AlvaroSG 12:15 22 dic 2010 (UTC)

#include <stdlib.h>

#include <time.h>

#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>

#include <sys/types.h>

#include <sys/wait.h>

#include <errno.h>

#include <string.h>

#include <sys/types.h>

Page 29: Ejercicio Fork

#include <sys/stat.h>

#include <fcntl.h>

 

#define lectura 0

#define escritura 1

 

 

int aleatorio(void)

{

int semilla = (int)time(NULL);

srand(semilla);

}

 

int hijo(int tube1[2], int tube2[2]){

int ret;

int minumero;

 

int numbytes;

char buf[256]={};

 

ret = fork();

 

if (ret == 0){

/*Tratamiento del nieto*/

//minumero = aleatorio();

minumero= 6;

 

printf("%d\n",minumero);

sprintf(buf,"%d",minumero);

 

if( write (tube1[escritura],buf, sizeof(buf)) == -

1){

perror("Fallo write nieto");

exit(EXIT_FAILURE);

}

 

numbytes = read(tube2[lectura],buf,sizeof(buf));

 

if (numbytes == -1){

perror("Fallo read nieto");

exit(EXIT_FAILURE);

}

 

 

 

Page 30: Ejercicio Fork

close(tube1[escritura]);

close(tube2[lectura]);

 

printf("Soy hijo2 con PID=%d, mi número aleatorio

es %d y el del otro proceso es %s\n",getpid(),minumero,buf);

 

 

}

 

else if (ret > 0){

/*Tratamiento del padre*/

 

//minumero = aleatorio();

minumero=5;

 

printf("%d\n",minumero);

sprintf(buf,"%d",minumero);

 

if( write (tube2[escritura],buf, sizeof(buf)) == -

1){

perror("Fallo write padre");

exit(EXIT_FAILURE);

}

 

numbytes = read(tube1[lectura],buf,sizeof(buf));

 

if (numbytes == -1){

perror("Fallo read padre");

exit(EXIT_FAILURE);

}

 

 

 

 

close(tube1[lectura]);

close(tube2[escritura]);

 

printf("Soy hijo2 con PID=%d, mi número aleatorio

es %d y el del otro proceso es %s\n",getpid(),minumero,buf);

}

 

else if (ret == -1){

/*Error*/

perror("Fallo en el segundo fork");

exit(EXIT_FAILURE);

Page 31: Ejercicio Fork

}

}

 

int main (void){

int ret;

int ret2;

int tube1[2];

int tube2[2];

int temp;

int e;

char buf[256]={};

 

if (pipe(tube1) == -1){

perror("Fallo pipe1");

exit(EXIT_FAILURE);

}

 

if (pipe(tube2) == -1){

perror("Fallo pipe2");

exit(EXIT_FAILURE);

}

 

ret = fork();

 

if (ret == 0){

/*tratamiento del hijo*/

hijo(tube1,tube2);

 

}

 

else if( ret > 0){

/*tratamiento del abuelo*/

 

 

}

 

else if (ret == -1){

/*error*/

perror("Fallo en fork");

exit(EXIT_FAILURE);

}

 

ret = wait (NULL);

 

while (ret > 0){

Page 32: Ejercicio Fork

ret = wait(NULL);

}

 

if (ret == -1 && errno != ECHILD){

perror("Fallo en wait");

exit (EXIT_FAILURE);

}

 

}

Ejercicio 5 (Complemento)

Realice un programa en C que resulte en la ejecución de la siguiente orden:

ls -la | grep ^d | tail -1 > salida.txt

--Fmlopjur 17:15 15 dic 2010 (UTC)

Solución:

#include <unistd.h>

#include <stdlib.h>

#include <stdio.h>

#include <sys/types.h>

#include <sys/wait.h>

#include <errno.h>

#include <string.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#define NUM_HIJOS 3 /* número de hijos a crear. */

 

void hijo1(int fds[2], int fds2[2])

{

close(fds2[0]);

close(fds2[1]);

close(fds[0]);

dup2(fds[1], STDOUT_FILENO);

close(fds[1]);

execlp("ls", "ls", "-la", NULL);

perror("fallo en execlp");

exit(EXIT_FAILURE);

}

 

void hijo2(int fds[2], int fds2[2])

{

Page 33: Ejercicio Fork

 

 

close(fds2[0]);

dup2(fds2[1], STDOUT_FILENO);

close(fds2[1]);

close(fds[1]);

dup2(fds[0], STDIN_FILENO);

close(fds[0]);

execlp("grep", "grep", "^d", NULL);

perror("fallo en execlp");

exit(EXIT_FAILURE);

}

void hijo3(int fds[2], int fds2[2])

{

int fd;

fd = open("salida.txt", O_WRONLY | O_CREAT | O_TRUNC, 0600);

if(fd == -1){

perror("fallo en open\n");

exit(EXIT_FAILURE);

}

dup2(fd, STDOUT_FILENO);

if(close(fd)){

perror("fallo en close\n");

exit(EXIT_FAILURE);

 

}

close(fds[0]);

close(fds[1]);

close(fds2[1]);

dup2(fds2[0], STDIN_FILENO);

close(fds2[0]);

execlp("tail", "tail", "-1", NULL);

perror("fallo en execlp");

exit(EXIT_FAILURE);

}

 

int main(void)

{

int ret, i, fds[2], fds2[2];

 

if (pipe(fds) == -1) {

perror("fallo en pipe");

exit(EXIT_FAILURE);

}

if (pipe(fds2) == -1) {

Page 34: Ejercicio Fork

perror("fallo en pipe");

exit(EXIT_FAILURE);

}

 

/*CREAR 3 HIJOS EN PARALELO*/

for (i=0; i<=NUM_HIJOS; i++) {

ret = fork();

if (ret == 0) {

/* estamos en alguno de los hijos. */

switch(i) {

case 0:

/* tratamiento hijo 1. */

hijo1(fds, fds2);

exit(EXIT_SUCCESS);

case 1:

/* tratamiento hijo 2. */

hijo2(fds, fds2);

exit(EXIT_SUCCESS);

case 2:

/* tratamiento hijo 3. */

hijo3(fds, fds2);

exit(EXIT_SUCCESS);

}

} else if (ret > 0) {

/* tratamiento del padre */

} else if (ret == -1) {

perror("fallo en fork");

exit(EXIT_FAILURE);

}

}

/* tratamiento del padre una vez lanzados ambos hijos. */

close(fds[0]);

close(fds[1]);

close(fds2[0]);

close(fds2[1]);

 

ret = wait(NULL);

while (ret > 0) {

ret = wait(NULL);

}

/* si hay error, ignoramos si no hay más hijos a esperar. */

if (ret == -1 && errno != ECHILD) {

perror("fallo en wait");

exit