windows - rendimiento - ¿Es seguro recompilar un ejecutable mientras se está ejecutando?
no se puede ejecutar esta aplicacion en el equipo windows 8.1 pro (8)
¿Qué sucede si recompilo un ejecutable mientras se está ejecutando? ¿El sistema operativo lee todo el contenido del ejecutable en la memoria cuando comienza a ejecutarlo, por lo que nunca leerá el nuevo archivo ejecutable? ¿O leerá las secciones del nuevo archivo ejecutable pensando que no ha cambiado, conduciendo a un comportamiento posiblemente indefinido?
¿Qué pasa si tengo un script en ejecución que invoca repetidamente un ejecutable en un bucle, y recompilo el ejecutable mientras el script está en ejecución? ¿Está garantizado que las futuras iteraciones del bucle invocarán el nuevo ejecutable, y solo el resultado de la invocación que estaba en curso cuando se realizó el cambio podría estar dañado?
Mi sistema operativo es Linux, pero también tengo curiosidad por lo que sucede en Windows.
Bajo Linux, los ejecutables se solicitan 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 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 kernel mantendrá una referencia a él y no lo eliminará del disco hasta que no haya más referencias (cuando el proceso finalice, se liberará). su referencia al archivo). Esto significa que puede "sobrescribir" un ejecutable en uso eliminándolo primero y luego creando un nuevo archivo con el mismo nombre que el archivo anterior.
Entonces, todo se reduce a cómo el compilador crea el archivo ejecutable cuando "sobrescribe" un archivo existente. Si solo abre el archivo para escribirlo y lo trunca ( O_WRONLY|O_CREAT|O_TRUNC
), fallará con un error ETXTBSY
. Si primero elimina el archivo de salida existente y crea uno nuevo, funcionará sin error.
Depende. Por lo que he experimentado, en Linux todavía puede estar ejecutando 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 de bloquear su secuencia de comandos cuando se ejecute un programa que solo se ha escrito a medias.
Depende.
Si el sistema operativo lee todo el ejecutable en la memoria y no se refiere 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 un identificador de archivo abierto (como lo hace Windows) en el ejecutable, esto evitará que el archivo se elimine o se sobrescriba.
Con Linux / Unix es posible sobrescribir un archivo que está "en uso". Vea la respuesta de David Thornley para una explicación detallada.
El ejecutable puede cargarse completamente en la memoria en el inicio, sin embargo, si es lo suficientemente grande y se ejecuta durante el tiempo suficiente, el sistema operativo puede decidir intercambiar algunas partes no utilizadas.
Como el sistema operativo asume que el archivo del programa aún está allí, no hay razón para escribir estos bloques de memoria en el archivo de intercambio. Así que 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 forma automática, ya que un módulo cargado es un archivo asignado en 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.
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 archivo ejecutable.
Para que pudieras
- Mueve el exe antiguo a un directorio temporal en la misma unidad
- programarlo 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á ejecutándose, pero los nuevos procesos utilizarán el nuevo archivo.
En Windows no puede si el ejecutable todavía se está ejecutando, el archivo se bloqueará. Si el exe no se está ejecutando realmente, las nuevas ejecuciones deberían recoger la nueva, dependiendo de cómo esté codificado su script entre otras cosas.
No sé sobre Linux.
Me imagino que no le permitiría reemplazar el archivo, ya que Windows lo bloqueó mientras estaba en uso.
Ya que este es un compilador convencional, que escribe un archivo ejecutable, vamos a seguirlo en Linux.
Lo primero que debe saber es que un nombre de archivo de Linux no se refiere directamente al archivo, sino a una entrada de directorio, que es independiente del nombre de archivo. Un archivo no necesita realmente tener un nombre de archivo, pero si no lo hace, será difícil referirse a él.
Si un proceso utiliza un archivo y lo reemplaza o elimina, el proceso continuará utilizando ese archivo a través de su entrada de directorio. Cualquier proceso nuevo que use el archivo, o que lo busque, obtendrá la nueva versión (si la reemplazó) o no la encontrará (si la eliminó). Una vez que todos los procesos hayan terminado con el archivo anterior, se eliminará del sistema de archivos.
Por lo tanto, si recompila y crea un nuevo ejecutable con el mismo nombre, no afectará el proceso en ejecución. Continuará utilizando el antiguo ejecutable. Cualquier nuevo proceso que intente abrir el archivo obtendrá el nuevo. Si tienes system("foo");
en un bucle, cada vez que lo ejecute verá lo que significa el nombre de archivo foo en ese momento.
Windows maneja los archivos de manera diferente. En general, si hay un proceso que usa un archivo, el archivo está bloqueado y no se puede eliminar ni reemplazar.