Pytanie Napisz skrypt powłoki bash, który zużywa stałą ilość pamięci RAM na czas zdefiniowany przez użytkownika [closed]


Próbuję napisać skrypt powłoki bash, który zużywa dużą ilość pamięci RAM na urządzeniu osadzonym przez czas zdefiniowany przez użytkownika. Jak to zrobić bez korzystania z tablic?


21
2018-02-11 01:39


pochodzenie


Nie jestem zorientowany w bash-fu, ale ... co jest złego w korzystaniu z tablic? - Scott M.
Tablice nie są obsługiwane w tej ograniczonej powłoce na urządzeniu osadzonym. - abc
Wtedy to nie Bash. - Dennis Williamson
Chyba, że ​​oznacza on powiązane tablice, które są "najnowsze" w bashu. W każdym razie nie widzę, jak nie używanie tablic jest istotne dla tego problemu. - ℝaphink
Mogę to przeliterować dd bs=250M if=/dev/zero of=/dev/null zająć 250 MB - user128536


Odpowiedzi:


Nawet jeśli jest tradycyjny Tablice Bash nie są obsługiwane, nadal możliwe jest tworzenie zmiennych tablicowych za pomocą eval polecenie wbudowane w konkretną powłokę.

Poniższy skrypt przykładowy jest oparty na niektórych skryptach, które zrobiłem podczas używania BusyBox w osadzonym projekcie linuksowym. BusyBox używa Powłoka Almquista (znany również jako A Shell, ash i sh), który nie obsługuje tablic.

#!/bin/ash

for index in 1 2 3 4 5; do
    value=$(($index * 1024))
    eval array$index=\"array[$index]: $value\"
done

for i in 1 3 5; do
    eval echo \$array$i
done

Zachowaj ostrożność podczas cytowania podczas używania eval!

Wydajność:

array[1]: 1024
array[3]: 3072
array[5]: 5120

W zależności od konkretnego scenariusza może wystarczyć skrypt podobny do poniższego.

#!/bin/ash

echo "Provide sleep time in the form of NUMBER[SUFFIX]"
echo "   SUFFIX may be 's' for seconds (default), 'm' for minutes,"
echo "   'h' for hours, or 'd' for days."
read -p "> " delay

echo "begin allocating memory..."
for index in $(seq 1000); do
    value=$(seq -w -s '' $index $(($index + 100000)))
    eval array$index=$value
done
echo "...end allocating memory"

echo "sleeping for $delay"
sleep $delay

W moich krótkich testach ten skrypt pochłonął ~ 570M do ~ 575M pamięci fizycznej* przez określony czas 5 minut.

* Monitorowane za pomocą programów top i memprof w osobnych testach


15
2018-02-11 17:39



Tak, jestem również na zajęty w urządzeniu wbudowanym. - abc
Dzięki za wspaniałą odpowiedź! - abc
Dzięki, że drugi wykonał za mnie to zadanie - tristanbailey


Osobiście chciałbym pójść z odpowiedzią Nicka, ponieważ robienie tego w C będzie znacznie łatwiejsze.

Ale ... jeśli naprawdę chcesz uniknąć pisania super prostego programu C, to (jeśli system działa pod Linuksem z właściwymi wbudowanymi) powinieneś być w stanie to zrobić montując tmpfs o rozmiarze ograniczenie ilości pamięci, z której chcesz korzystać, a następnie wypuszczanie danych do pliku w tmpfs w celu wypełnienia go (np. poprzez kopiowanie danych z nieskończonego źródła (np. /dev/zero).

Program C jest jednak znacznie łatwiejszy, o ile można go skompilować na platformę.


4
2018-02-11 01:50





Musisz rozróżnić przydzieloną i roboczą pamięć RAM. Łatwo jest zjeść pamięć w bashu:

A="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
for power in $(seq 8); do
  A="${A}${A}"
done

ale jeśli skrypt często nie przeszukuje danych, to te strony pamięci są dobrymi kandydatami do wymiany.


3
2018-02-11 15:37





@JohnBartholomew

Twój pomysł na temat montażu tmpfs też nie jest taki trudny i możesz być bardziej pewny, że faktycznie zużywa on RAM, prawda? (patrz komentarz Chrisa Dodda w odpowiedzi Nicka)

mount -t tmpfs none /new/path/for/temp -o size=32m
dd if=/dev/zero of=/new/path/for/temp/zero.txt bs=32m count=1 

Prawdopodobnie dd będzie narzekać, że na urządzeniu nie ma już miejsca. Ponadto, nie wiem, ile pamięci RAM będzie używane dokładnie, ale jeśli mówisz o MB, to powinno być dobrze.


2
2018-02-11 14:59



Powodem, dla którego wybrałbym opcję C (ale nie malloc, konkretnie) jest to, że możesz wtedy użyć funkcji zarządzania pamięcią systemową i mieć pewność, jaki dokładnie efekt masz. np. mlock () może być użyty, aby upewnić się, że jądro nie popchnie twojej alokacji do magazynu zaplecza. Zauważ, że tmpfs jest wspierany przez pamięć wirtualną, tak naprawdę moja sugestia cierpi z powodu tego samego problemu co Nick - w rzeczywistości pisanie pliku do wypełnienia jest tylko hackem, aby upewnić się, że pamięć RAM jest zużyta. Być może istnieje jakiś inny system plików oparty na pamięci RAM, ale jak sądzę. - John Bartholomew


Jeśli masz /dev/shm urządzenie, możesz zapisać do pliku tam, ponieważ domyślnie jest to tmpfs.


2
2018-02-11 15:12





Wpadłem na to. / dev to tmpfs

 #!/bin/sh

 mntroot rw
 cd /dev
 while : 
 do 
        dd > /dev/null 2>&1 if=/dev/zero of=myfile1 count=25000 bs=1024 # eat up 25 MB of RAM 
        usleep 1 
        rm myfile1

 done

2
2018-02-12 02:34