salida redireccionar redireccionamiento por pipelines mensajes los guardar generados filtros estandar error envían entrada ejemplos dónde defecto comandos comando archivo c exec fork

redireccionamiento - redireccionar entrada estandar c



Redirigir la salida del ejecutor a un búfer o archivo (4)

Estoy escribiendo un programa C en donde fork() , exec() y wait() . Me gustaría tomar el resultado del programa que ejecuté para escribirlo en un archivo o buffer.

Por ejemplo, si ejecuto ls quiero escribir file1 file2 etc en buffer / archivo. No creo que haya una forma de leer stdout, ¿eso significa que tengo que usar una tubería? ¿Hay un procedimiento general aquí que no he podido encontrar?


Como parece que vas a usar esto en un entorno Linux / cygwin, quieres usar popen . Es como abrir un archivo, solo obtendrá los programas de ejecución stdout , para que pueda usar su fscanf , fread normal, etc.


Debes decidir exactamente qué quieres hacer y, preferiblemente, explicarlo con más claridad.

Opción 1: Archivo

Si sabe a qué archivo desea que vaya la salida del comando ejecutado, entonces:

  1. Asegúrese de que el padre y el niño estén de acuerdo con el nombre (el padre decide el nombre antes de bifurcar).
  2. Parent tenedores: tienes dos procesos.
  3. El niño reorganiza las cosas para que el descriptor de archivo 1 (salida estándar) vaya al archivo.
  4. Por lo general, puede dejar el error estándar solo; puede redirigir la entrada estándar desde / dev / null.
  5. Niño luego ejecuta el comando relevante; dicho comando se ejecuta y cualquier salida estándar va al archivo (esta es la redirección básica de E / S del shell).
  6. El proceso ejecutado luego termina.
  7. Mientras tanto, el proceso principal puede adoptar una de dos estrategias principales:
    • Abra el archivo para leer y siga leyendo hasta que llegue a un EOF. Luego debe verificar si el niño murió (para que no haya más datos para leer), o quedarse esperando más información del niño.
    • Espere a que el niño muera y luego abra el archivo para leer.
    • La ventaja de la primera es que el padre puede hacer algo de su trabajo mientras el niño también se está ejecutando; la ventaja de la segunda es que no tiene que manipular el sistema de E / S (leyendo repetidamente pasado EOF).

Opción 2: Pipe

Si desea que el padre lea la salida del niño, haga los arreglos para que el niño canalice su salida al padre.

  1. Use popen () para hacer esto de la manera más fácil. Ejecutará el proceso y enviará la salida a su proceso principal. Tenga en cuenta que el padre debe estar activo mientras el hijo está generando el resultado ya que las tuberías tienen un tamaño de búfer pequeño (a menudo 4-5 KB) y si el hijo genera más datos que eso mientras el padre no lee, el hijo bloqueará hasta que el padre lee Si el padre espera que el niño muera, tiene un punto muerto.
  2. Use pipe (), etc. para hacer esto de la manera difícil. El padre llama a pipe (), luego se bifurca. El niño clasifica las tuberías para que el extremo de escritura de la tubería sea su salida estándar y se asegura de que todas las demás descripciones de archivos relacionadas con la tubería estén cerradas. Esto bien podría usar la llamada al sistema dup2 (). A continuación, ejecuta el proceso requerido, que envía su salida estándar por la tubería.
  3. Mientras tanto, el padre también cierra los extremos no deseados de la tubería y luego comienza a leer. Cuando obtiene EOF en la tubería, sabe que el niño ha terminado y cerrado la tubería; también puede cerrar su extremo de la tubería.

Después de bifurcar, use dup2(2) para duplicar el FD del archivo en FD de stdout, luego dup2(2) exec.


Para enviar la salida a otro archivo (excluyo la comprobación de errores para centrarme en los detalles importantes):

if (fork() == 0) { // child int fd = open(file, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); dup2(fd, 1); // make stdout go to file dup2(fd, 2); // make stderr go to file - you may choose to not do this // or perhaps send stderr to another file close(fd); // fd no longer needed - the dup''ed handles are sufficient exec(...); }

Para enviar la salida a una tubería para que luego pueda leer la salida en un búfer:

int pipefd[2]; pipe(pipefd); if (fork() == 0) { close(pipefd[0]); // close reading end in the child dup2(pipefd[1], 1); // send stdout to the pipe dup2(pipefd[1], 2); // send stderr to the pipe close(pipefd[1]); // this descriptor is no longer needed exec(...); } else { // parent char buffer[1024]; close(pipefd[1]); // close the write end of the pipe in the parent while (read(pipefd[0], buffer, sizeof(buffer)) != 0) { } }