2010-11-22 8 views
51

Si funciono con la clásica forkbomb bash:¿Por qué las bombas C-forkbombs no funcionan como las de bash?

:(){ :&:&};: 

mi sistema se bloquea después de unos segundos.

Traté de escribir una bomba fork en C, aquí está el código:

#include <unistd.h> 

int main() 
{ 
    while(1) { 
     fork(); 
    } 
    return 0; 
} 

Cuando lo ejecuto el sistema se vuelve menos sensible, pero puede matar a ese proceso (incluso después de minutos) sólo pulsar ^C.


El código anterior es diferente de la fiesta de forkbomb originales que he publicado: se trata de algo más como:

:() 
{ 
    while true 
    do 
     : 
    done 
} 

(no he probado que, no sé si había hang el sistema).

Así que también intenté implementar la versión original; aquí el código:

#include <unistd.h> 

inline void colon(const char *path) 
{ 
    pid_t pid = fork(); 
    if(pid == 0) { 
     execl(path, path, 0); 
    } 
} 

int main(int argc, char **argv) 
{ 
    colon(argv[0]); 
    colon(argv[0]); 
    return 0; 
} 

Pero todavía nada: puedo ejecutarlo y luego matarlo fácilmente. No es colgando mi sistema.


¿Por qué?

¿Qué tiene de especial las bombas de tenedor bash? ¿Es porque bash usa mucha más memoria/CPU? ¿Porque los procesos de bash llaman a muchas más llamadas al sistema (por ejemplo, para acceder al sistema de archivos) que a las mías?

+0

Como dice el refrán, los avances científicos rara vez van acompañados de "Eureka!", Comúnmente acompañados por "Hmm, eso es extraño". –

Respuesta

44

Ese programa C es tiny, tiny tiny. Además, tenedor() 'un programa como ese es muy, muy eficiente. Sin embargo, un intérprete, como Bash, es mucho más costoso en términos de uso de RAM y necesita acceder al disco todo el tiempo.

Prueba a ejecutarlo por mucho más tiempo. :)

+26

Además, los Unixes modernos tienden a usar copia sobre escritura para la memoria virtual. A menos que cada proceso realmente escriba en una ubicación de memoria, todos usarán las mismas páginas físicas, incluso después del 'exec'. Ponga algunos mallocs al azar y escriba en la memoria mallada. Creo que eso matará a la máquina. – JeremyP

+0

Sí, ya he citado estas cosas, pero ¿cuáles de ellas son las que cuelgan el sistema y por qué? Si para cualquier proceso que genero, asigno 1MB de memoria en el montón/pila, ¿colgará mi sistema? O si algún proceso hace 1 segundo de cálculo intensivo? O si algún proceso llama a algunas llamadas al sistema? – peoro

+3

@ peoro: Técnicamente no lo hiciste. Mi punto no era que cada nuevo proceso utiliza poca memoria, pero que en realidad no utiliza memoria extra (aparte de las estructuras del kernel). Cuando haces un fork, el proceso secundario usa exactamente las mismas páginas físicas que el padre hasta que escribe algo en la memoria. Incluso con el ejecutor, la imagen ejecutable se comparte. Se creará una nueva página de pila, pero el gran asesino de rendimiento se intercambia y esto no sucederá a menos que haga algunas escrituras. – JeremyP

3

En tu forkbomb bash, estás poniendo nuevos procesos en nuevos grupos de procesos en segundo plano, por lo que no podrás ^C ellos.

0

Eso es básicamente debido a su tamaño. Cuando está ejecutando la bomba de fork bash, carga grandes programas de monstruos en la memoria (con respecto a su programa c) cada uno de ellos empieza a acaparar sus recursos de CPU. Definitivamente cuando los monstruos grandes comienzan a reproducir problemas viene más rápido que si las abejas comienzan a hacer mismo. Entonces la computadora se cuelga inmediatamente. Sin embargo, si mantiene su ejecutable c funcionando por mucho tiempo, también se cuelga el sistema. Solo que el tiempo será mucho más. Si desea comparar el tamaño de bash con el tamaño del programa c, consulte/proc // status. primero con pid de cualquier instancia en ejecución de fiesta, y luego con el pid de cualquier instancia en ejecución de un programa en C

3

El verdadera causa de esto es que en el proceso de BASH se crea se separa de la matriz. Si el proceso principal (el que inicialmente comenzó) se cancela, el resto de los procesos continuará.Pero en las implementaciones de C que enumeró, los procesos secundarios mueren si el elemento principal se elimina, por lo que es suficiente para reducir el proceso inicial que comenzó a reducir el árbol completo de procesos siempre bifurcados.

Todavía no he encontrado una implementación C forkbomb que separe los procesos secundarios para que no se eliminen si el padre muere. Los enlaces a tales implementaciones serían apreciados.

Cuestiones relacionadas