Sospecho que el por qué tiene mucho que ver con la visión / diseño que dio forma a Unix (y, en consecuencia, Linux), y las ventajas derivadas de ello.
Sin duda, hay un beneficio de rendimiento no despreciable al no acelerar un proceso adicional, pero creo que hay más: unix temprano tenía una metáfora de "todo es un archivo", que tiene una ventaja no obvia pero elegante si se mira desde una perspectiva del sistema, en lugar de una perspectiva de script de shell.
Digamos que tiene su null
programa de línea de comandos y /dev/null
el nodo del dispositivo. Desde una perspectiva de script de shell, el foo | null
programa es realmente útil y conveniente , y foo >/dev/null
toma un poco más de tiempo para escribir y puede parecer extraño.
Pero aquí hay dos ejercicios:
Vamos a implementar el programa null
usando las herramientas Unix existentes y /dev/null
- fácil: cat >/dev/null
. Hecho.
¿Se puede implementar /dev/null
en términos de null
?
Tiene toda la razón en que el código C para descartar la entrada es trivial, por lo que puede que aún no sea obvio por qué es útil tener un archivo virtual disponible para la tarea.
Considere: casi todos los lenguajes de programación ya necesitan trabajar con archivos, descriptores de archivos y rutas de archivos, porque formaron parte del paradigma "todo es un archivo" de Unix desde el principio.
Si todo lo que tiene son programas que escriben en stdout, bueno, al programa no le importa si los redirige a un archivo virtual que traga todas las escrituras, o una tubería a un programa que traga todas las escrituras.
Ahora, si tiene programas que toman rutas de archivos para leer o escribir datos (lo que hace la mayoría de los programas), y desea agregar la funcionalidad de "entrada en blanco" o "descartar esta salida" a esos programas, bueno, /dev/null
eso es gratis.
Tenga en cuenta que la elegancia de esto es que reduce la complejidad del código de todos los programas involucrados: para cada caso de uso común pero especial que su sistema puede proporcionar como un "archivo" con un "nombre de archivo" real, su código puede evitar agregar un comando personalizado Opciones de línea y rutas de código personalizadas para manejar.
La buena ingeniería de software a menudo depende de encontrar metáforas buenas o "naturales" para abstraer algún elemento de un problema de una manera que sea más fácil de pensar pero que sea flexible , para que pueda resolver básicamente el mismo rango de problemas de nivel superior sin tener que dedicar el tiempo y la energía mental a reimplementar soluciones a los mismos problemas de nivel inferior constantemente.
"Todo es un archivo" parece ser una de esas metáforas para acceder a los recursos: se llama open
a una ruta determinada en un espacio de nombres jerárquico, se obtiene una referencia (descriptor de archivo) al objeto, y se puede read
y write
, etc., en los descriptores de archivo. Sus stdin / stdout / stderr también son descriptores de archivos que se abrieron previamente para usted. Sus tuberías son solo archivos y descriptores de archivos, y la redirección de archivos le permite pegar todas estas piezas juntas.
Unix tuvo tanto éxito como en parte debido a lo bien que funcionaron estas abstracciones juntas, y /dev/null
se entiende mejor como parte de ese todo.
PD Vale la pena mirar la versión Unix de "todo es un archivo" y cosas /dev/null
como los primeros pasos hacia una generalización más flexible y poderosa de la metáfora que se ha implementado en muchos sistemas que siguieron.
Por ejemplo, en Unix, los objetos especiales como archivos /dev/null
tuvieron que implementarse en el núcleo en sí, pero resulta que es lo suficientemente útil como para exponer la funcionalidad en forma de archivo / carpeta que desde entonces se han creado múltiples sistemas que proporcionan una forma para los programas Para hacer eso.
Uno de los primeros fue el sistema operativo Plan 9, creado por algunas de las mismas personas que crearon Unix. Más tarde, GNU Hurd hizo algo similar con sus "traductores". Mientras tanto, Linux terminó recibiendo FUSE (que ahora también se ha extendido a los otros sistemas convencionales).
cat foo | bar
es mucho peor (a escala) quebar <foo
.cat
es un programa trivial, pero incluso un programa trivial crea costos (algunos de ellos específicos de la semántica FIFO) porque los programas no puedenseek()
dentro de FIFO, por ejemplo, un programa que podría implementarse eficientemente con la búsqueda puede terminar haciendo operaciones mucho más costosas cuando se le da una canalización; con un dispositivo de caracteres como/dev/null
este puede falsificar esas operaciones, o con un archivo real puede implementarlas, pero un FIFO no permite ningún tipo de manejo contextualizado).