2013-03-24 8 views
6

Niedawne jądra Linuksa (przynajmniej na amd64) dostarczają magiczny plik obiektowy o nazwie linux-vdso.so.1, który usuwa interfejs syscall do jądra, umożliwiając jądrowi wybór optymalnej konwencji wywoływania. Jeśli napiszesz kod w C, glibc automatycznie użyje tego obiektu.Jak wykorzystać obiekt VDSO z własnym językiem programowania?

Teraz, jeśli chcę napisać program bez użycia glibc, jak mogę użyć tego obiektu? Czy interfejs, który zapewnia, jest gdzieś udokumentowany? A co z konwencją wzywającą?

+0

Z ciekawości, jaki jest twój język, który nie korzysta z interfejsu * C * dla syscalls? Czy zapewniasz dla niego darmową implementację oprogramowania? –

+0

@Basile Próbuję napisać Forth, aby dowiedzieć się, jak działa Forth. Chcę programować w złożeniu bez żadnych istniejących bibliotek, podobnych do [jonesforth] (http://git.annexia.org/?p=jonesforth.git). Obiekt VDSO jest po prostu przyjemnym i wydajnym sposobem realizacji wywołań systemowych. – fuz

Odpowiedz

6

To zależy, czy realizacja używa C interfejs do narzędzi niskopoziomowych albo nie.

Jeśli język daje bezpośredni dostęp do syscalli bez przechodzenia thru C owijki nie trzeba używać VDSO (można na przykład wygenerować odpowiednią dyspozycję SYSENTER maszynowy zrobić syscall). W takim przypadku twój język nie musi nawet przestrzegać wszystkich konwencji ABI, tylko konwencji jądra. (na przykład, nie potrzebujesz ABI pod warunkiem, że w rejestrach jest bezpieczne bezpieczne wywołanie, możesz nawet uniknąć używania jakichkolwiek stosów).

Moja wiedza na temat VDSO polega na tym, że jest to abstrakcja dostarczana przez jądro, aby usunąć różne małe różnice (związane z użytkownik-ziemia -> przejścia jądra) we wdrażaniu syscalls pomiędzy różnymi rodzinami procesorów x86. Jeśli wybrałeś konkretny cel procesora, nie potrzebujesz VDSO i zawsze możesz tego uniknąć.

AFAIU, VDSO jest obiektem wspólnym ELF, siedzi (na moim Debianie/AMD64 z ostatnio skompilowanym jądrem 3.8.3) w segmencie ffffffffff600000-ffffffffff601000; sprawdź dokładnie, gdzie jest cat /proc/self/maps). Musisz więc po prostu zrozumieć organizację obiektów wspólnych ELF i pobrać z niej symbole. Zobacz linki: this & that. VDSO używa konwencji C dla wywołania udokumentowanego w specyfikacji ABI x86-64.

Oznacza to, że jeśli wyodrębnić z przestrzeni procesowej VDSO i zapisać go na dysku plik, wynik jest dobrze uformowane ELF obiekt udostępniony

ELF jest dobrze udokumentowana Format. Tak samo jest z x86-64 ABI conventions (która dokładnie definiuje konwencje wywoływania C i jak dokładnie zaczyna się obraz procesu (zobacz także execve(2)) oraz dokumentację jądra, więc nie rozumiem, jaki jest twój problem. Zgadzam się, że zrozumienie ELF wymaga czasu (zrobiłem to 10 lat temu, ale moja pamięć jest zardzewiała). Przeczytaj także plik nagłówkowy <elf.h> na swoim komputerze.

Na przykład; działa (w zsh na 64 bitów x86-64 Debiana)

% file $(which sash) 
/bin/sash: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), 
     statically linked, for GNU/Linux 2.6.26, 
     BuildID[sha1]=0x0347fcc08fba2f811f58af99f26111d0f579a9f6, stripped 

