2010-07-28 27 views
26

¿Qué sucede si recompilo un ejecutable mientras se está ejecutando? ¿El sistema operativo lee todos los contenidos del ejecutable en la memoria cuando comienza a ejecutarlo, por lo que nunca leerá el nuevo archivo ejecutable? ¿O leerá secciones del nuevo archivo ejecutable pensando que no ha cambiado, dando lugar a un comportamiento posiblemente indefinido?¿Es seguro recompilar un ejecutable mientras se está ejecutando?

¿Qué pasa si tengo un script en ejecución que invoca repetidamente un ejecutable en un bucle, y recompilo el ejecutable mientras se ejecuta el script. ¿Está garantizado que las iteraciones futuras del bucle invocarán el nuevo ejecutable, y que solo el resultado de la invocación que estaba en progreso cuando se realizó el cambio podría estar dañado?

Mi sistema operativo es Linux, pero también tengo curiosidad sobre lo que sucede en Windows.

+1

¿Qué idioma e implementación? Para la mayoría de los compiladores Common Lisp, no hay problema con cambiar el ejecutable sobre la marcha. Otros sistemas funcionan de manera diferente. –

+0

Este es un ejecutable de C++. No estoy seguro de cómo eso hace una diferencia en el sistema operativo, aunque ... – HighCommander4

+1

Marca la diferencia en esa compilación y ejecución son pasos completamente diferentes, por lo que se trata de cómo el sistema operativo maneja los archivos ejecutables. –

Respuesta

28

Dado que este es un compilador convencional, que escribe un archivo ejecutable, sigámoslo en Linux.

Lo primero que debe saber es que un nombre de archivo Linux no se refiere directamente al archivo, sino a una entrada de directorio, que es independiente del nombre del archivo. Un archivo realmente no necesita tener un nombre de archivo, pero si no es así, será difícil referirse a él.

Si un proceso está utilizando un archivo y lo reemplaza o elimina, el proceso continuará usando ese archivo a través de su entrada de directorio. Cualquier nuevo proceso que use el archivo, o lo busque, obtendrá la nueva versión (si la reemplazó) o no la encontrará (si la eliminó). Una vez que todos los procesos hayan finalizado con el archivo anterior, se eliminará del sistema de archivos.

Por lo tanto, si vuelve a compilar y crea un nuevo ejecutable del mismo nombre, no afectará el proceso de ejecución. Continuará usando el viejo ejecutable. Cualquier nuevo proceso que intente abrir el archivo obtendrá el nuevo. Si tiene system("foo"); en un bucle, cada vez que lo ejecute verá el nombre del archivo foo en ese momento.

Windows maneja los archivos de manera diferente. En general, si hay un proceso que utiliza un archivo, el archivo está bloqueado y no puede ser eliminado o reemplazado.

+0

Interesante: eso me da una buena idea de cómo maneja Linux los archivos. – HighCommander4

+1

[Linux] Depende de cómo se "reemplaza" un archivo para saber si funcionará o no. No puede abrir un ejecutable en uso para escribir. – camh

+0

¿Qué sucede si, a mitad de la salida del archivo .exe del enlazador, intento ejecutarlo? ¿Intentará iniciar un ejecutable medio escrito? – Thanatos

7

Depende.

Si el sistema operativo lee todo el ejecutable en la memoria y no hace referencia a la imagen del disco, entonces sí puede recompilarlo mientras estaba "en uso".

En la práctica, esto no siempre sucede. Si el sistema operativo mantiene abierto un identificador de archivo (como Windows) en el archivo ejecutable, esto evitará que el archivo se elimine y/o sobrescriba.

Con Linux/Unix, es posible sobrescribir un archivo que está "en uso". Vea la respuesta de David Thornley para una explicación detallada.

0

Me imagino que no le permitirá reemplazar el archivo, ya que Windows lo bloqueó mientras estaba en uso.

0

Depende. Por lo que he experimentado, en Linux todavía puede ejecutar un programa si lo elimina (y no es demasiado grande). Pero no creo que eso sea un comportamiento definido.

En lo que respecta al bucle, dependiendo de cómo invoque el ejecutable, es probable que termine bloqueando el script cuando vaya a ejecutar un programa que está medio escrito.

0

En Windows no puede si el ejecutable aún se está ejecutando, el archivo se bloqueará. Si el archivo ejecutable no se está ejecutando en realidad, las nuevas ejecuciones deberían elegir la nueva, dependiendo de cómo se codifica su secuencia de comandos, entre otras cosas.

No sé sobre Linux.

-1

El Ejecutable puede cargarse completamente en la memoria en el inicio, sin embargo, si es lo suficientemente grande y funciona lo suficiente, el sistema operativo puede decidir cambiar algunas partes no utilizadas de la misma.

Como el sistema operativo asume que el archivo del programa todavía está allí, no hay ninguna razón para escribir realmente estos bloques de memoria en el archivo de intercambio. Entonces simplemente son invalidados y reutilizados. Si el programa necesita estas páginas nuevamente, el sistema operativo las carga desde el archivo ejecutable.

En Windows, esto sucede de manera automática, ya que un módulo cargado es un archivo mapeado en la memoria. Eso también significa que el archivo está bloqueado durante su ejecución, y no podrá sobrescribirlo fácilmente.

No estoy seguro acerca de Linux, pero IIRC hace el intercambio de la misma manera.

5

En Windows no puede eliminar un archivo bloqueado, pero lo que la mayoría de la gente no sabe es que puede mover o cambiar el nombre de un ejecutable.

por lo que podría

  • movimiento del viejo exe en un directorio temporal en la misma unidad
  • cronograma para su eliminación en el siguiente reinicio: MoveFileEx (nombre, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
  • mueve un nuevo exe en su lugar.

El programa antiguo seguirá en ejecución pero los nuevos procesos utilizarán el nuevo archivo.

+3

Información interesante que se puede usar para demostrar cómo las malas elecciones de diseño pueden llevar a soluciones temporales extrañas. Al dividir la información sobre el archivo en, el nombre de archivo y el inodo no hay necesidad de tales comandos complejos. Además, no hay necesidad de reiniciar. La actualización puede suceder sobre la marcha. – Saurabh

4

En Linux, los ejecutables se buscan en la memoria según sea necesario. El ejecutable en el disco se convierte en el almacén de respaldo para la aplicación. Esto significa que no puede modificar el ejecutable en el disco o afectará a una aplicación en ejecución. Si intenta open(2) un ejecutable en uso para escribir, obtendrá un error ETXTBSY (Archivo de texto ocupado) (consulte la página de manual para open(2)).

Como muchos otros han dicho, puede eliminar el archivo del sistema de archivos (unlink(2)) y el núcleo mantendrá una referencia y no lo eliminará del disco hasta que no haya más referencias (cuando el proceso finalice, lo hará liberar su referencia al archivo). Esto significa que puede "sobrescribir" efectivamente un ejecutable en uso quitándolo primero y luego creando un nuevo archivo con el mismo nombre que el archivo anterior.

Por lo tanto, se trata de cómo el compilador crea el ejecutable al "sobrescribir" un archivo existente. Si solo abre el archivo para escritura y lo trunca (O_WRONLY|O_CREAT|O_TRUNC), se producirá un error de ETXTBSY. Si primero elimina el archivo de salida existente y crea uno nuevo, funcionará sin error.

Cuestiones relacionadas