¿Por qué existen open()
y close()
existen en el diseño del sistema de archivos Unix?
¿No podría el sistema operativo detectar la primera vez read()
o write()
fue llamado y hacer lo open()
que normalmente haría?
fuente
¿Por qué existen open()
y close()
existen en el diseño del sistema de archivos Unix?
¿No podría el sistema operativo detectar la primera vez read()
o write()
fue llamado y hacer lo open()
que normalmente haría?
Dennis Ritchie menciona en «La evolución del sistema de tiempo compartido Unix» que open
, y close
junto con read
, write
y creat
estuvieron presentes en el sistema desde el principio.
Supongo que un sistema sin open
y close
no sería inconcebible, sin embargo, creo que complicaría el diseño. En general, desea realizar múltiples llamadas de lectura y escritura, no solo una, y eso probablemente fue especialmente cierto en aquellas computadoras viejas con RAM muy limitada en la que se originó UNIX. Tener un controlador que mantenga su posición actual de archivo simplifica esto. Si read
owrite
para devolver el identificador, tendrían que devolver un par, un identificador y su propio estado de devolución. La parte de manejo del par sería inútil para todas las demás llamadas, lo que haría que ese arreglo fuera incómodo. Dejar el estado del cursor en el núcleo le permite mejorar la eficiencia no solo mediante el almacenamiento en búfer. También hay algunos costos asociados con la búsqueda de rutas: tener un identificador le permite pagarlo solo una vez. Además, algunos archivos en la visión del mundo UNIX ni siquiera tienen una ruta de acceso al sistema de archivos (o no la tenían, ahora lo hacen con cosas como /proc/self/fd
).
open
/ close
, estarías seguro de implementar cosas como /dev/stdout
permitir tuberías.
open()
a get_inode()
e hizo que todo el sistema sea más rígida (imposible de leer / escribir el mismo archivo en varias posiciones al mismo tiempo).
Entonces todas las llamadas read
y write
tendrían que pasar esta información en cada operación:
Si se tiene en cuenta los independientes llamadas open
, read
, write
y close
para ser más simple que una E / S de propósito único mensaje se basa en su filosofía de diseño. Los desarrolladores de Unix optaron por utilizar operaciones y programas simples que se pueden combinar de muchas maneras, en lugar de una sola operación (o programa) que hace todo.
read
y write
no están restringidos a archivos que viven en un sistema de archivos, y esa es una decisión fundamental de diseño en Unix, como explica pjc50.
lseek
)
El concepto del identificador de archivos es importante debido a la elección de diseño de UNIX de que "todo es un archivo", incluidas las cosas que no forman parte del sistema de archivos. Como unidades de cinta, el teclado y la pantalla (¡o teletipo!), Lectores de tarjetas / cintas perforadas, conexiones en serie, conexiones de red y (la invención clave de UNIX) conexiones directas a otros programas llamados "tuberías".
Si observa muchas de las simples utilidades estándar de UNIX como grep
, especialmente en sus versiones originales, notará que no incluyen llamadas a open()
y close()
sino solo read
y write
. El shell configura los identificadores de archivos fuera del programa y los pasa cuando se inicia. Por lo tanto, el programa no tiene que preocuparse si está escribiendo en un archivo o en otro programa.
Así como open
, las otras formas de obtener los descriptores de fichero son socket
, listen
, pipe
, dup
, y un mecanismo muy Heath Robinson para el envío de descriptores de archivos a través de canalizaciones: https://stackoverflow.com/questions/28003921/sending-file-descriptor-by-linux -enchufe
Editar: algunas notas de clase que describen las capas de indirección y cómo esto le permite a O_APPEND trabajar con sensatez. Tenga en cuenta que mantener los datos del inodo en la memoria garantiza que el sistema no tendrá que ir a buscarlos nuevamente para la próxima operación de escritura.
creat
, y listen
no crea un fd, pero cuando (y si) entra una solicitud mientras se escucha, accept
crea y devuelve un fd para el nuevo socket (conectado).
pipe
se introdujo unos años después del inicio del desarrollo en Unix.
La respuesta es no, porque open () y close () crean y destruyen un controlador, respectivamente. Hay momentos (bueno, todo el tiempo, realmente) en los que es posible que desee garantizar que es la única persona que llama con un nivel de acceso particular, ya que otra persona (por ejemplo) que escribe en un archivo que está analizando inesperadamente podría abandonar una aplicación en un estado desconocido o que conduzca a un punto muerto o un punto muerto, por ejemplo, el lema de Dining Philosophers.
Incluso sin esa consideración, hay implicaciones de rendimiento a considerar; close () permite que el sistema de archivos (si es apropiado o si lo solicitó) vacíe el búfer que estaba ocupando, una operación costosa. Varias ediciones consecutivas en un flujo en memoria son mucho más eficientes que varios ciclos de lectura-escritura-modificación esencialmente no relacionados a un sistema de archivos que, por lo que usted sabe, existe a medio mundo de distancia disperso en un centro de datos de almacenamiento masivo de alta latencia. Incluso con el almacenamiento local, la memoria suele ser muchos órdenes de magnitud más rápida que el almacenamiento masivo.
Open () ofrece una forma de bloquear archivos mientras están en uso. Si el sistema operativo abriera, leyera / escribiera y luego volviera a cerrar el sistema operativo, no habría nada que impidiera que otras aplicaciones cambien esos archivos entre operaciones.
Si bien esto puede ser manejable (muchos sistemas admiten acceso a archivos no exclusivo) por simplicidad, la mayoría de las aplicaciones asumen que los archivos que tienen abiertos no cambian.
Debido a que la ruta del archivo podría moverse mientras se supone que permanecerá igual.
Leer y escribir en un sistema de archivos puede implicar una gran variedad de esquemas de almacenamiento en búfer, mantenimiento del sistema operativo, administración de discos de bajo nivel y una gran cantidad de otras posibles acciones. Entonces, las acciones de open()
y close()
sirven como la configuración para este tipo de actividades bajo el capó. Las diferentes implementaciones de un sistema de archivos podrían personalizarse según sea necesario y seguir siendo transparentes para el programa de llamada.
Si el sistema operativo no tenía abrir / cerrar, entonces con read
o write
, esas acciones de archivo aún tendrían que realizar cualquier inicialización, limpieza / gestión de búfer, etc. cada vez. Eso es una gran carga para imponer para lecturas y escrituras repetitivas.
El mantra de Unix es "ofrecer una forma de hacer las cosas", lo que significa "factorizar" en piezas (reutilizables) que se combinarán a voluntad. Es decir, en este caso, separe la creación y destrucción de identificadores de archivos de su uso. Beneficios importantes llegaron más tarde, con tuberías y conexiones de red (también se manipulan a través de identificadores de archivos, pero se crean de otras maneras). Ser capaz de enviar identificadores de archivos (por ejemplo, pasarlos a procesos secundarios como "archivos abiertos" que sobreviven exec(2)
e incluso a procesos no relacionados a través de una tubería) solo es posible de esta manera. Particularmente si desea ofrecer acceso controlado a un archivo protegido. Entonces puedes, por ejemplo, abrir/etc/passwd
para escribir y pasar eso a un proceso secundario que no tiene permitido abrir ese archivo para escribir (sí, sé que este es un ejemplo ridículo, siéntase libre de editar con algo más realista).
open()
existe. "¿No podría el sistema operativo detectar la primera vez read () o write () y hacer lo que normalmente haría open ()?" ¿Hay alguna sugerencia correspondiente para cuándo ocurriría el cierre ?read()
o awrite()
qué archivo acceder? Presumiblemente pasando el camino. ¿Qué sucede si la ruta del archivo cambia mientras está accediendo (entre dosread()
owrite()
llamadas)?read()
ywrite()
solo se activaopen()
.