Wywołania systemowe Uniksa: Różnice pomiędzy wersjami

[wersja przejrzana][wersja przejrzana]
Usunięta treść Dodana treść
m Poprawienie linku do art. o forku()
Paweł Ziemian BOT (dyskusja | edycje)
m Zamieniam przestarzały tag 'source' na 'syntaxhighlight'
Linia 45:
== Otwieranie i zamykanie plików - <tt>open</tt>, <tt>create</tt> i <tt>close</tt> ==
Pliki otwiera się za pomocą trzyargumentowego <tt>open</tt>, którego definicja znajduje się w <tt>fcntl.h</tt>[http://lxr.linux.no/linux/include/asm-generic/fcntl.h]:
<sourcesyntaxhighlight lang="c">
int open(const char *pathname, int flags, mode_t mode);
</syntaxhighlight>
</source>
 
Pierwszy argument <tt>pathname</tt> oznacza ścieżkę do pliku.
Linia 63:
'''Opcjonalny''' trzeci - uprawnienia dla nowo utworzonych plików.
<tt>open</tt> należy do nielicznych wywołań systemowych dopuszczających pomijanie argumentu:
<sourcesyntaxhighlight lang="c">
int open(const char *pathname, int flags);
</syntaxhighlight>
</source>
 
Istnieje też specjalna postać <tt>open</tt>:
<sourcesyntaxhighlight lang="c">
int creat(const char *pathname, mode_t mode);
</syntaxhighlight>
</source>
równoważna <tt>open(pathname, O_CREAT|O_WRONLY|O_TRUNC, mode)</tt>
 
Linia 76:
W przypadku błędu zwracają <tt>-1</tt> a <tt>[[errno]]</tt> jest ustawiana na kod błędu.
 
<sourcesyntaxhighlight lang="c">
int close(int fd);
</syntaxhighlight>
</source>
zamyka otwarty deskryptor pliku. W dawnych czasach <tt>close</tt> nie zwracało kodu błędu,
więc nikt go nie sprawdzał. Współcześnie zwraca kod błędu, co z punktu widzenia architektury systemu
Linia 91:
 
Katalogi tworzy się za pomocą:
<sourcesyntaxhighlight lang="c">
int mkdir(const char *pathname, mode_t mode);
</syntaxhighlight>
</source>
gdzie <tt>pathname</tt> i <tt>mode</tt> mają znaczenie podobne jak w <tt>creat</tt>.
 
Pliki urządzeń tworzy się za pomocą:
<sourcesyntaxhighlight lang="c">
int mknod(const char *pathname, mode_t mode, dev_t dev);
</syntaxhighlight>
</source>
gdzie <tt>pathname</tt> i <tt>mode</tt> mają to samo znaczenie a <tt>dev</tt> to informacje o typie urządzenia.
 
== Zakończenie pracy - <tt>_exit</tt> ==
<sourcesyntaxhighlight lang="c">
void _exit(int status);
</syntaxhighlight>
</source>
służy do zakończenia pracy programu.
<tt>status</tt> zostanie zwrócony jako kod wyjścia.
 
== Zarządzanie pamięcią - <tt>brk</tt> ==
<sourcesyntaxhighlight lang="c">
int brk(void *end_data_segment);
</syntaxhighlight>
</source>
 
Wywołanie <tt>brk</tt> jest bardzo ważne i widać je często w wynikach <tt>strace</tt>,
Linia 129:
=== <tt>read</tt> ===
<tt>read</tt> jest zdefiniowany w <tt>unistd.h</tt>[] jako:
<sourcesyntaxhighlight lang="c">
ssize_t read(int fd, void *buf, size_t count);
</syntaxhighlight>
</source>
 
Pierwszym argumentem jest otwarty deskryptor piku, drugim bufor, do którego mają się dostać zapisywane dane,
Linia 152:
=== <tt>write</tt> ===
<tt>write</tt> jest zdefiniowany w <tt>unistd.h</tt> jako:
<sourcesyntaxhighlight lang="c">
ssize_t write(int fd, const void *buf, size_t count);
</syntaxhighlight>
</source>
 
Argumenty mają takie samo znaczenie jak w <tt>read</tt> - <tt>write</tt> pisze do deskryptora <tt>fd</tt> co najwyżej <tt>count</tt> bajtów z bufora <tt>buf</tt> i zwraca liczbę zapisanych bajtów. W przypadku <tt>write</tt> liczba <tt>0</tt> jest jednak równie poprawna jak pozostałe i można próbować dalej.
Linia 165:
 
Nic nie stoi jednak na przeszkodzie, żeby kernel sam zajął się tą operacją - służą temu zdefiniowane w <tt>sys/uio.h</tt> wywołania:
<sourcesyntaxhighlight lang="c">
int readv(int filedes, const struct iovec *vector, size_t count);
int writev(int filedes, const struct iovec *vector, size_t count);
</syntaxhighlight>
</source>
 
Pierwszy argument to tradycyjnie otwarty deskryptor pliku, drugi to wskaźnik na tablicę wektorów,
trzeci zaś to ilość elementów tej tablicy. Element ma postać:
 
<sourcesyntaxhighlight lang="c">
struct iovec {
void *iov_base;
size_t iov_len;
};
</syntaxhighlight>
</source>
 
gdzie <tt>iov_base</tt> to adres a <tt>iov_len</tt> rozmiar bufora.
 
Procedura naszego serwera miałaby wówczas postać:
<sourcesyntaxhighlight lang="c">
struct iovec io[2];
io[0].iov_base = http_headers;
Linia 190:
io[1].iov_len = file_headers_size;
writev (fd, io, 2);
</syntaxhighlight>
</source>
 
<tt>readv</tt> i <tt>writev</tt> pojawiły się po raz pierwszy w systemie [[4.2BSD]].
Linia 197:
=== <tt>sendfile</tt> ===
Kolejny często występujący problem wydajności przedstawia następujący fragment kodu:
<sourcesyntaxhighlight lang="c">
bytes_read = read (fd1, buf, buf_size);
write (fd2, buf, bytes_read);
</syntaxhighlight>
</source>
 
Często występuje konieczność przerzucenia ogromnej ilości danych z jednego deskryptora do drugiego.
Jednym problemem jest podwojona liczba wywołań systemowych, ale jeszcze poważniejse jest zupełnie
bezużyteczne kopiowanie danych. Przeciwdziałać temu ma zdefiniowany w nagłówku <tt>sys/sendfile.h</tt>:
<sourcesyntaxhighlight lang="c">
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
</syntaxhighlight>
</source>
 
<tt>out_fd</tt> to deskryptor wyjściowy, <tt>in_fd</tt> - wejściowy, <tt>offset</tt> to wskaźnik na
Linia 225:
 
Przykład działania:
<sourcesyntaxhighlight lang="c">
#include <sys/sendfile.h>
#include <unistd.h>
Linia 256:
return 0;
}
</syntaxhighlight>
</source>
 
