En Linux, una ejecución finalizada de un comando como cp
o dd
no significa que los datos se han escrito en el dispositivo. Uno tiene que, por ejemplo, llamar sync
o invocar la función "Quitar con seguridad" o "Expulsar" en la unidad.
¿Cuál es la filosofía detrás de este enfoque? ¿Por qué no se escriben los datos de una vez? ¿No hay peligro de que la escritura falle debido a un error de E / S?
kernel
drivers
io
unix-philosophy
marmistrz
fuente
fuente
Respuestas:
Eficiencia (mejor uso de las características del disco) y rendimiento (permite que la aplicación continúe inmediatamente después de una escritura).
La principal ventaja es que el sistema operativo es libre de reordenar y fusionar operaciones de escritura contiguas para mejorar su uso de ancho de banda (menos operaciones y menos búsquedas). Los discos duros funcionan mejor cuando se solicita una pequeña cantidad de operaciones grandes, mientras que las aplicaciones tienden a necesitar una gran cantidad de operaciones pequeñas. Otra optimización clara es que el sistema operativo también puede eliminar todas las escrituras excepto la última cuando el mismo bloque se escribe varias veces en un corto período de tiempo, o incluso eliminar algunas escrituras todas juntas si el archivo afectado se ha eliminado mientras tanto.
Estas escrituras asincrónicas se realizan después de que la
write
llamada del sistema ha regresado. Esta es la segunda ventaja más visible para el usuario. Las escrituras asincrónicas aceleran las aplicaciones, ya que son libres de continuar su trabajo sin esperar a que los datos estén realmente en el disco. El mismo tipo de almacenamiento en búfer / almacenamiento en caché también se implementa para operaciones de lectura en las que los bloques de lectura recientes o frecuentes se retienen en la memoria en lugar de leerse nuevamente desde el disco.No necesariamente. Eso depende del sistema de archivos utilizado y la redundancia en el lugar. Un error de E / S puede ser inofensivo si los datos se pueden guardar en otro lugar. Los sistemas de archivos modernos como ZFS se auto curan de bloques de disco defectuosos. Tenga en cuenta también que los errores de E / S no bloquean los sistemas operativos modernos. Si ocurren durante el acceso a los datos, simplemente se informan a la aplicación afectada. Si ocurren durante el acceso a metadatos estructurales y ponen en riesgo el sistema de archivos, podría volverse a montar como de solo lectura o volverse inaccesible.
También existe un ligero riesgo de pérdida de datos en caso de un bloqueo del sistema operativo, un corte de energía o una falla de hardware. Esta es la razón por la cual las aplicaciones que deben estar 100% seguras de que los datos están en el disco (por ejemplo, bases de datos / aplicaciones financieras) están haciendo escrituras sincrónicas menos eficientes pero más seguras. Para mitigar el impacto en el rendimiento, muchas aplicaciones aún usan escrituras asíncronas, pero eventualmente las sincronizan cuando el usuario guarda explícitamente un archivo (por ejemplo, vim, procesadores de texto).
Por otro lado, una gran mayoría de usuarios y aplicaciones no necesitan ni les importa la seguridad que proporcionan las escrituras síncronas. Si hay un choque o un corte de energía, el único riesgo a menudo es perder en el peor de los últimos 30 segundos de datos. A menos que haya una transacción financiera involucrada o algo similar que implique un costo mucho mayor que 30 segundos de su tiempo, la enorme ganancia en el rendimiento (que no es una ilusión sino muy real), las escrituras asincrónicas están permitiendo superar en gran medida el riesgo.
Finalmente, las escrituras sincrónicas no son suficientes para proteger los datos escritos de todos modos. Si su aplicación realmente necesita asegurarse de que sus datos no puedan perderse, pase lo que pase, la replicación de datos en múltiples discos y en múltiples ubicaciones geográficas debe implementarse para resistir desastres como incendios, inundaciones, etc.
fuente
Simplemente da una ilusión de velocidad a los programas que en realidad no tienen que esperar hasta que se complete una escritura. Monte sus sistemas de archivos en modo de sincronización (que le proporciona sus escrituras instantáneas) y vea qué tan lento es todo.
A veces los archivos existen solo temporalmente ... un programa hace un poco de trabajo y elimina el archivo justo después de que el trabajo está hecho. Si retrasó esas escrituras, podría salirse con la suya sin haberlas escrito nunca.
Oh absolutamente En tal caso, generalmente todo el sistema de archivos entra en modo de solo lectura, y todo es horrible. Pero eso rara vez sucede, no tiene sentido perder las ventajas de rendimiento en general.
fuente
La E / S asincrónica y amortiguada estaba en uso antes de Linux e incluso antes de Unix. Unix lo tenía, y también todos sus retoños.
Esto es lo que Ritchie y Thompson escribieron en su artículo de CACM The UNIX Time-Sharing System :
En tu pregunta, también escribiste:
Sí, la escritura puede fallar y es posible que el programa nunca lo sepa. Aunque nunca es bueno, los efectos de esto se pueden minimizar en los casos en que un error de E / S genera un pánico del sistema (en algunos sistemas operativos esto es configurable; en lugar de entrar en pánico, el sistema puede continuar ejecutándose pero el sistema de archivos afectado es desmontado o montado de solo lectura). Los usuarios pueden ser notificados de que los datos en ese sistema de archivos son sospechosos. Y una unidad de disco se puede monitorear proactivamente para ver si su lista de defectos aumentada está aumentando rápidamente, lo cual es una indicación de que la unidad está fallando.
BSD agregó la
fsync
llamada al sistema para que un programa pudiera estar seguro de que sus datos de archivo se habían escrito completamente en el disco antes de continuar, y los sistemas Unix posteriores han proporcionado opciones para realizar escrituras sincrónicas. GNU dd tiene una opciónconv=fsync
para asegurarse de que todos los datos se hayan escrito antes de que salga el comando. Resulta útil al escribir en unidades flash extraíbles lentas, donde los datos almacenados en el búfer pueden tardar varios minutos en escribirse.Otra fuente de corrupción de archivos es un apagado repentino del sistema, por ejemplo, por pérdida de energía. Prácticamente todos los sistemas actuales admiten una marca limpia / sucia en sus sistemas de archivos. El indicador se establece para limpiar cuando no hay más datos para escribir y el sistema de archivos está a punto de desmontarse, generalmente durante el apagado del sistema o mediante una llamada manual
umount
. Los sistemas generalmente se ejecutaránfsck
al reiniciar si detectan que los sistemas de archivos no se cerraron limpiamente.fuente
Muchas buenas respuestas, pero permítanme agregar otra cosa ... Recuerde que Unix es un sistema multiproceso y multiusuario, por lo que potencialmente muchos usuarios estarían intentando realizar operaciones de archivo (especialmente escrituras) en (casi) el Mismo tiempo. Con los viejos discos duros lentos, tal vez montados en la red, esto no solo llevaría tiempo (para lo cual los programas básicamente se bloquearían y los usuarios tendrían que esperar), sino que causaría mucho movimiento del cabezal de lectura / escritura del disco de ida y vuelta.
Entonces, en cambio, los archivos que esperaban ser escritos se mantuvieron en la memoria por un tiempo, y se ordenaron según dónde deberían terminar en el disco ... y cuando el búfer estaba lleno, o el demonio de sincronización de disco había esperado el número requerido de segundos (creo que usualmente fueron unos 30 segundos): todo el búfer se escribió en el disco "en orden", con el cabezal de escritura solo teniendo que hacer un movimiento de barrido continuo, escribiendo los archivos en el disco como fue ... en lugar de saltar por todo el lugar.
Por supuesto, con los discos rápidos de hoy en día, sin mencionar los dispositivos de estado sólido, la ganancia es mucho menor ... especialmente en un sistema Linux doméstico, donde solo hay un usuario trabajando a la vez, y solo con unos pocos programas.
De todos modos, la combinación de anticipar las lecturas leyendo (en el caché / búfer) más de lo que se solicitó, y clasificando los datos en espera de ser escritos, para que pudieran escribirse en "un solo movimiento", en realidad fue una muy buena idea. tiempo, especialmente en sistemas con mucha lectura y escritura por parte de muchos usuarios.
fuente
No es específico de Linux, y se llama caché de página (que Linux hace bastante bien). Ver también http://linuxatemyram.com/ ; así que si se escribe un archivo, vuelva a leerlo unos segundos más tarde, a menudo no se necesita E / S de disco.
La principal ventaja es que en muchos sistemas, hay mucha RAM, y parte del núcleo puede ser utilizada como caché. Por lo tanto, algunas operaciones de archivos pueden aprovechar este almacenamiento en caché. Además, el tiempo de E / S de disco es mucho más lento (generalmente miles de veces para SDD y casi un millón de veces más lento para discos duros mecánicos) que la RAM.
El código de la aplicación puede dar pistas sobre este almacenamiento en caché: consulte, por ejemplo, posix_fadvise (2) y madvise (2)
fuente
Los platos giratorios son más lentos que la RAM. Usamos el almacenamiento en caché de lecturas / escrituras para 'ocultar' este hecho.
Lo útil de escribir IO es que no requiere que IO de disco ocurra de inmediato, a diferencia de una lectura, donde no puede devolver datos al usuario hasta que la lectura se complete en el disco.
Por lo tanto, las escrituras operan bajo una restricción de tiempo flexible: siempre que nuestro rendimiento sostenido no exceda el de nuestro disco, podemos ocultar muchas de las penalizaciones de rendimiento en un caché de escritura.
Y necesitamos escribir caché: los discos giratorios son muy lentos comparativamente. Pero para hacerlo, los tipos RAID modernos tienen una penalización significativa para la operación.
Un RAID 6, por ejemplo, para completar una escritura, IO debe:
Por lo tanto, cada escritura es en realidad 6 operaciones de E / S, y particularmente cuando tiene discos lentos como grandes unidades SATA, esto se vuelve extremadamente costoso.
Pero hay una buena solución fácil: escribir en combinación. Si puede construir una escritura de 'franja completa' en un búfer, no necesita leer la paridad de su disco; puede calcularla en función de lo que tiene en la memoria.
Es muy deseable hacer esto, porque entonces ya no tienes amplificación de escritura. De hecho, puede terminar con una penalización de escritura menor que RAID 1 + 0.
Considerar:
RAID 6, 8 + 2 - 10 husillos.
8 bloques de datos consecutivos para escribir: calcule la paridad en la memoria caché y escriba un bloque en cada disco. 10 escrituras por 8, significa una penalización de escritura de 1.25. 10 discos de RAID 1 + 0 todavía tienen una penalización de escritura de 2 (porque tiene que escribir en cada submirror). Entonces, en este escenario, puede hacer que RAID 6 funcione mejor que RAID1 + 0. Sin embargo, en el uso en el mundo real, obtienes un poco más de un perfil IO mixto.
Por lo tanto, el almacenamiento en caché de escritura hace una gran diferencia en el rendimiento percibido de los conjuntos RAID: puede escribir a velocidad de RAM y tener una baja penalización de escritura, lo que mejora su rendimiento sostenido si lo hace.
Y si no lo hace, sufre el rendimiento lento de SATA, pero multiplíquelo por 6 y agregue cierta contención allí. Su SATA RAID-6 de 10 vías sin almacenamiento en caché de escritura sería un poco más rápido que una sola unidad sin RAID ... pero no mucho.
Sin embargo, se arriesga, como observa, la pérdida de energía significa la pérdida de datos. Puede mitigar esto mediante ciclos de descarga de caché, batería que respalde su caché o utilizando SSD u otros cachés no volátiles.
fuente
Ninguna de las otras respuestas mencionó la asignación tardía . XFS, ext4, BTRFS y ZFS lo usan. XFS lo ha estado usando desde antes de que existiera ext4, así que lo usaré como ejemplo:
XFS ni siquiera decide dónde colocar los datos hasta la escritura. La asignación retrasada le da al asignador mucha más información para basar sus decisiones. Cuando se escribe un archivo por primera vez, no hay forma de saber si será un archivo 4k o un archivo 1G y aún en crecimiento. Si hay 10G de espacio libre contiguo en alguna parte, colocar el archivo 4k al comienzo no sirve de nada. Poner el archivo grande al comienzo de un gran espacio libre reduce la fragmentación.
fuente
Todas las otras respuestas aquí son mínimas, en su mayoría correctas para el caso normal, y recomendaría leer cualquiera de ellas antes que la mía, pero usted mencionó dd y dd tiene un caso de uso típico que puede no involucrar el almacenamiento en caché de escritura. El almacenamiento en caché de escritura se implementa principalmente en el nivel del sistema de archivos. Los dispositivos sin formato no suelen almacenar en caché de escritura (los controladores de dispositivos múltiples, como raid o lvm, son otra bola de cera). Dado que dd se usa a menudo con dispositivos de bloque sin formato, proporciona bs y opciones relacionadas para permitir grandes escrituras para un mejor rendimiento en dispositivos sin formato. Esto no es tan útil cuando ambos puntos finales son archivos normales (aunque las escrituras grandes utilizan menos llamadas al sistema en este caso). El otro lugar común donde esto es particularmente visible es con el paquete mtools, que es una implementación del sistema de archivos fat del espacio de usuario. El uso de mtools con una unidad de disquete siempre se siente increíblemente lento, ya que las herramientas son completamente sincrónicas y las unidades de disquete son increíblemente lentas. Montar el disquete y usar el sistema de archivos de kernel fat es mucho más receptivo, excepto para umount, que es sincrónico (y muy importante para que sea así para evitar la pérdida de datos, especialmente para dispositivos extraíbles como disquetes). Solo hay algunos otros programas que conozco que se usan regularmente con dispositivos sin procesar como bases de datos especialmente configuradas (que implementan su propio almacenamiento en caché de escritura), tar y dispositivos especiales y herramientas de sistema de archivos como chdsk, mkfs y mt. Montar el disquete y usar el sistema de archivos de kernel fat es mucho más receptivo, excepto para umount, que es sincrónico (y muy importante para que sea así para evitar la pérdida de datos, especialmente para dispositivos extraíbles como disquetes). Solo hay algunos otros programas que conozco que se usan regularmente con dispositivos sin procesar como bases de datos especialmente configuradas (que implementan su propio almacenamiento en caché de escritura), tar y dispositivos especiales y herramientas de sistema de archivos como chdsk, mkfs y mt. Montar el disquete y usar el sistema de archivos de kernel fat es mucho más receptivo, excepto para umount, que es sincrónico (y muy importante para que sea así para evitar la pérdida de datos, especialmente para dispositivos extraíbles como disquetes). Solo hay algunos otros programas que conozco que se usan regularmente con dispositivos sin procesar como bases de datos especialmente configuradas (que implementan su propio almacenamiento en caché de escritura), tar y dispositivos especiales y herramientas de sistema de archivos como chdsk, mkfs y mt.
fuente
O_DIRECT
si desea omitir el caché.dd oflag=direct
. IIRC, algunos dispositivos predeterminan la E / S directa en dispositivos de bloque. (Y requiere lectura / escritura de bloques alineados, lo que Linux no hace porque de todos modos solo está escribiendo el caché de página).La filosofía es insegura por defecto.
Hay dos estrategias razonables y obvias posibles: vaciar las escrituras al disco inmediatamente o retrasar la escritura. UNIX eligió históricamente el último. Por lo tanto, obtenga seguridad, debe llamar
fsync
después.Sin embargo, puede especificar la seguridad por adelantado montando un dispositivo con opción
sync
, o por archivo abriéndolo conO_SYNC
.Recuerde que UNIX fue diseñado para expertos en informática. "Seguro por defecto" no fue una consideración. Seguridad significa E / S más lenta, y esos primeros sistemas realmente tenían E / S lenta, lo que hacía que la tasa de precios fuera muy alta. Desafortunadamente, ni UNIX ni Linux cambiaron a safe-be-default, a pesar de que este es un cambio sin interrupciones.
fuente
Cambia una pequeña cantidad de confiabilidad por un gran aumento en el rendimiento.
Supongamos, por ejemplo, un programa de compresión de video. Con escritura retrasada ("escribir de nuevo"):
Versus
La segunda versión aparece el doble de rápido porque puede usar la CPU y el disco al mismo tiempo, mientras que la primera versión siempre está esperando uno u otro.
En general, desea una reescritura para las operaciones de transmisión y operaciones de archivos masivos, y la reescritura para bases de datos y aplicaciones similares.
fuente
En muchas aplicaciones, los dispositivos de almacenamiento estarán ocupados intermitentemente leyendo datos. Si un sistema siempre puede diferir las escrituras hasta el momento en que el dispositivo de almacenamiento no está ocupado leyendo datos, desde el punto de vista de una aplicación, las escrituras tardarán cero tiempo en completarse. Las únicas situaciones en las que las escrituras no serían instantáneas serían cuando:
Los buffers de escritura se llenan hasta el punto de que no se pueden aceptar más solicitudes de escritura diferida hasta que las escrituras se completen realmente.
Es necesario apagar o eliminar el dispositivo para el cual hay escrituras pendientes.
Una aplicación solicita específicamente la confirmación de que una escritura se ha completado realmente.
De hecho, es solo debido a los requisitos anteriores que las escrituras siempre deben tener lugar. Por otro lado, generalmente no hay razón para no realizar ninguna escritura pendiente en momentos en que un dispositivo estaría inactivo, por lo que muchos sistemas las realizan en ese momento.
fuente
También hay esto:
Escribir "Hola, Joe Moe"
es más rápido que:
Escribir "Hola",
Escribir "Joe"
Escribir "Moe"
Y también:
Escribe "Hola, ¿cómo estás?"
es más rápido que:
Escribe "Hola, ¿qué pasa?"
Elimina eso
Escribe "Hola, ¿cómo estás?"
Elimina eso
Escribe "Hola, ¿cómo estás?"
Es mejor que ocurran modificaciones y agregaciones en la RAM que en el disco. La escritura en disco por lotes libera a los desarrolladores de aplicaciones de tales preocupaciones.
fuente