evola Posted January 2, 2012 Report Share Posted January 2, 2012 (edited) A ver, necesito ayuda para realizar una práctica de Sistemas Operativos que estoy más perdido que una aguja en un pajar. No quiero que penséis que abro el post para quitarme trabajo de encima; por vagancia vamos. Simplemente es que no "pude" ir a la práctica donde lo explicaba y ahora no me aclaro. Vale un puntazo, el cual necesito desesperadamente para aprobar la asignatura más jodida de este curso. Son tres ejercicios pero os voy a poner uno solo, para ver si con vuestra ayuda puedo ver la luz y hacer yo mismo los otros dos. Estoy seguro que para la gente entendida en Linux (o C) será una chorrada máxima. Primero me pide crear un fichero llamado fichero_previo que contiene esto: $ cat fichero_previo wvcin4902q3ḱwecwqedfknm cwfp1w4mf0qadekfdwe54tg fqw4tm9scelm3lmr5mñ7ñcas caefqwdpo33e89dqwd39jdqq acw1e3sa4k5kace0caf4aecac caeñoj59sefmol5mslm6lmcaae aefamaeo0eaem4mcadlm8aecme aemj45macso94to8am3e332ed eqro3q3ed05ms0394lndq39de aw34kd93523r9494rjf043432 1. Crear un fichero fuente con el código (en lenguaje C) que aparece en esta página (y la siguiente) y llamarlo misterioso_1.c, en el directorio de trabajo por defecto. Compilar y enlazar el código misterioso_1.c y nombrar al fichero ejecutable resultante, en el directorio de trabajo por defecto, con el nombre misterioso_1. Sin cambiar de directorio de trabajo por defecto, solicitarle, a un “intérprete de comandos de tipo UNIX”, la ejecución del siguiente comando: $ ./misterioso_1 grep 8 fichero_previo a) Anotar, detalladamente, el comportamiento observado. Explicar, detalladamente, el comportamiento observado. #include <sys/wait.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { pid_t childpid; int status, exit_code, x; exit_code = EXIT_SUCCESS; if (argc < 2) { printf(“Usage: %s command args\n“, argv[0]); exit_code = EXIT_FAILURE; } else { switch (childpid = fork()) { case -1: perror("Could not fork\n"); exit_code = EXIT_FAILURE; break; case 0: if (execvp(argv[1], &argv[1]) < 0) { perror(“Could not execute the command\n”); exit_code = EXIT_FAILURE; break; } default: if ((x = wait(&status)) != childpid) { perror(“Wait interrupted by a signal\n”); exit_code = EXIT_FAILURE; } } // end switch } // end else exit(exit_code); } // end main ----------------------------------------------------------------------------------------- Aquí os dejo la páctica: tercera_práctica.pdf 36.0 KBwww.megaupload.com/?d=QTHD9CFK Mil grasias compañeros por la disculpas chavacanas wey. Edited January 2, 2012 by evola Quote Link to comment Share on other sites More sharing options...
oscarfg Posted January 2, 2012 Report Share Posted January 2, 2012 No te fumes las clases hombre, que luego pasa lo que pasa (por experiencia). Yo no controlo mucho de C, pero a simple vista parece que lo que hace es crear un nuevo proceso en la línea switch (childpid = fork()) y en dicho proceso ejecuta lo que le pasas en la línea de comando, es decir el "grep 8 fichero_previo", con lo que te devuelve aquellas lineas de fichero_previo que tienen un 8. Después con el wait(&status) parece que espera a que finalice el proceso que ha creado, lo que ya no sé bien es si finaliza por sí mismo o hay que matarlo con un kill. ¿No tienes un linux en donde probar? Los pasos parecen bastante sencillitos. Suerte. Quote Link to comment Share on other sites More sharing options...
Kyle_Katarn Posted January 2, 2012 Report Share Posted January 2, 2012 Vaya tela evola a ultima hora como los buenos estudiantes jajaja A ver, empezando por que hace mil años que no toco C y que con unix me he peleado poco, por lo que veo, el programa hace como un pequeño prompt del sistema que ejecuta el comando que le pasas con los archivos como paramentros de ese comando. Bueno, grep, buscara digito_1 dentro de fichero_previo Pero cuando se hace el childpid = fork() se hace un proceso duplicado del actual, pero cada uno parece ser que tieen su propia pila de memoria para variables, con lo que las variables definidas en el proceso no se comparten. Y esto es conjetura, creo que entonces el proceso hijo no tendra acceso a los parametros usados en grep y no encontrara nada. Si pudieras poner una copia del resultado podria ver mas cositas :P Quote Link to comment Share on other sites More sharing options...
evola Posted January 2, 2012 Author Report Share Posted January 2, 2012 !!KYLEEEEEEE NECESITO TU AYUDA!! El problema es que no consigo compilar el código. Si no viniese del profesor juraría que tiene un error. Llevo toda la tarde intentándolo. Al hacer gcc misterioso_1.c -o misterioso me sale esta ristra de errores: Prueba.c: In function ‘main’: Prueba.c:13:3: error: stray ‘\342’ in program Prueba.c:13:3: error: stray ‘\200’ in program Prueba.c:13:3: error: stray ‘\234’ in program Prueba.c:13:13: error: ‘Usage’ undeclared (first use in this function) Prueba.c:13:13: note: each undeclared identifier is reported only once for each function it appears in Prueba.c:13:18: error: expected ‘)’ before ‘:’ token Prueba.c:13:18: error: stray ‘\’ in program Prueba.c:13:18: error: stray ‘\342’ in program Prueba.c:13:18: error: stray ‘\200’ in program Prueba.c:13:18: error: stray ‘\234’ in program Prueba.c:27:4: error: stray ‘\342’ in program Prueba.c:27:4: error: stray ‘\200’ in program Prueba.c:27:4: error: stray ‘\234’ in program Prueba.c:27:14: error: ‘Could’ undeclared (first use in this function) Prueba.c:27:20: error: expected ‘)’ before ‘not’ Prueba.c:27:20: error: stray ‘\’ in program Prueba.c:27:20: error: stray ‘\342’ in program Prueba.c:27:20: error: stray ‘\200’ in program Prueba.c:27:20: error: stray ‘\235’ in program Prueba.c:34:4: error: stray ‘\342’ in program Prueba.c:34:4: error: stray ‘\200’ in program Prueba.c:34:4: error: stray ‘\234’ in program Prueba.c:34:14: error: ‘Wait’ undeclared (first use in this function) Prueba.c:34:19: error: expected ‘)’ before ‘interrupted’ Prueba.c:34:19: error: stray ‘\’ in program Prueba.c:34:19: error: stray ‘\342’ in program Prueba.c:34:19: error: stray ‘\200’ in program Prueba.c:34:19: error: stray ‘\235’ in program No consigo hacer el ejecutable. Quote Link to comment Share on other sites More sharing options...
Korrea Jong-un Posted January 2, 2012 Report Share Posted January 2, 2012 Pregunta tonta. Hicistes el fichero .c en windows? Quote Link to comment Share on other sites More sharing options...
evola Posted January 2, 2012 Author Report Share Posted January 2, 2012 Nop. Lo he hecho con el gedit de Linux copiándolo y pegándolo desde el pdf. ¿Me recomendáis otro editor o entorno? Quote Link to comment Share on other sites More sharing options...
Korrea Jong-un Posted January 2, 2012 Report Share Posted January 2, 2012 Lo decia pq algunos editores meten caracteres raros. Y para ficheros creados en win lo pasas por dos2unix y listo. Comenta todo e intenta compilar. Aun asi me suena que faltan opciones a ese gcc.... Quote Link to comment Share on other sites More sharing options...
evola Posted January 2, 2012 Author Report Share Posted January 2, 2012 !!Quiero parao!! Al parecer el problema estaba en las comillas que pone el puto profesor. Las he sustituido y ahora sí que me deja. Voy a ver qué hace la función de los cojones. Quote Link to comment Share on other sites More sharing options...
Korrea Jong-un Posted January 2, 2012 Report Share Posted January 2, 2012 !!Quiero parao!! Al parecer el problema estaba en las comillas que pone el puto profesor. Las he sustituido y ahora sí que me deja. Voy a ver qué hace la función de los cojones. Cierra todas las paginas web, quedate solo con google y centrate Quote Link to comment Share on other sites More sharing options...
evola Posted January 2, 2012 Author Report Share Posted January 2, 2012 Os explico: He compilado el fichero .c con gcc misterioso_1.c -o misterioso_1 y me ha creado el ejecutable misterioso_1 que al ejecutarlo junto con grep 8 fichero_previo me da como salida las 3 lineas que contienen 8 del fichero_previo. Me da la misma salida que si ejecutase el grep a secas. Quote Link to comment Share on other sites More sharing options...
Kyle_Katarn Posted January 2, 2012 Report Share Posted January 2, 2012 jodio no ves que te dice que Usage no esta declarado Quote Link to comment Share on other sites More sharing options...
evola Posted January 2, 2012 Author Report Share Posted January 2, 2012 Cacho de nen, que el stray \342 significa un error de enriquecimiento del texto y lo he solucionado cambiando las comillas. Ahora ya no me da error alguno al compilar. Quote Link to comment Share on other sites More sharing options...
Kyle_Katarn Posted January 2, 2012 Report Share Posted January 2, 2012 Como ya te he comentado antes, es una especie de prompt cutre hecho por uno mismo que ejecuta dos veces lo mismo, o casi ya que el segundo grep que se ejecuta al crear el proceso hijo no tiene acceso a las variables locales del proceso padre y su salida supongo que sera vacio Prueba a hacer un grep sin parametros a ver que sale, aunque creo que no sera valida esta prueba, ya que no es exactamente eso lo que esta haciendo la funcion. La funcion crea dos procesos grep con parametros, pero el segundo no tiene acceso a ellos, asi que hace las comparaciones con dos bloques de memoria vacios. Si haces un grep con dos cadenas vacias puede que si te de un resultado vacio, que es la segunda parte del resultado. Fijate si al acabar la funcion hay una linea de mas en el resultado que este vacia, como si se metiera un retorno de carro sin venir a cuento Cacho de nen, que el stray \342 significa un error de enriquecimiento del texto y lo he solucionado cambiando las comillas. Ahora ya no me da error alguno al compilar. ya, pero si te dice que Usage no esta definido, es que lo que hay justo antes de Usage no esta bien, asi que se sustituye en la primera vez que se compila :P Quote Link to comment Share on other sites More sharing options...
evola Posted January 2, 2012 Author Report Share Posted January 2, 2012 Nop, esta es la salida tal cual: evola@evola-Aspire-3610:~/Documentos/SO/tercera_practica$ grep 8 fichero_previo caefqwdpo33e89dqwd39jdqq aefamaeo0eaem4mcadlm8aecme aemj45macso94to8am3e332ed evola@evola-Aspire-3610:~/Documentos/SO/tercera_practica$ Kyle ¿Te puedes meter al TS ahora o algún día de esta semana? Quote Link to comment Share on other sites More sharing options...
Kyle_Katarn Posted January 2, 2012 Report Share Posted January 2, 2012 (edited) ENTRANDO... ¿y el grep de dos cadenas vacias que da? Edited January 2, 2012 by Kyle_Katarn Quote Link to comment Share on other sites More sharing options...
evola Posted January 2, 2012 Author Report Share Posted January 2, 2012 He creado un archivo llamado vacio con dos lineas vacias y le he dado la orden grep 8 vacio y no me ha devuelto nada: evola@evola-Aspire-3610:~/Documentos/SO/tercera_practica$ grep 8 vacio evola@evola-Aspire-3610:~/Documentos/SO/tercera_practica$ Quote Link to comment Share on other sites More sharing options...
oscarfg Posted January 2, 2012 Report Share Posted January 2, 2012 (edited) A ver, yo creo que es simple: hay dos procesos, el padre que es el .c compilado, y que una vez ejecutado crea otro proceso hijo, que es el grep. Solo queda el espíritu santo. PD: Un grep de lo que sea sobre un fichero vacío siempre te va a dar vacío. Edited January 2, 2012 by oscarfg Quote Link to comment Share on other sites More sharing options...
Advan Posted January 4, 2012 Report Share Posted January 4, 2012 Has probado a reiniciar? xD Quote Link to comment Share on other sites More sharing options...
Zaitsev Posted January 4, 2012 Report Share Posted January 4, 2012 (edited) 1 #include <sys/wait.h> 2 #include <unistd.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 6 int main(int argc, char *argv[]) 7 { 8 pid_t childpid; 9 int status, exit_code, x; 10 exit_code = EXIT_SUCCESS; 11 if (argc < 2) 12 { 13 printf(“Usage: %s command args\n“, argv[0]); 14 exit_code = EXIT_FAILURE; 15 } 16 else 17 { 18 switch (childpid = fork()) 19 { 20 case -1: 21 perror("Could not fork\n"); 22 exit_code = EXIT_FAILURE; 23 break; 24 case 0: 25 if (execvp(argv[1], &argv[1]) < 0) 26 { 27 perror(“Could not execute the command\n”); 28 exit_code = EXIT_FAILURE; 29 break; 30 } 31 default: 32 if ((x = wait(&status)) != childpid) 33 { 34 perror(“Wait interrupted by a signal\n”); 35 exit_code = EXIT_FAILURE; 36 } 37 } // end switch 38 } // end else 39 exit(exit_code); 40 } // end main Hace un huevo y medio que no tiro una sola línea de C, pero creo que más o menos podré explicar como funciona este a la vista del código. Líneas 11 - 15: Comprueba que el número de argumentos que se le pasan al programa sea un mínimo de 2. Línea 18: Se ejecuta un fork(). Esto hace que se clone el proceso principal en un proceso hijo. A partir de esta línea tenemos dos procesos diferentes, padre e hijo. La llamada a fork devuelve, en el caso del padre, el pid del hijo recién creado y en el caso del hijo, el valor entero 0. Así el switch hace que cada uno de los procesos ejecute un código diferente. Líneas 20 - 23: Esto se ejecuta si el valor de retorno del fork es -1, en cuyo caso no se ha podido crear un proceso hijo y el programa muestra un error por pantalla y termina la ejecución con un exit() en la línea 39. Líneas 24 - 30: Este trozo lo ejecuta el proceso hijo, y lo que hace es ejecutar un programa externo en la línea 25 con la llamada a execvp(). Si no puede ejecutarlo se muestra un mensaje de error y termina la ejecución del proceso hijo. Líneas 31 - 36: Este trozo solo lo ejecuta el proceso padre y lo que hace es simplemente esperar a que el hijo termine su ejecución mediante llamada a wait(). En cuanto el proceso hijo termina la ejecución, la llamada a wait retorna su pid y la ejecución del proceso padre termina también. Como conclusión, si se ejecuta la siguiente orden: $ ./misterioso_1 grep 8 fichero_previo Lo que va a pasar es que se va a crear un proceso hijo que va a ejecutar la orden "grep 8 fichero_previo" sacando por salida estándar el resultado. El programa grep saca por salida estándar todas las líneas del fichero especificado como segundo parámetro que contengan la cadena especificada como primer parámetro. Es decir, va a sacarte las líneas del fichero_previo que contengan al menos un carácter "8". Eso es todo, espero haberlo explicado bien y que te sirva para completar la práctica. Edited January 4, 2012 by Zaitsev Quote Link to comment Share on other sites More sharing options...
evola Posted January 4, 2012 Author Report Share Posted January 4, 2012 !!Gracias Zaitsev!! Es lo mismo que me dijo Kyle, al cual le estaré eternamente agradecido por el tiempo que se tomó. Voy a postear aquí mis respuestas y si no es mucha molestia miráis a ver si pongo alguna burrada ¿Faler? !!Otra vez gracias chicos!! a) Anotar, detalladamente, el comportamiento observado. Compilo mediante la orden: $gcc misterioso_1.c -o misterioso_1 Esto crea un ejecutable con nombre misterioso_1 y lo ejecuto tal como dice el enunciado: $./misterioso_1 grep 8 fichero_previo La salida da como resultado: caefqwdpo33e89dqwd39jdqq aefamaeo0eaem4mcadlm8aecme aemj45macso94to8am3e332ed Estas tres líneas son las únicas que contienen al menos un 8 y és exactamente la misma salida que si diéramos la orden: $ grep 8 fichero previo Explico el por qué en el apartado b. Explicar, detalladamente, el comportamiento observado. #include <sys/wait.h> // #include <stdio.h> // #include <unistd.h> // --> Importación de las cabeceras necesarias #include <stdlib.h> // int main(int argc, char *argv[]) //-->Inicio del main con la cantidad de argumentos en argc y los argumentos en argv[] { pid_t childpid; //-->creación de una variable childpid de tipo pid_t int status, exit_code, x; //-->Creación de varias variables de tipo entero exit_code = EXIT_SUCCESS; //--> igualamos exit_code a la variable EXIT_SUCCES que devuelve el estado de la terminación del programa if (argc < 2) //-->Si se han introducido menos de dos parátros { printf("Usage: %s command args\n", argv[0]); //-->Sacamos por pantalla el error exit_code = EXIT_FAILURE; // } else //-->Si los argumentos son 2 o más { switch (childpid = fork()) //-->Se crea un nuevo proceso hijo con la funcion fork() la cual devuelve el PID del hijo al padre { //-->y 0 al hijo (si todo ha ido bien), se asigna a chilpid y se hace un case con su valor case -1: //-->Si el proceso no se ha creado correctamente perror("Could not fork\n"); //-->Se saca por pantalla esta frase exit_code = EXIT_FAILURE; //-->y se almacena el error break; case 0: //-->Si el proceso hijo se crea correctamente pasa por aquí //(no así el padré que tendrá el PID del hijo mayor que 0) if (execvp(argv[1], &argv[1]) < 0) //e intenta ejecutar las ódenes pasadas como argumentos. { //Si devuelve -1 es que ha habido un error y entrará en este if. perror("Could not execute the command\n");//-->Imprimirá en pantalla el error y se almacena el código de error. exit_code = EXIT_FAILURE; break; } default: //-->Aquí entrará el padre por tener el PID del hijo (siempre mayor que 0) if ((x = wait(&status)) != childpid) //y esperará a que termine la ejecución del proceso hijo { perror("Wait interrupted by a signal\n");//a no ser que una señal lo interrumpa exit_code = EXIT_FAILURE; } } // end switch } // end else exit(exit_code); } // end main CONCLUSIÓN: Este programa lo que hace es crear un proceso hijo, el cual ejecuta los comandos introducidos, mientras que el padre espera a que se ejecute, momento en el cual terminan los dos. Quote Link to comment Share on other sites More sharing options...
Zaitsev Posted January 4, 2012 Report Share Posted January 4, 2012 Estupendo! Para mi está de 10... Quote Link to comment Share on other sites More sharing options...
evola Posted January 4, 2012 Author Report Share Posted January 4, 2012 (edited) Bueno, aquí os dejo el segundo. No os cortéis en comentar cualquier cosa mejorable #include <sys/stat.h> // #include <fcntl.h> // #include <unistd.h> //-->Importación de las cabeceras necesarias #include <stdlib.h> // #include <stdio.h> // #define TRUE 1 //-->Asignación de constantes #define FALSE 0 // #define BLKSIZE 1 // #define NEWFILE (O_WRONLY | O_CREAT | O_EXCL) //-->Modos de la función open(); Abre en modo: Lectura | Creación | Retorno de error si el fichero existe #define MODE600 (S_IRUSR | S_IWUSR) // -->Da los permisos de escritura y lectura al creador del archivo int main(int argc, char *argv[]) //-->Inicio del main con la cantidad de argumentos en argc y los argumentos en argv[] { int from_fd, to_fd, count, exit_code; //-->Creación de variables de tipo entero (from_fd para leer desde, to_fd para escribir a, y exit_code que almacena el código de error int written_flag, read_flag, end_of_file_flag; //-->Diferentes banderas para asegurarnos de que los archivos están listos para escritura/lectura char buf[bLKSIZE]; //-->¿Tamaño de buffer? exit_code = EXIT_SUCCESS; //-->Código de error if (argc != 3) //-->Si introducimos un número distinto de 3 argumentos { //nos dará error y entrará en este if printf("Usage: %s from_file to_file\n", argv[0]); //-->Imprime por pantalla el mensaje de error de argumentos exit_code = EXIT_FAILURE; //..>Recoge el código de error y lo almacena } else //-->Si el número de argumentos son correctos { //entramos en el siguiente if if ((from_fd = open(argv[1], O_RDONLY)) < 0) //-->Si existe algún problema con el proceso de apertura del fichero { //del argumento 1 (fichero_previo) en modo solo lectura entramos en este if perror("Could not open the source file\n");//el cual imprime el error y almacena el código exit_code = EXIT_FAILURE; } else //-->Si la apertura del fichero se realiza correctamente { if ((to_fd = open(argv[2], NEWFILE, MODE600)) < 0) //-->Si existe algún problema en la creación un fichero nuevo { //de nombre el argumento 2 y con los permisos de escritura/lectura perror("Could not create the destination file\n");//entramos en este if y sacamos por pantalla el mensaje de error exit_code = EXIT_FAILURE; //además de almacenar el código } else //-->Si la creación del archivo es correcta { written_flag = TRUE; //-->Activamos la banderas que nos indican que estamos listos para escribir read_flag = TRUE; //y leer end_of_file_flag = FALSE; //y que no se ha llegado al final del archivo while (written_flag && read_flag && !end_of_file_flag) //-->Mientras las banderas de escritura y lectura estén a true { //y la del final de archivo a false switch (count = read(from_fd, buf, sizeof(buf)))//-->Hacemos un switch con el tamaño del bufer de lectura { case -1: //-->Si es -1 es que ha habido un error y por lo tanto read_flag = FALSE; //pasamos la bandera de leer a falso perror("Could not read from source\n"); //y sacamos por pantalla el mensaje de error exit_code = EXIT_FAILURE; //además de almacenar el coádigo break; case 0: //-->Si el tamaño del budder de lectura es 0 significa que ya no tiene más que leer end_of_file_flag = TRUE;//así que pasamos la bandera de fin de archivo a true break; default: //-->Si el tamaño del buffer de lectura es mayor de 0 es que tenemos algo que escribir if (write(to_fd, buf, count) != count)//hacia el fichero_2 { //siepre que no haya un error de escritura written_flag = FALSE; //en cuyo caso pasamos la bandera de escritura a false perror("Could not write to destination\n"); //e imprimimos el mensaje de error exit_code = EXIT_FAILURE; } } //switch } // while if (close(to_fd) != 0) //-->Cierra el archivo al que le estamos escribiendo y si hay algún error { //entra en este if perror("Could not close the destination file\n");//imprime por pantalla el error exit_code = EXIT_FAILURE; //y almacena el código } } // else open to_fd if (close(from_fd) != 0) //-->Cierra el archivo desde el que estamos leyendo y comprueba que no hay error { //si hay ulgún problema al cerrarlo entra en este id perror("Could not close the source file\n");//imprime por pantalla que no ha podido cerrarlo exit_code = EXIT_FAILURE; //y almacena el código de error } } // else open from_fd } // else argc exit(exit_code); } // main CONCLUSIÓN: Este programa lo que hace es leer de un fichero (parámetro 1) y volcarlo su contenido en otro (parámetro 2) que ha sido creado por el mismo programa con los permisos de escritura y lectura del propietario del archivo: $ ls -al fichero_2 -rw------- 1 evola evola 261 2012-01-04 16:00 fichero_2 Edited January 4, 2012 by evola Quote Link to comment Share on other sites More sharing options...
evola Posted January 4, 2012 Author Report Share Posted January 4, 2012 Y aquí el 3º. Muchas gracias a todos por contestar, no sé qué haría sin vosotros. 3. Crear un fichero fuente con el código (en lenguaje C) que aparece en esta página (y la siguiente) y llamarlo misterioso_3.c, en el directorio de trabajo por defecto. Compilar y enlazar el código misterioso_3.c y nombrar al fichero ejecutable resultante, en el directorio de trabajo por defecto, con el nombre misterioso_3. Sin cambiar de directorio de trabajo por defecto, y en una situación en la que, en el directorio de trabajo por defecto, no existe una entrada con el nombre fichero_3, solicitarle, a un “intérprete de comandos de tipo UNIX”, la ejecución de los siguientes comandos: $ ./misterioso_3 fichero_3 tail –n [digito_3]->(2) fichero_previo $ head –n [digito_2]->(1) fichero_3 a) Anotar, detalladamente, el comportamiento observado. Una vez obtenido el fichero ejecutable misterioso_3 paso a ejecutarlo con los parámetros descritos: $ ./misterioso_3 fichero_3 tail -n 2 fichero_previo y el resultado es la creación de un nuevo fichero llamado como el primer argumento, fichero_3 el cual paso a mostrar $ cat fichero_3 eqro3q3ed05ms0394lndq39de aw34kd93523r9494rjf043432 Si ahora ejecuto la orden que me pide el enunciado obtengo: $ head -n 1 fichero_3 eqro3q3ed05ms0394lndq39de Dado que en fichero_3 tengo las últimas 2 líneas de fichero_previo, con esta última orden lo que consigo es la penúltima línea de fichero_previo. Explicar, detalladamente, el comportamiento observado. #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #define NEWFILE (O_WRONLY | O_CREAT | O_EXCL) #define MODE644 (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) int redirect_output(const char *file) //-->Entrada de la función con fichero_3 como parámetro { int return_code, fd; //-->Definición de variables enteras return_code = 0; //-->Inicialización de return_code a 0 if ((fd = open(file, NEWFILE, MODE644)) < 0)//-->Asociación de un descriptor de fichero a un nuevo fichero con los permisos (rw-r--r--) y asignación a fd { //-->Si la creación del archivo nuevo no se ha producido correctamente return_code = -1; //pasamos return_code a -1 (El entero a develver la función) } else //-->Si el fichero nuevo es creado correctamente { //entramos en el if principal if (dup2(fd, STDOUT_FILENO) < 0)//-->Cierra la salida estandar, copia el nuevo "file_descriptor en su lugar (redirección de la salida) { //y comprueba que su valor de retorno sea el nuevo fd y no -1 return_code = -1; //-->En el caso de que retorne -1 se habrá producido un error en el redireccionamiento } //así que devolvemos -1 else //-->Si el redireccionamiento se porduce con éxito { if (close(fd) != 0) //-->Se cierra el file descriptor { //y se comprueba que la operación no devuelve -1 return_code = -1;//-->Si ha devuelto -1 es que no se ha podido cerrar así que devolvemos -1 } } }//Fin else fd=open return return_code; //-->Si se ha cerrado correctamente es que la redirección se ha compretado correctamente y devolvemos 0 }//Fin función redirect_output int main(int argc, char *argv[]) //-->Inicio del main con la cantidad de argumentos en argc y los argumentos en argv[] { int exit_code; //-->entero donde almacenaremos el código de error de salida exit_code = EXIT_SUCCESS; //y asignación if (argc < 3) //-->Si el número de argumentos es menor a 3 { //no estamos haciendo lo que debemos printf("Usage: %s to_file command args\n", argv[0]);//y por lo tanto lanza un error exit_code = EXIT_FAILURE; } else //-->Si los argumentos son 3 o más { //entramos en el if if (redirect_output(argv[1]) == -1) //-->Llamamos a la función redirect_output con el argumento 1 (fichero_3) como argumento { //-->Si devuelve un -1 es que algo ha fallado perror("Could not redirect the output\n");//así que se imprimirá por pantalla que no se ha podido redirigir exit_code = EXIT_FAILURE; //y almacenamos el fallo } else //Si se devuelve un valor distinto a -1 es que la operación de redireccionamiento se ha realizado con éxito { //así que volcamos en la salida, que ya no será la pantalla sinó el argumento_1 (fichero_3) if (execvp(argv[2], &argv[2]) < 0)//las órdenes a partir del argumento 2 y comprobamos qué no nos devuelve un -1 { //-->En caso de que nos devuelva un -1 es que no se ha podido perror("Could not execute the command\n");//llevar a cabo con éxito las órdenes, se imprimirá por pantalla el eror exit_code = EXIT_FAILURE; //y se almacenará el código } } } exit(exit_code); }//Fin main CONCLUSIÓN: Este código lo que hace es crear un archivo con el nombre del primer argumento y redirecciona la salida a este archivo. Acto seguido vuelca en él la orden pasada con los siguientes argumentos. Quote Link to comment Share on other sites More sharing options...
Kyle_Katarn Posted January 4, 2012 Report Share Posted January 4, 2012 un apunte, en los comentarios del if (dup2(.......... Mejor poner, que redirecciona la salida standard, la pantalla, a disco. Y luego en las conclusiones, no pongas "acto seguido vuelca en el la orden ....", mejor que al ejecutarse la orden del sistema, esta no se visualiza por pantalla por que ha cambiado la salida standard en el procedimiento redirect_output, en su lugar se ha volcado al archivo que se puso como primer parametro en el prompt del sistema cuando ejecutamos nuestro codigo. Lo que tu pones no es que este mal, pero creo que es mas correcto esto despues de leer los comentarios del codigo Quote Link to comment Share on other sites More sharing options...
evola Posted January 9, 2012 Author Report Share Posted January 9, 2012 !!Mirelda Kyle, no sé por qué no había visto tu post!! Gracias tío, ahora mismo lo cambio. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.