Ponieważ dane nie wędrują przez pamięć procesu, można podawać "absurdalne" wartości typu (jak wyżej) 64 megabajty
Linia 274:
== Sprawdzanie uprawnień ==
Zdefiniowane w <tt>unistd.h</tt> wywołanie:
<sourcesyntaxhighlight lang="c">
int access(const char *pathname, int mode);
</syntaxhighlight>
</source>
służy do sprawdzenia praw do pliku <tt>pathname</tt>.
 
Linia 298:
 
Przykład działania:
<sourcesyntaxhighlight lang="c">
#include <unistd.h>
#include <stdio.h>
Linia 332:
return 0;
}
</syntaxhighlight>
</source>
 
== Przechwytywanie sygnałów ==
Kontroler sygnałów instaluje się za pomocą zdefiniowanej w <tt>signal.h</tt> funkcji:
<sourcesyntaxhighlight lang="c">
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
</syntaxhighlight>
</source>
 
Na przykład jeśli nie chcemy pozwolić na Control-C (SIGINT, 2) w trakcie wpisywania danych,
możemy przechwycić sygnał:
<sourcesyntaxhighlight lang="c">
#include <stdio.h>
#include <signal.h>
Linia 359:
return 0;
}
</syntaxhighlight>
</source>
 
== Zobacz też ==