2014-04-28 8 views
6

Próbuję zapewnić własną implementację funkcji close() w systemie Linux. Czemu? Ponieważ właśnie się dowiedziałem, że możesz to zrobić i brzmi to zabawnie.Zastępowanie funkcji close() w systemie Linux z moją własną funkcją close()

Oto myclose.c:

#include <stdio.h> 

int close(int fd) { 
    printf("Closing fd: %d\n", fd); 
    return 0; 
} 

Oto mój makefile:

all: myclose.so my-close.so 

%.so: %.o 
    gcc -shared -o [email protected] $< 

%.o:%.c 
    gcc -c -fPIC -o [email protected] $< 

clean: 
    rm -f *.so *.o 

Po kompilacji, biegnę:

export LD_PRELOAD=`pwd`/myclose.so 

Potem uruchom:

cat myclose.c 

Wyjście pojawia się:

#include <stdio.h> 

int close(int fd) { 
    printf("Closing fd: %d\n", fd); 
    return 0; 
} 
Closing fd: 3 

Yay! Działa dobrze? Prawie. cat dzwoni close() więcej niż jeden raz, ale widzimy tylko jeden wiersz wyjściowy. Zgodnie z strace (i zdrowym rozsądkiem), należy również wywołać close() dla deskryptorów plików 1 i 2. Jeśli uruchomię cat * i cat wszystkie pliki w katalogu, widzę "Zamykanie fd: 3", "Zamykanie fd: 4" itd. Aż do ostatniego pliku w katalogu. Ponieważ wszystkie te deskryptory plików są większe niż 2, pomyślałem, że być może wystąpił problem z zamykaniem specjalnych deskryptorów plików (stdout i stderr). Jednak po uruchomieniu ls widzę tylko zwykłe dane wyjściowe i nie ma linii "Zamykanie fd:", co oznacza, że ​​nie działał on również dla ls, chociaż strace pokazuje close(3) podczas uruchamiania ls.

Wszelkie pomysły na temat tego, co może być nie tak?

+0

Mogę się tu całkowicie mylić, ale czy to nie powłoka zajmuje się FD 1 i 2? Czy próbowałeś uruchomić powłokę preinstalującą ją za pomocą "close()"? – lorenzog

Odpowiedz

1

Jestem zaskoczony, że zadziałało tak dobrze, jak było!

Zastępujesz wpis biblioteki C dla close(), a nie wywołania systemowego. Jednak inne części biblioteki C nadal są używane w tych programach. Prawdopodobnie istnieje pewne bezpośrednie połączenie z pierwszymi trzema uchwytami plików. Spójrz na źródło dowolnej biblioteki C, której używasz.

2

Ten rodzaj "zamiennika" działa tylko w dynamicznie powiązanych programach.

Każdy program połączony statycznie z biblioteką implementującą telefon close nie będzie mógł go "wymienić".

Ta ostatnia będzie miała miejsce w przypadku każdego połączenia z close() z biblioteki implementującej sam siebie jako oryginalną close(). I wydaje się, że jest tak również w przypadku standardowych deskryptorów plików, ponieważ ich zamykanie jest najprawdopodobniej zaimplementowane w tej samej bibliotece, co w używanej implementacji libc.

Powiązane problemy