stringtranslate.com

Flujos estándar

En programación informática , los flujos estándar son canales de comunicación de entrada y salida preconectados [1] entre un programa informático y su entorno cuando comienza su ejecución. Las tres conexiones de entrada/salida (E/S) se denominan entrada estándar ( stdin ), salida estándar ( stdout ) y error estándar ( stderr ). Originalmente, la E/S se realizaba a través de una consola del sistema conectada físicamente (entrada a través del teclado, salida a través del monitor), pero los flujos estándar abstraen esto. Cuando se ejecuta un comando a través de un shell interactivo , los flujos suelen estar conectados a la terminal de texto en la que se ejecuta el shell, pero se pueden cambiar con una redirección o una canalización . De forma más general, un proceso hijo hereda los flujos estándar de su proceso padre .

Solicitud

Los flujos estándar de entrada, salida y error en una configuración predeterminada común

Los usuarios generalmente conocen los flujos estándar como canales de entrada y salida que manejan datos provenientes de un dispositivo de entrada o que escriben datos desde la aplicación. Los datos pueden ser texto con cualquier codificación o datos binarios . Cuando un programa se ejecuta como un demonio , su flujo de error estándar se redirige a un archivo de registro, generalmente con fines de análisis de errores.

Los flujos se pueden utilizar para encadenar aplicaciones, lo que significa que el flujo de salida de un programa se puede redirigir para que sea el flujo de entrada de otra aplicación. En muchos sistemas operativos, esto se expresa enumerando los nombres de las aplicaciones, separados por el carácter de barra vertical, por este motivo, a menudo llamado carácter de canalización . Un ejemplo bien conocido es el uso de una aplicación de paginación , como more , que proporciona al usuario control sobre la visualización del flujo de salida en la pantalla.

Fondo

En la mayoría de los sistemas operativos anteriores a Unix , los programas tenían que conectarse explícitamente a los dispositivos de entrada y salida apropiados. Las complejidades específicas del sistema operativo hicieron que esta fuera una tarea de programación tediosa. En muchos sistemas era necesario obtener el control de las configuraciones del entorno, acceder a una tabla de archivos local, determinar el conjunto de datos deseado y manejar el hardware correctamente en el caso de un lector de tarjetas perforadas , una unidad de cinta magnética , una unidad de disco , una impresora de línea , una perforadora de tarjetas o una terminal interactiva.

Uno de los avances revolucionarios de Unix fueron los dispositivos abstractos , que eliminaron la necesidad de que un programa supiera o se preocupara por el tipo de dispositivos con los que se estaba comunicando [ cita requerida ] . Los sistemas operativos más antiguos obligaban al programador a utilizar una estructura de registros y, con frecuencia, una semántica de datos no ortogonal y un control de dispositivos. Unix eliminó esta complejidad con el concepto de flujo de datos: una secuencia ordenada de bytes de datos que se pueden leer hasta el final del archivo . Un programa también puede escribir bytes según lo desee y no necesita, ni puede, declarar fácilmente su recuento o agrupación.

Otro gran avance de Unix fue asociar automáticamente la entrada y la salida al teclado y la pantalla del terminal, respectivamente, de forma predeterminada [ cita requerida ] : el programa (y el programador) no hacían absolutamente nada para establecer la entrada y la salida para un programa de entrada-proceso-salida típico (a menos que eligiera un paradigma diferente). En contraste, los sistemas operativos anteriores generalmente requerían algún lenguaje de control de tareas (a menudo complejo ) para establecer conexiones, o la carga equivalente tenía que ser orquestada por el programa. [ cita requerida ]

Dado que Unix proporcionaba flujos estándar, el entorno de ejecución C de Unix también estaba obligado a soportarlos. Como resultado, la mayoría de los entornos de ejecución C (y sus descendientes ), independientemente del sistema operativo, brindan una funcionalidad equivalente.

Entrada estándar (stdin)

La entrada estándar es un flujo de datos desde el cual un programa lee sus datos de entrada. El programa solicita transferencias de datos mediante el uso de la operación de lectura . No todos los programas requieren una entrada de flujo de datos. Por ejemplo, los programas dir y ls (que muestran los nombres de los archivos contenidos en un directorio) pueden tomar argumentos de línea de comandos , pero realizan sus operaciones sin ninguna entrada de datos de flujo de datos.

A menos que se redirija , la entrada estándar se hereda del proceso padre. En el caso de un shell interactivo, esto suele estar asociado con el dispositivo de entrada de un terminal (o pseudoterminal ) que, en última instancia, está vinculado al teclado del usuario .

