2012-05-09 8 views
5

Chciałbym mieć mały program do "ładowania aplikacji", który odbiera inne pliki aplikacji binarnych przez TCP z zewnętrznego serwera i uruchamia je.Wykonać proces z pamięci w ramach innego procesu?

Mogłem to zrobić, zapisując przesłany plik na dysk twardy i używając wywołania system(), aby go uruchomić. Zastanawiam się jednak, czy możliwe byłoby uruchomienie nowej aplikacji z pamięci bez dotykania dysku twardego.

Stan aplikacji ładującej nie ma znaczenia po załadowaniu nowej aplikacji. Wolę trzymać się C, ale rozwiązania C++ są również mile widziane. Chciałbym również trzymać się standardowych funkcji Linux C i nie używać zewnętrznych bibliotek, jeśli to możliwe.

+0

Tak, jest to możliwe, ale jest nieco skomplikowane. Musisz emulować system operacyjny i mapować plik binarny do pamięci, itp. –

+2

Możesz zapisać go do pliku na ramdysku – TJD

+1

Mam również tendencję do myślenia, że ​​* dowolny * poziom bezpieczeństwa systemu operacyjnego na umiarkowanie niedawnym CPU będzie robił najlepiej, aby to się nie stało. Z pewnością jest to wykonalne, ale byłby bardzo trudny w użyciu na dystrybucjach w świecie rzeczywistym (mam nadzieję). – BRFennPocock

Odpowiedz

3

Krótka odpowiedź: nie.

Długa odpowiedź: Jest to możliwe, ale dość trudne, aby to zrobić bez zapisywania go na dysku. Możesz teoretycznie napisać własny program ładujący elfa, który czyta plik binarny, mapuje pamięć, obsługuje dynamiczne łączenie zgodnie z wymaganiami, a następnie przekazuje kontrolę, ale to bardzo dużo pracy, która nigdy nie będzie warta wysiłku.

Kolejnym najlepszym rozwiązaniem jest zapisanie go na dysk i wywołanie odłączenia ASAP. Dysk nie musi nawet być "prawdziwym" dyskiem, może to być tmpfs lub podobny.

Alternatywą, której ostatnio używałem, jest nie przekazywanie kompletnych skompilowanych plików binarnych, ale przekazywanie kodu bajtowego LLVM, który następnie może być JIT'd/interpretowany/zapisywany jako odpowiedni. Ma to także tę zaletę, że aplikacja działa w heterogenicznych środowiskach.

może to być kuszące, aby spróbować kombinacji fmemopen, fileno i fexecve, ale to nie będzie działać z dwóch powodów:

  1. Od fexecve() manpage:

    „Plik deskryptor fd musi być otwarty tylko do odczytu, a wywołujący musi mieć pozwolenie na wykonanie pliku, który odnosi się do "

    tj. musi to być fd, które odnosi się do pliku.

  2. Od fmemopen() manpage:

    „Nie ma plik deskryptora związane ze strumienia pliku zwracanej przez te funkcje (tj fileno(3) zwróci błąd, jeśli wezwał zwróconego Stream)”

+0

Dzięki za odpowiedź; właśnie tego szukałem. Kierowanie tematem nie zaszło mi zbyt daleko i musiałem zaspokoić moją ciekawość! – Flip

+0

Należy zauważyć, że obecnie standardem jest posiadanie 'tmpfs' zamontowanego w'/dev/shm/'. – caf

0

Znacznie łatwiej niż to zrobić, C będzie po prostu skonfigurować system plików tmpfs. Miałbyś wszystkie zalety interfejsu twardego dysku, ze swojego programu/serwera/cokolwiek innego, co mógłbyś zrobić po prostu exec. Tego typu wirtualne systemy plików są obecnie dość wydajne, w pamięci podręcznej stron byłaby naprawdę tylko jedna kopia pliku wykonywalnego.

Jak zauważa Andy, aby taki system był skuteczny, musisz upewnić się, że nie używasz buforowanych zapisów do pliku, ale że "piszesz" (w szerszym znaczeniu) bezpośrednio na miejscu.

  • trzeba by wiedzieć, jak duży plik wykonywalny będzie
  • utworzyć plik na swoim tmpfs skalować
  • do tej wielkości z ftruncate
  • „map”, że plik do pamięci z mmap do uzyskać adr bufora
  • podanie tego adresu bezpośrednio na wezwanie recv zapisywać dane w miejscu
  • munmap plik
  • zadzwoń pod numer exec z plikiem
  • plik. Można to zrobić nawet wtedy, gdy plik wykonywalny jest nadal uruchomiony
+0

Szczerze mówiąc tmpfs nie będzie szybszy niż macierzysty system plików, chyba że twoje miejsce jest już w stanie. Zapisy zostają zbuforowane do pamięci tak, że natychmiastowe execve() po prostu zmapuje je z pamięci podręcznej. Jedynym kosztem, jaki zapłacisz, jest ostateczny spłukanie na dysk, który jest asynchroniczny. –

+0

@AndyRoss, nie używaj buforowanych zapisów do takich rzeczy, zaktualizuję moją odpowiedź. –

+1

Nawet to po prostu unika kopii pamięci. Jakie jest ograniczenie wydajności? Mam problem z wyobrażeniem sobie sytuacji, w której szybkość zapisu przez system plików jest limitem, ale szybkość odbierania pakietów przez sieć nie jest. Wydaje się bardzo skomplikowane. Wystarczy otworzyć/zapisać do zwykłego systemu plików i zapisać kłopoty. –

0

Możecie zajrzeć do i ponowne UPX, który dekompresuje wykonywalny do pamięci, a następnie przekazuje sterowanie do ld-linux aby go uruchomić.

Powiązane problemy