2012-05-09 21 views
5

Me gustaría tener un pequeño programa de "cargador de aplicaciones" que reciba otros archivos de aplicaciones binarias a través de TCP desde un servidor externo y los ejecute.¿Ejecuta un proceso desde la memoria dentro de otro proceso?

Podría hacerlo guardando el archivo transmitido en el disco duro y utilizando la llamada al sistema() para ejecutarlo. Sin embargo, me pregunto si sería posible lanzar la nueva aplicación desde la memoria sin tocar el disco duro.

El estado de la aplicación del cargador no es importante después de cargar una nueva aplicación. Prefiero quedarme con C, pero las soluciones de C++ también son bienvenidas. También me gustaría apegarme a las funciones estándar de Linux C y no usar ninguna biblioteca externa, si es posible.

+0

Sí, es posible pero es algo complicado. Tienes que emular el sistema operativo y asignar el binario a la memoria, etc. –

+2

Podrías escribirlo en un archivo en un ramdisk – TJD

+1

También tiendo a pensar que * cualquier * nivel de seguridad del sistema operativo en una CPU moderadamente reciente va a hacer su Lo mejor es asegurarse de que esto no pueda suceder. Ciertamente es factible, pero sería un verdadero dolor utilizarlo en las distribuciones del mundo real (espero) – BRFennPocock

Respuesta

3

Respuesta corta: no.

Respuesta larga: Es posible pero bastante complicado hacer esto sin escribirlo en el disco. En teoría, puedes escribir tu propio cargador de elfos que lea el binario, mapee un poco de memoria, maneje los enlaces dinámicos según sea necesario, y luego transfiera el control, pero eso es una gran cantidad de trabajo, que casi nunca valdrá la pena el esfuerzo.

La siguiente mejor solución es escribirlo en el disco y desvincularlo lo antes posible. El disco ni siquiera tiene que ser un disco "real", puede ser tmpfs o similar.

La alternativa que he estado utilizando recientemente es no pasar completos binarios compilados, sino pasar el bytecode LLVM, que luego se puede JIT/interpretar/guardar como apto. Esto también tiene la ventaja de hacer que su aplicación funcione en entornos heterogéneos.

Puede ser tentador tratar una combinación de fmemopen, fileno y fexecve, pero esto no va a funcionar por dos razones:

  1. De fexecve() página de manual:

    "El archivo descriptor fd debe abrirse como de solo lectura, y la persona que llama debe tener permiso para ejecutar el archivo al que hace referencia "

    I.e. necesita ser un fd que se refiera a un archivo.

  2. De fmemopen() página de manual:

    "No hay descriptor de fichero asociado con la secuencia de archivo devuelto por estas funciones (es decir, fileno(3) devolverá un error si se llama a la secuencia devuelta)"

+0

Gracias por la respuesta; Esto es exactamente lo que estaba buscando. ¡Buscar en Google el tema no me llevó muy lejos y necesitaba satisfacer mi curiosidad! – Flip

+0

Tenga en cuenta que actualmente es un estándar tener un 'tmpfs' montado en'/dev/shm/'. – caf

0

Mucho más fácil que hacerlo es C solo para configurar un sistema de archivos tmpfs. Tendría todas las ventajas de la interfaz de un disco duro, desde su programa/servidor/lo que sea que pueda hacer es un exec. Estos tipos de sistemas de archivos virtuales son bastante eficientes hoy en día, en realidad solo habría una copia del ejecutable en la memoria caché de la página.

Como Andy señala, para que este esquema sea eficiente, debe asegurarse de no utilizar escrituras almacenadas en el archivo, sino que debe "escribir" (en un sentido más amplio) directamente en su lugar.

  • que tendría que saber cómo grande es su ejecutable será
  • crear un archivo en su tmpfs
  • escala a ese tamaño con ftruncate
  • "mapa" de ese archivo en la memoria con mmap a obtener el dir de un tampón
  • pase que aborda directamente a la llamada recv para escribir los datos en el lugar
  • munmap el archivo
  • llamada exec con el archivo
  • rm el archivo. se puede hacer incluso cuando el ejecutable se sigue ejecutando
+0

Honestamente, tmpfs no será más rápido que un sistema de archivos nativo a menos que su almacenamiento ya esté en capacidad. Las escrituras se almacenan en búfer en la memoria de forma tal que un execve inmediato() simplemente las correlacionará fuera de caché. El único costo que paga es el eventual lavado al disco, que es asincrónico. –

+0

@AndyRoss, no use escrituras con buffer para tal cosa, actualizaré mi respuesta. –

+1

Incluso eso solo evita una copia de memoria. ¿Cuál es la restricción de rendimiento aquí? Tengo problemas para imaginar una situación en la que la velocidad de las escrituras a través del sistema de archivos sea un límite, pero la velocidad de recepción de paquetes a través de una red no lo es. Parece enormemente complicado. Simplemente abre/escribe en tu sistema de archivos habitual y guarda el problema. –

0

Es posible que desee ver y reutilizar UPX, que descomprime el ejecutable en la memoria, y luego transfiere el control a ld-linux para iniciarlo.

Cuestiones relacionadas