En los sistemas POSIX , el descriptor de archivo para la entrada estándar es 0 (cero); la definición POSIX es ; la abstracción C correspondiente se proporciona a través de la variable global. De manera similar, la variable C++ global de tipo proporciona una abstracción a través de C++ streams . Existen abstracciones similares en las bibliotecas de E/S estándar de prácticamente todos los lenguajes de programación .<unistd.h>STDIN_FILENO<stdio.h>FILE* stdinstd::cin<iostream>

Salida estándar (stdout)

La salida estándar es un flujo en el que un programa escribe sus datos de salida. El programa solicita la transferencia de datos con la operación de escritura . No todos los programas generan una salida. Por ejemplo, el comando de cambio de nombre de archivo (también llamado mv , move o ren ) no indica si se realizó correctamente.

A menos que se redirija , la salida estándar se hereda del proceso principal. En el caso de un shell interactivo, normalmente es la terminal de texto que inició el programa.

El descriptor de archivo para la salida estándar es 1 (uno); la definición POSIX <unistd.h> es STDOUT_FILENO; la <stdio.h>variable C correspondiente es FILE* stdout; de manera similar, la <iostream>variable C++ es std::cout.

Error estándar (stderr)

El error estándar es otro flujo de salida que suelen utilizar los programas para generar mensajes de error o diagnósticos. Es un flujo independiente de la salida estándar y se puede redirigir por separado.

Esto resuelve el problema del semipredicado , permitiendo distinguir la salida de los errores, y es análogo a una función que devuelve un par de valores – ver Problema del semipredicado: retorno de múltiples valores . El destino habitual es la terminal de texto que inició el programa para proporcionar la mejor posibilidad de ser visto incluso si se redirige la salida estándar (por lo que no se observa fácilmente). Por ejemplo, la salida de un programa en una tubería se redirige a la entrada del siguiente programa o un archivo de texto, pero los errores de cada programa siguen yendo directamente a la terminal de texto para que el usuario pueda revisarlos en tiempo real. [2]

Es aceptable y normal dirigir la salida estándar y el error estándar al mismo destino, como la terminal de texto. Los mensajes aparecen en el mismo orden en que el programa los escribe, a menos que se utilice un buffer . Por ejemplo, en situaciones comunes, el flujo de error estándar no se almacena en buffer, pero el flujo de salida estándar sí se almacena en buffer de línea; en este caso, el texto escrito posteriormente en el error estándar puede aparecer antes en la terminal, si el buffer del flujo de salida estándar aún no está lleno.

El descriptor de archivo para el error estándar está definido por POSIX como 2 (dos); el archivo de encabezado <unistd.h>STDERR_FILENO proporciona el símbolo ; [3] la <stdio.h>variable C correspondiente es FILE* stderr. El <iostream>encabezado estándar de C++ proporciona dos variables asociadas con este flujo: std::cerry std::clog, la primera no tiene búfer y la segunda utiliza el mismo mecanismo de búfer que todos los demás flujos de C++.

Los shells de estilo Bourne permiten redirigir el error estándar al mismo destino al que se dirige la salida estándar mediante

2>&1

Los shells de estilo csh permiten redirigir el error estándar al mismo destino al que se dirige la salida estándar mediante

>&

El error estándar se agregó a Unix en la década de 1970 después de varias ejecuciones de fotocomposición inútiles que terminaron con mensajes de error compuestos en lugar de mostrarse en la terminal del usuario. [4]

Cronología

Década de 1950: Fortran

Fortran tiene el equivalente de los descriptores de archivos de Unix: por convención, muchas implementaciones de Fortran utilizan números de unidad UNIT=5para stdin, UNIT=6stdout y UNIT=0stderr. En Fortran-2003, el ISO_FORTRAN_ENVmódulo intrínseco se estandarizó para incluir las constantes nombradas INPUT_UNIT, OUTPUT_UNITy ERROR_UNITpara especificar de manera portable los números de unidad.

! FORTRAN 77 ejemplo PROGRAMA NÚMERO ENTERO PRINCIPAL LEER ( UNIDAD = 5 , * ) NÚMERO ESCRIBIR ( UNIDAD = 6 , '(A,I3)' ) ' EL NÚMERO ES: ' , NÚMERO FIN       
! Programa de ejemplo de Fortran 2003 uso principal iso_fortran_env implícito ninguno entero :: número lectura ( unidad = UNIDAD_DE_ENTRADA , * ) número escritura ( unidad = UNIDAD_DE_SALIDA , '(a,i3)' ) 'El número es: ' , número fin del programa            

