ďťż

Blog literacki, portal erotyczny - seks i humor nie z tej ziemi


Oto zadanie poświęcone funkcji systemowej fork.

Wydawać by sie mogło, że nic się nie da tutaj wymyślić, gdyż
fork dobrze wykonuje swoją robotę. Można jednak usprawnić tą funkcję
w przypadku, gdy proces potomny wywołuje
jedną z funkcji z rodziny exec. W takim przypadku nie musi być kopiowana
żadna ze struktur vm_area_struct opisujaca pamieć wirtualną procesu. Odpowiada
to wywołaniu funkcji do_fork z ustawioną flagą CLONE_VM. Tak więc, chciałoby
się mieć nową funkcję, powiedzmy fork2, która wywoływałaby w ten sposób
do_fork, a którą byśmy używali w naszych programach testowych (zmiana funkcji
sys_fork w jądrze na pewno by zawiesiła system). Są na to dwie metody.

Sposób 1.

Stworzyć własną funkcję w standardowej bibliotece lib.c, ktora by korzystała
z funkcji systemowej sys_clone (sys_clone(0, SIGCLD | CLONE_VM)) Co prawda
dawniej istniała stadardowa funkcja C clone wywołująca sys_clone, ale zniknęła
z powodu złego działania.


Sposób 2.

Zmodyfikować istniejacą w źródłach jądra funkcję execve. Np. jeśli
jej pierwszym parametrem jest NULL wówczas dziala jak nasz fork2. Odpowiednia
zmiana funkcji w pliku process.c wygląda tak:

asmlinkage int sys_execve(struct pt_regs regs) {

int error;

char * filename;

/********************* poczatek dodanego kodu *****************/


if (!regs.ebx) {


return do_fork(SIGCHLD | CLONE_VM, regs.esp, regs);


}


/********************* koniec dodanego kodu ******************/


error = getname((char *) regs.ebx, &filename);

if (error) return error;

error = do_execve(filename, (char **) regs.ecx, (char **) regs.edx,
regs);

putname(filename);

return error;


}

Osobiście polecam raczej drugi sposób, choć jest mniej elegancki. Kompilacja
biblioteki C jest równie czasochłonna jak jądra oraz przy tworzeniu wlasnej
funkcji wywołującej funkcję systemową trzeba stworzyć kilka plików bazujących
w dużej mierze na niezrozumiałych na pierwszy rzut oka makrach. Próbowałem
to uzyskać, ale się zniechęciłem - nie miałem pewności, czy będzie to działać.


Pozostaje ponownie skompilować jądro, a następnie zrobić jakiś eksperyment.
Np. porównać czasy wykonania programów zawierających fork i exec, dla normalnego
forka i fork2 (czyli dla naszego execve(NULL,NULL,NULL)).

Oczekiwane wyniki eksperymentu:

Skopiowanie listy i drzewa AVL struktur vm_area_strukt, ktore nam udało
się wyeliminować z tak wywołanej funkcji fork2, znacznie przyspieszy samą
operację tworzenia nowego procesu. Wydaje się jednak, że operacją dominującą
jest wywołanie funkcji exec. Mimo wszystko w sytuacji gdy proces-rodzic
jest dosyć duży, a sam plik uruchamiany w funkcji exec niewielki, możemy
uzyskać nawet niezłą poprawę szybkości takiego programu.

P.S. Wydawać by sie mogło, że to, co opisuję odpowiada w pewnym stopniu
istniejącej w unixowych systemach funkcji vfork. Otóż, nic takiego nie
ma miejsca, jak można przekonać się ze źródeł biblioteki libc.a funkcja
vfork dokładnie pokrywa sie z fork.

Autor: Michał Smoktunowicz
  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • qualintaka.pev.pl
  •