% ldd $(which sash) 
not a dynamic executable 

    % sash 
    Stand-alone shell (version 3.7) 
    > ps |grep sash 
    21635 pts/3 00:00:00 sash 
    > cat /proc/21635/maps 
    00400000-004da000 r-xp 00000000 08:01 4985590       /bin/sash 
    006da000-006dc000 rw-p 000da000 08:01 4985590       /bin/sash 
    006dc000-006e1000 rw-p 00000000 00:00 0 
    017e3000-01806000 rw-p 00000000 00:00 0         [heap] 
    7fe4950e5000-7fe4950e7000 rw-p 00000000 00:00 0 
    7fff3f130000-7fff3f151000 rw-p 00000000 00:00 0       [stack] 
    7fff3f173000-7fff3f175000 r-xp 00000000 00:00 0       [vdso] 
    ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0     [vsyscall] 

Patrz także this answer.

Prawdopodobnie chcesz w swoim środowisku wykonawczym minimalną wersję dynamicznego linkera, który będzie w stanie po prostu przeanalizować VDSO.Na pewno chcesz zrozumieć dokładny stan, w którym rozpoczyna się proces, a zwłaszcza rolę auxv, pomocniczego wektora (naprawdę zapominam o tych szczegółach, ale pamiętam, że są one ważne). Zobacz np. this article

Rzeczywiście, uruchomienie niezawodnie Twój czas pracy jest prawdopodobnie trudniejszy niż problem VDSO.

Można też przeczytać linux assembly howto która wyjaśnia również pewne rzeczy (ale o x86 niż x86-64)

BTW, kod http://musl-libc.org/ (który jest alternatywą libc) jest znacznie łatwiejsze do odczytania i zrozumieć (i będziesz łatwo nauczyć robią dynamiczne linkowanie, pthreads, etc ..)

+0

Próbuję zaimplementować bibliotekę środowiska wykonawczego dla języka programowania, bez używania jakichkolwiek elementów glibc. Potrzebuję prymitywów dla wywołań systemowych, które zawijają instrukcje. Chciałbym użyć VDSO dla prędkości, ponieważ używa najszybszej dostępnej metody do wykonania wywołania systemowego. – fuz

+0

Następnie zaprojektuj i zaimplementuj go jako pierwszy, a następnie zoptymalizuj go. VDSO to optymalizacja, która nie jest tak naprawdę ważna w praktyce, zwłaszcza w nowym języku programowania (większość programów nie jest związana z syscall, ale jest to procesor użytkownika lub IO), więc VDSO nie ma większego znaczenia. AFAIK, statycznie połączone pliki binarne (nawet w C) nie używają VDSO, nawet jeśli pozostaje w ich przestrzeni adresowej. –

+0

Twoja odpowiedź i twój komentarz nie odnoszą się do żadnego z moich pytań.To strasznie nieprzydatne, gdy pytam "Howto A", a odpowiedź brzmi "Do A later". – fuz

4

Na kopanie w internecie znalazłem ten link

http://www.linuxjournal.com/content/creating-vdso-colonels-other-chicken

myślę, że odpowiedzi na swoje pytanie

+0

Ten artykuł nie pomaga w ogóle. Opisuje sposób dodania syscall do VDSO po stronie jądra; nie mówi prawie nic o stronie użytkownika, z wyjątkiem tego, jak uzyskać ten obiekt, jeśli jest już podłączony (co nie ma miejsca, jeśli kompiluję bez glibc). – fuz

+2

VDSO jest magicznie połączony nawet bez Glibc. Można zrozumieć, jak robią to inne Libc-y. Znajduję kod źródłowy http://musl-libc.org/ bardzo czytelny (więcej niż Glibc, który używa wielu sztuczek preprocesora). –

+0

@Basile Skompiluj plik obiektowy za pomocą -nostdlib, a następnie wykonaj ldd a.out, aby zrzucić połączone biblioteki; linux-vdso.so.1 nie ma na liście. (To jest, jeśli używasz glibc). – fuz

4

znalazłem te pliki w drzewie jądra Linux pomocne:

Przedmiotem vDSO jest wirtualny dynamiczny obiekt udostępniony że zawsze jest odwzorowywany w przestrzeni adresowej procesu amd64 pod Linuksem. Może służyć do realizacji szybkich wywołań systemowych. Aby uzyskać dostęp do funkcji wewnątrz obiektu vDSO, trzeba

  • zlokalizować obiekt
  • ekstrakt adresu z tablicy symboli

Obie rzeczy można zrobić z realizacji CC0 licencjonowany odniesienia parse_vdso.c.

Powiązane problemy