1960: ALGOL 60

ALGOL 60 fue criticado por no tener acceso estándar a archivos. [ cita requerida ]

1968: ALGOL 68

Las facilidades de entrada y salida de ALGOL 68 se denominaron colectivamente transput. [5] Koster coordinó la definición del estándar transput . El modelo incluía tres canales estándar: stand in, stand out, y stand back.

Década de 1970: C y Unix

En el lenguaje de programación C , los flujos de entrada, salida y error estándar se adjuntan a los descriptores de archivo Unix existentes 0, 1 y 2 respectivamente. [6] En un entorno POSIX, se deben utilizar las definiciones de < unistd.h > STDIN_FILENO , STDOUT_FILENO o STDERR_FILENO en lugar de los números mágicos . También se proporcionan los punteros de archivo stdin , stdout y stderr .

Ken Thompson (diseñador e implementador del sistema operativo Unix original) modificó sort en la versión 5 de Unix para aceptar "-" como representación de la entrada estándar, lo que se extendió a otras utilidades y se convirtió en parte del sistema operativo como un archivo especial en la versión 8. Los diagnósticos fueron parte de la salida estándar hasta la versión 6 , después de la cual Dennis M. Ritchie creó el concepto de error estándar. [7]

1995: Java

En Java , los flujos estándar se denominan System.in(para stdin), System.out(para stdout) y System.err(para stderr). [8]

public static void main ( String args [] ) { try { BufferedReader br = new BufferedReader ( new InputStreamReader ( System . in )); String s = br . readLine (); double number = Double . parseDouble ( s ); System . out . println ( "El número es:" + number ); } catch ( Exception e ) { System . err . println ( "Error:" + e . getMessage ()); } }                                  

Década de 2000: .NET

En C# y otros lenguajes .NET , los flujos estándar se denominan System.Console.In(para stdin), System.Console.Out(para stdout) y System.Console.Error(para stderr). [9] Las capacidades básicas de lectura y escritura para los flujos stdin y stdout también son accesibles directamente a través de la clase System.Console(por ejemplo, System.Console.WriteLine()se pueden usar en lugar de System.Console.Out.WriteLine()).

System.Console.In, System.Console.Outy System.Console.Errorson objetos System.IO.TextReader(stdin) y System.IO.TextWriter(stdout, stderr) que solo permiten el acceso a los flujos estándar subyacentes en forma de texto. El acceso binario completo a los flujos estándar debe realizarse a través de los System.IO.Streamobjetos devueltos por System.Console.OpenStandardInput(), System.Console.OpenStandardOutput()y System.Console.OpenStandardError()respectivamente.

// Ejemplo de C# public static int Main ( string [ ] args ) { try { string s = System.Console.In.ReadLine ( ) ; double number = double.Parse ( s ) ; System.Console.Out.WriteLine ( " El número es : { 0 : F3 } " , number ) ; return 0 ;                   // Si Parse() generó una excepción } catch ( ArgumentNullException ) { System . Console . Error . WriteLine ( "¡No se ingresó ningún número!" ); } catch ( FormatException ) { System . Console . Error . WriteLine ( "¡El valor especificado no es un número válido!" ); } catch ( OverflowException ) { System . Console . Error . WriteLine ( "¡El número especificado es demasiado grande!" ); }                  devolver - 1 ; } 
' Ejemplo de Visual Basic .NETFunción pública Main () como entero Intentar Dim s como String = System . Console . [ In ] . ReadLine () Dim número como Double = Double . Parse ( s ) System . Console . Out . WriteLine ( "El número es: {0:F3}" , número ) Devuelve 0                      ' Si Parse() lanzó una excepción Catch ex As System . ArgumentNullException System . Console . [ Error ] . WriteLine ( "¡No se ingresó ningún número!" ) Catch ex2 As System . FormatException System . Console . [ Error ] . WriteLine ( "¡El valor especificado no es un número válido!" ) Catch ex3 As System . OverflowException System . Console . [ Error ] . WriteLine ( "¡El número especificado es demasiado grande!" ) End Try                  Retorno - 1 Función final  

Al aplicar la System.Diagnostics.Process clase, se pueden utilizar las propiedades StandardInput de instancia , StandardOutputy StandardErrorde esa clase para acceder a los flujos estándar del proceso.

2000 - : Python (2 o 3)

El siguiente ejemplo, escrito en Python , muestra cómo redirigir la entrada estándar tanto a la salida estándar como a un archivo de texto.

