Kurs C
menu C#
Wywołania systemowe w kodzie C |
Mając już jakieś pojęcie o języku C dochodzimy do jego największej zalety, czyli wywołań systemowych. W języku C mamy bezpośredni dostęp do każdego programu zapisanego na komputerze poprzez funkcje system(). Użycie tej funkcji jest proste. Jeśli chcemy wyświetlić zawartość katalogu w którym jest projekt wystarczy wpisać polecenie system("ls"). Jeśli byśmy chcieli otworzyć konsole w Windowsie, to wystarczyłoby wpisać system("cmd"). Mamy w ten sposób dostęp do wszystkich poleceń wykonywalnych w konsoli z poziomu kodu. Dla przykładu użyjmy polecenia "echo", które utworzy plik log.txt i zapisze słowo 'test'. Wynikiem działania będzie powstanie pliku z zawartością 'test' o nazwie log.txt w tym samym katalogu co kod. Jak widzicie funkcja system() jest bardzo prosta, ale niesie ze sobą niebezpieczeństwo w postaci zapisywania i uruchamiania niechcianych plików. Jeśli nasz program będzie pobierał stringa z poleceniem z serwera www, to moglibyśmy wstrzyknąć tam praktycznie każdy kod. Począwszy od kasowania, a skończywszy na uruchamianiu złośliwego oprogramowania. Z tego też właśnie powodu utworzono funkcje exec(), która ma jednoznacznie określi co chcemy zrobić. Używając funkcji system(), to jądro systemu interpretowało polecenie i dopiero wykonywało program. W tym przypadku, to my musimy podać wszystkie argumenty i zmienne, a czasem nawet ścieżkę do katalogu lub zmienne PATH. Z tego właśnie powodu jest wiele rodzajów funkcji exec(). Ogólnie dzielimy je na dwie grupy: funkcje exec() z listą argumentów oraz funkcje z tablicą argumentów. Funkcje z listą argumentów, to na przykład execl(), execlp() i execle(), a stosuje się je w następujący sposób: Załóżmy, że chcemy odpalić Projekt1.exe (może to być ten program powyżej) który umieścimy na dysku C w katalogu test. Ścieżka do tego pliku wygląda następująco C:\test\Projekt1.exe. Używając funkcji execl() dla systemu Windows możemy to zrobić w następujący sposób: Po odpaleniu tego programu zostanie wywołany program Projekt1.exe. Jeśli jest to wcześniejszy program z funkcjami system(), to uzyskacie dokładnie taki sam efekt. Program wyświetli pliki w projekcie i utworzy plik log.txt. Warte uwagi jest to, że plik zapisze się w katalogu z nowym projektem, a nie tam gdzie znajduje się program. Wywołanie tego samego programu za pomocą funkcji execlp() będzie wyglądało tak: W tym przypadku litera "p" na końcu funkcji oznacza, że projekt będzie szukany w zmiennej PATH. Czyli, aby program zadziałał należałoby dodać ścieżkę do programu w zmiennej PATH lub dołączyć go do już istniejących ścieżek. Wywołanie tego samego programu za pomocą funkcji execle() będzie wyglądało tak: W tym przypadku litera "e" na końcu oznacza, że do programu można dołożyć zmienne środowiskowe. Funkcje z tablicą argumentów, to na przykład execv(), execvp() i execve(), a stosuje się je w podobny sposób co funkcje z listą argumantów: Ogólna postać funkcji exec() wygląda następująco: Ale co tak naprawdę robi funkcja exec()? Funkcja exec() zastępuje działający program na ten wywołany. Czyli nowy program jest widziany przez system jako stary program, ponieważ ma ten sam numer PID (PID to numer procesu, które przydziela jądro). Jeśli rzeczywiście tak jest, to wszystkie komendy poniżej exec() nie będą wykonywane, jeśli uda się otworzyć program. Takie zachowanie można użyć do sprawdzania, czy nasz program rzeczywiście otworzył inny program. W tym celu stworzono globalną zmienną errno, która znajduje się w pliku errno.h. Ta zmienna może przybierać wiele różnych wartości, które można zobaczyć otwierając plik errno.h. Gdy nie uda się nam otworzyć programu za pmocą exec(), to zmienna errno przybierze jakąś wartość, która będzie informowała o zdarzeniu które się stało. Aby odczytać te zdarzenie należy użyć funkcji strerror(errno), która przekształci liczbę na stringa. Dla przykładu, gdy zmienna errno ma wartość 1, 2 lub 3, to uzyskamy następujące komunikaty: EPERM = 1 Operation not permitted (niedozwolona operacja) Najłatwiej sprawdzić naszą funkcję podając błędnąścieżkę do pliku: teraz w konsoli uzyskamy komunikat: Dzięki funkcji exec() możecie połączyć dowolny program napisany w innym języku programowania. Nie ważne czy jest to program napisany w Javie, czy Pythonie, nasz program w C go uruchomi i dostarczy odpowiednie parametry do prawidłowej pracy. |