¿Por qué un paquete de software funciona bien incluso cuando se está actualizando?
29
Digamos que estoy ejecutando un software, y luego ejecuto el administrador de paquetes para actualizar el software, me doy cuenta de que Linux no reduce el proceso de ejecución para la actualización del paquete, todavía funciona bien. ¿Cómo hace esto Linux?
La razón es que Unix no bloquea un archivo ejecutable mientras se ejecuta o incluso si le gusta Linux, este bloqueo se aplica al inodo, no al nombre del archivo. Eso significa que un proceso que lo mantiene abierto está accediendo a los mismos datos (antiguos) incluso después de que el archivo se haya eliminado (desvinculado en realidad) y reemplazado por uno nuevo con el mismo nombre, que es esencialmente lo que hace una actualización del paquete.
Esa es una de las principales diferencias entre Unix y Windows. Este último no puede actualizar un archivo bloqueado ya que le falta una capa entre los nombres de archivo y los inodos, lo que dificulta la actualización o incluso la instalación de algunos paquetes, ya que generalmente requiere un reinicio completo.
Para aclarar, bajo Linux no puede modificar un archivo ejecutable mientras se está ejecutando. Pero puede desvincular el archivo y reemplazarlo con un nuevo archivo con el mismo nombre.
cjm
En Linux, puede modificar un archivo ejecutable mientras se está ejecutando. Sin embargo, el resultado probablemente sería impredecible a menos que realmente sepas lo que estás haciendo. Se agregó el punto "mismo nombre" que no se indicó explícitamente.
jlliagre
44
@jlliagre A menos que sea un malentendido, no puedes hasta donde yo sé: sprunge.us/egiR
Chris Down
2
Sin embargo, una cosa interesante sobre NFTS: si realiza un cambio de nombre desde la línea de comando u otro programa, puede colocar un archivo con el mismo nombre allí, y no afectará a los programas que tengan abierto el archivo original. (el comando de cambio de nombre en el explorador no funciona para esto)
Steffan Donal
1
@cjm Tiene razón acerca de la protección de "archivo de texto ocupado" en Linux, respuesta actualizada. No existe tal restricción en Solaris con la que estoy más familiarizado. Sin embargo, aún puede modificar las bibliotecas compartidas con ambos sistemas operativos.
jlliagre
18
Los ejecutables generalmente se abren una vez, se adjuntan a un descriptor de archivo y no tienen un descriptor de archivo a su binario reabierto durante un solo período de ejecución. Por ejemplo, si ejecuta bash, exec()generalmente solo crea un descriptor de archivo para el inodo al que apunta /bin/bashuna vez, en la invocación.
Esto a menudo significa que para los archivos binarios simples que no intentan releerse durante la ejecución (mediante el uso de la ruta por la que se invocaron), el contenido almacenado en caché permanece válido como un inodo colgante. Esto significa que esencialmente hay una réplica de la versión anterior del ejecutable.
En casos más complejos, esto puede causar problemas. Por ejemplo, un archivo de configuración puede actualizarse y luego volverse a leer, o el programa puede volver a ejecutarse a sí mismo a través de la ruta desde la que se ejecutó. También puede haber problemas si los programas están interconectados, y uno se ejecuta antes de la actualización y otro después (posiblemente por el primer programa). Esto también es cierto para algunas bibliotecas.
Sin embargo, para casos de uso simples, es seguro actualizar sin reiniciar el proceso.
El otro peligro, incluso en casos simples, es que debido a que la aplicación en ejecución está usando una copia en caché del binario, hasta que reinicie manualmente la aplicación, aún está ejecutando la versión anterior del código. Si bien esto no debería importar la mayor parte del tiempo; si la actualización incluyó correcciones de seguridad, a pesar de la instalación del parche, su sistema sigue siendo vulnerable porque la versión anterior todavía se está ejecutando.
Dan Neely
1
Me temo que su primer párrafo es inexacto. Los núcleos Unix / Linux no cargan programas ejecutables a la vez, sino que los mapean en memoria. Eso significa que solo las páginas realmente utilizadas finalmente llegan a la RAM. Este es el objetivo de la protección "Archivo de texto ocupado" en Linux. No hay garantía de que alguna parte de un ejecutable no se leerá mucho después de que se haya lanzado. Además, algunas páginas nunca se cargarán para programas lo suficientemente grandes y esto es aún más cierto para las bibliotecas cargadas dinámicamente. Por ejemplo, el bashbinario tiene alrededor de 200 páginas 4K, no estoy seguro de que todas se usen en una sesión promedio.
jlliagre
@jlliagre Estaba hablando ialloc()de una estructura del núcleo en lectura, no del mapeo de memoria de las páginas en sí. ¿No estoy en lo cierto al pensar que en los modernos sistemas de archivos ext *, el inodo eventualmente es consistente en el núcleo (y dentro del subsistema VM)?
Chris Down
No hay garantía de que partes del contenido ejecutable no se leerán mucho tiempo después de que se ejecute, y tampoco hay garantía de que las mismas páginas no se volverán a leer después de un tiempo durante el tiempo de ejecución.
jlliagre
@jlliagre Correcto, pero eso no es lo que quise decir. Tal vez puse mis palabras un poco en mi respuesta, intentaré aclarar lo que quise decir.
Los ejecutables generalmente se abren una vez, se adjuntan a un descriptor de archivo y no tienen un descriptor de archivo a su binario reabierto durante un solo período de ejecución. Por ejemplo, si ejecuta
bash
,exec()
generalmente solo crea un descriptor de archivo para el inodo al que apunta/bin/bash
una vez, en la invocación.Esto a menudo significa que para los archivos binarios simples que no intentan releerse durante la ejecución (mediante el uso de la ruta por la que se invocaron), el contenido almacenado en caché permanece válido como un inodo colgante. Esto significa que esencialmente hay una réplica de la versión anterior del ejecutable.
En casos más complejos, esto puede causar problemas. Por ejemplo, un archivo de configuración puede actualizarse y luego volverse a leer, o el programa puede volver a ejecutarse a sí mismo a través de la ruta desde la que se ejecutó. También puede haber problemas si los programas están interconectados, y uno se ejecuta antes de la actualización y otro después (posiblemente por el primer programa). Esto también es cierto para algunas bibliotecas.
Sin embargo, para casos de uso simples, es seguro actualizar sin reiniciar el proceso.
fuente
bash
binario tiene alrededor de 200 páginas 4K, no estoy seguro de que todas se usen en una sesión promedio.ialloc()
de una estructura del núcleo en lectura, no del mapeo de memoria de las páginas en sí. ¿No estoy en lo cierto al pensar que en los modernos sistemas de archivos ext *, el inodo eventualmente es consistente en el núcleo (y dentro del subsistema VM)?