C
Unter Verwendung der Programmiersprache C und getestet mit Linux-Kernel 2.6.32-49-generic und libc-2.11.1.so.
Sie können den Speicher nur freigeben, indem Sie das Programm im Task-Manager beenden oder taskkill / im yourprogram / f verwenden oder den PC neu starten.
Dies wird erreicht, indem alle Signale außer SIGKILL und SIGSTOP blockiert werden.
Wenn Sie es schließen, sollte es immer noch schwer zu merken sein.
Das hat mich wirklich verwirrt ... Das Beenden oder Schließen beider Prozesse führt zum Abbruch des Prozesses und ermöglicht dem Betriebssystem, den vom Prozess zugewiesenen Speicher zurückzugewinnen. Aber dann musste ich denken, dass Sie mit dem Schließen des Terminals oder eines anderen übergeordneten Prozesses, der den Speicherverlust ausführt, möglicherweise das Terminal schließen möchten. Wenn ich das richtig verstanden habe, habe ich dieses Problem gelöst, indem ich alle Signale blockiert habe, die den Prozess in einen Daemon verwandeln, wenn der übergeordnete Prozess beendet wird. Auf diese Weise können Sie das Terminal schließen, in dem der Prozess ausgeführt wird, und es wird weiter ausgeführt, und es tritt ein Speicherverlust auf.
Gabelbomben jeglicher Art sind verboten. Das bedeutet, dass die berüchtigte Bash: () {: |: &} ;: verboten ist!
Der Prozess gibt nicht auf.
Die Anwendung darf nur mit einem Thread ausgeführt werden. Dies impliziert die Regel der Gabelbomben
Es werden keine neuen Threads erzeugt.
Das Programm darf kein anderes Programm ausführen. Das bedeutet, dass Sie nicht einfach so etwas wie "Ausführen" (memoryfiller.exe) ausführen können.
Es werden keine neuen Prozesse erzeugt.
Sie können so viel Speicher belegen, wie Sie möchten. Je mehr desto besser.
So viel das Betriebssystem bieten kann.
Code muss vollständig erklärt werden.
Der Quelle wurden Kommentare hinzugefügt.
Und zum Schluss hier der Code:
#define _GNU_SOURCE
#include <stdio.h>
#include <signal.h>
#include <sys/resource.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char* argv[]) {
/*
set the real, effective and set user id to root,
so that the process can adjust possible limits.
if the process doesn't have the CAP_SETUID capability, terminate the process.
*/
if (setresuid(0, 0, 0) == -1) {
printf("Are you root?!\n");
return 1;
}
/*
block all signals except for kill and stop.
this allows to terminate the parent process (most likely a terminal)
that this process is running in and turn it into a daemon.
additionally this makes it impossible to terminate the process
in a normal way and therefore satisfies the requirement that closing
it should still make it hog memory.
*/
sigset_t mask;
sigfillset(&mask);
sigprocmask(SIG_SETMASK, &mask, NULL);
/*
allow the process to acquire a virtually unlimited amount of memory
and queue a virtually unlimited amount of signals.
this is to prevent an out of memory error due to a virtual limit for the root user,
which would prevent the process from leaking any more memory
and to prevent the process from getting killed due to too many queued
signals that the process is blocking.
*/
struct rlimit memory = { RLIM_INFINITY, RLIM_INFINITY },
signal = { RLIM_INFINITY, RLIM_INFINITY};
setrlimit(RLIMIT_AS, &memory);
setrlimit(RLIMIT_SIGPENDING, &signal);
/*
allocate a buffer big enough to store a file name into it
that is generated from the process' pid.
if the file can be opened (which should always be the case unless /proc is not mounted)
the file will be opened and the string -17 followed by a new line written to it.
this will cause the oom killer to ignore our process and only kill other,
innocent processes when running out of memory.
*/
char file_name[20];
sprintf(file_name, "/proc/%u/oom_adj", getpid());
FILE* oom_killer_file = fopen(file_name, "w");
if (oom_killer_file) {
fprintf(oom_killer_file, "-17\n");
fclose(oom_killer_file);
}
/*
get the size of virtual memory pages in bytes,
so the process knows the size of chunks that have to be
made dirty to force the kernel to map the virtual memory page into RAM.
*/
long page_size = sysconf(_SC_PAGESIZE);
// allocate a virtually infinite amount of memory by chunks of a page size.
while(1) {
// will overwrite any previous stored address in tmp, leaking that memory.
char* tmp = (char*) malloc(page_size);
if (tmp)
// make the memory page dirty to force the kernel to map it into RAM.
tmp[0] = 0;
}
return 0;
}
Für alle, die daran interessiert sind, was passiert, wenn Sie dieses Programm am Laufen halten: Auf meinem Testsystem mit 2 GB RAM und 4 GB Swap-Speicher dauerte es ungefähr 10 Minuten, um den RAM aufzufüllen und zu tauschen. Der OOM-Killer hat seine Arbeit aufgenommen und drei Minuten später wurden alle Prozesse beendet. Sogar Maus, Tastatur und Display wurden vom System entfernt. /var/log/kern.log zeigt außer den Prozessen, die beendet wurden, keine nützlichen Informationen an.