#!/usr/bin/env pythonimportar  sistema# Guarda la salida estándar actual para que podamos revertir sys.stdout# después de que completemos nuestra redirecciónstdin_fileno  =  sys . stdinstdout_fileno  =  sys . stdout# Redirigir sys.stdout al archivosys . stdout  =  open ( "miarchivo.txt" ,  "w" )Ctrl  =  0para  entradas  en  stdin_fileno : ctrs  =  cadena ( ctr ) # Imprime en la salida estándar redirigida () sys . stdout . write ( ctrs  +  ") esto es para el redireccionado --->"  +  inps  +  " \n " ) # Imprime en el controlador de salida estándar guardado real stdout_fileno . write ( ctrs  +  ") esto es al actual --->"  +  inps  +  " \n " ) Ctrl  =  Ctrl  +  1# Cerrar el archivosys . stdout . close ()# Restaurar sys.stdout a nuestro antiguo controlador de archivos guardadosys . stdout  =  número_archivo_stdout

GUI

Las interfaces gráficas de usuario (GUI) no siempre hacen uso de los flujos estándar; lo hacen cuando las GUI son envoltorios de scripts subyacentes y/o programas de consola, por ejemplo, la GUI del administrador de paquetes Synaptic , que envuelve los comandos apt en Debian y/o Ubuntu. Las GUI creadas con herramientas de scripts como Zenity y KDialog por el proyecto KDE [10] hacen uso de stdin, stdout y stderr, y se basan en scripts simples en lugar de una GUI completa programada y compilada en C/C++ usando Qt , GTK u otro marco de widgets propietario equivalente.

El menú Servicios , tal como se implementó en NeXTSTEP y Mac OS X , también es análogo a los flujos estándar. En estos sistemas operativos, las aplicaciones gráficas pueden proporcionar funcionalidad a través de un menú para todo el sistema que opera sobre la selección actual en la GUI, sin importar en qué aplicación se encuentre.

Algunos programas GUI, principalmente en Unix, aún escriben información de depuración en la entrada de error estándar. Otros (como muchos reproductores multimedia de Unix) pueden leer archivos desde la entrada estándar. Los programas populares de Windows que abren una ventana de consola independiente además de sus ventanas GUI son los emuladores pSX y DOSBox .

El servidor GTK puede utilizar stdin como interfaz de comunicación con un programa interpretado para realizar una GUI.

El paradigma del Administrador de interfaz Common Lisp "presenta" elementos GUI enviados a un flujo de salida extendido.

Véase también

Referencias

  1. ^ DM Ritchie, "Un sistema de entrada-salida de flujo", AT&T Bell Laboratories Technical Journal, 68(8), octubre de 1984.
  2. ^ "¿Qué son stdin, stdout y stderr en Linux? | CodePre.com". 2 de diciembre de 2021. Consultado el 8 de abril de 2022 .
  3. ^ "<unistd.h>". Especificaciones básicas de The Open Group, número 6: IEEE Std 1003.1, edición 2004. The Open Group. 2004.
  4. ^ Johnson, Steve (11 de diciembre de 2013). «[TUHS] Fotocomposidora Graphic Systems C/A/T» (Lista de correo). Archivado desde el original el 25 de septiembre de 2020. Consultado el 7 de noviembre de 2020 .
  5. ^ "Informe revisado sobre el lenguaje algorítmico Algol 68", editado por A. van Wijngaarden, BJ Mailloux, JEL Peck, CHA Koster, M. Sintzoff, CH Lindsey, LGLT Meertens y RG Fisker, Sección 10.3.
  6. ^ "Stdin(3): flujos de E/S estándar - página del manual de Linux". die.net . Archivado desde el original el 8 de junio de 2023.
  7. ^ McIlroy, MD (1987). Un lector de Unix para investigación: extractos anotados del Manual del programador, 1971–1986 (PDF) (Informe técnico). CSTR. Bell Labs. 139. Archivado (PDF) del original el 15 de diciembre de 2023.
  8. ^ "Sistema (Java Platform SE 7)". Centro de ayuda de Oracle . Consultado el 20 de julio de 2012 .
  9. ^ ".NET Framework 4.7.1, mscorlib, console.cs". Fuente de referencia: Microsoft . Archivado desde el original el 10 de diciembre de 2017. Consultado el 10 de diciembre de 2017 .
  10. ^ Kißling, Kristian (2009). "Añadir elementos gráficos a tus scripts con Zenity y KDialog". Linux Magazine . Consultado el 11 de abril de 2021 .

Fuentes

Enlaces externos