linuxwiki.pl>PiotrekD (-sekcja "Ciekawostki") |
linuxwiki.pl>PiotrekD |
||
Linia 1: | Linia 1: | ||
+ | {{T}}jeden z podstawowych i sposobów komunikacji międzyprocesowej w systemach uniksowych, w tym również w [[GNU/Linux|Linuksie]]. |
||
− | {{małą literą}} |
||
− | {{T||od angielskiego ''catenate'' - ''łączyć''}}uniksowe polecenie, wyświetlające zawartość podanych plików na [[standardowe wyjście]]. Służy również do ich łączenia, poprzez przekierowywanie wyjścia w powłoce (przy użyciu znaku <code>></code>). |
||
+ | Sygnałami są po prostu liczby określone całkowite. Jeśli jakiś proces otrzyma sygnał, jądro systemu zatrzyma na chwilę jego dotychczasowe działanie i sprawdzi, czy posiada on kod obsługujący dany sygnał. Jeśli tak - uruchomi go, w przeciwnym wypadku - kontynuuje normalne wykonywanie procesu. |
||
− | == Użycie == |
||
+ | |||
+ | == Wysyłanie sygnałów == |
||
+ | |||
+ | === Z poziomu poleceń terminala === |
||
+ | Do wysyłania procesów z poziomu konsoli służy polecenie <code>[[kill]]</code>. Jej użycie ma postać |
||
<terminal> |
<terminal> |
||
− | $ |
+ | $ kill [przełączniki] <PID> {{...|identyfikatory wielu procesów}} |
⚫ | |||
+ | Jeśli nie podane zostaną żadne przełączniki zostanie wysłany sygnał <code>SIGTERM</code>. Aby wysłać inny sygnał, wystarczy podać go poprzedzonego myślnikiem (<code>-</code>). Przykładowo, wysłanie sygnału <code>SIGUSR1</code> o wartości 10 do procesu o numerze 1234, wygląda tak: |
||
⚫ | |||
+ | $ kill -10 1234 |
||
</terminal> |
</terminal> |
||
+ | === Z poziomu programu === |
||
− | * <code>opcje</code> – miejsce na ewentualne parametry; |
||
+ | Wysłanie sygnału z poziomu programu jest możliwe dzięki wywołaniu systemowemu <code>kill()</code>. Jako pierwszy parametr pobiera ono sygnał, który ma zostać wysłany (w przypadku języka C można posłużyć się makrami zdefiniowanymi w pliku nagłówkowym <code><signal.h></code>), a jako drugi - PID procesu, który ma zostać zabity. Umożliwia zabicie tylko jednego procesu naraz. W przypadku powodzenia zwraca 0, w przeciwnym wypadku - -1. Użycie tego wywołania (w C) polegające na wysłaniu <code>SIGUSR1</code> do procesu o numerze 1234, wygląda tak: |
||
− | * <code>plik plik2</code> – lista plików. |
||
+ | <source lang="c"> |
||
+ | kill(10, 1234); |
||
+ | </source> |
||
+ | lub, by użyciu makr z nazwami (wymaga załączenia <code><signal.h></code>): |
||
+ | <source lang="c"> |
||
+ | kill(SIGUSR1, 1234); |
||
+ | </source> |
||
+ | == Obsługa sygnałów == |
||
− | == Najczęściej używane przełączniki == |
||
+ | Za obsługę sygnałów odpowiada wywołanie systemowe <code>signal()</code>. Jako pierwszy argument przyjmuje ona sygnał numer sygnału, a jako drugi - wskaźnik do funkcji, która ma odpowiadać za obsługę tego sygnału. W momencie wywołania do owej funkcji przekazany zostanie argument w postaci numeru sygnału (umożliwia to używanie wspólnej funkcji dla wielu sygnałów). |
||
− | * <code>-A</code> lub <code>--show-all</code> - robi to samo, co <code>-ETv</code>; |
||
− | * <code>-b</code> lub <code>--number-nonblank</code> - numeruje niepuste linie; |
||
− | * <code>-E</code> lub <code>--show-ends</code> - wyświetla znak <code>$</code> na końcu każdej linii; |
||
− | * <code>-n</code> – numeruje wszystkie linie; |
||
− | * <code>-t</code> robi to samo, co <code>-vT</code>; |
||
− | * <code>-T</code> lub <code>--show-tabs</code> - wyświetla znaki tabulacji jako <code>^T</code>; |
||
− | * <code>-v</code> lub <code>--show-nonprinting</code> - wyświetla znaki kontrolne w postaci <code>^X</code> i <code>M-X</code>, gdzie X to odpowiedni znak. |
||
− | == |
+ | === Przykładowy program === |
+ | Poniższy program napisany w C po uruchomieniu czeka w nieskończoność, aż otrzyma sygnał <code>SIGUSR1</code>. Po jego otrzymaniu wyświetli odpowiednią informację i zakończy działanie. |
||
− | Przyjmijmy, że <code>plik.txt</code> zawiera następującą treść: |
||
+ | <source lang="c"> |
||
− | <pre> |
||
+ | #include <stdlib.h> |
||
− | To jest pierwsza linia. |
||
+ | #include <stdio.h> |
||
− | Ta druga. |
||
+ | #include <signal.h> |
||
− | A ta trzecia i zawiera taba,	tutaj. |
||
− | A ta	aż	dwa! |
||
− | To ostatnia linia. |
||
− | </pre> |
||
− | a <code>drugi.txt</code>: |
||
− | <pre> |
||
− | To jest drugi plik. |
||
− | Ma tylko 2 linie. |
||
− | </pre> |
||
+ | void funkcja_obslugujaca_sigusr1(int numer) { |
||
− | === Przykład 1 - wypisanie treści jednego pliku === |
||
+ | puts("Mam SIGUSR1."); |
||
− | Wykonanie <code>cat plik.txt</code> w przykładowym katalogu: |
||
+ | puts("Kończę pracę..."); |
||
⚫ | |||
+ | exit(0); |
||
− | $ cat plik.txt |
||
+ | } |
||
− | To jest pierwsza linia. |
||
− | Ta druga. |
||
− | A ta trzecia i zawiera taba,	tutaj. |
||
− | A ta	aż	dwa! |
||
− | To ostatnia linia. |
||
⚫ | |||
+ | int main(void) { |
||
− | === Przykład 2 – wypisanie treści paru plików === |
||
+ | signal(SIGUSR1, funkcja_obslugujaca_sigusr1); |
||
− | Wykonanie <code>cat plik.txt drugi.txt</code> w przykładowym katalogu: |
||
+ | while (1) { |
||
− | <terminal> |
||
+ | sleep(3600); |
||
− | $ cat plik.txt drugi.txt |
||
+ | } |
||
− | To jest pierwsza linia. |
||
+ | return 0; |
||
− | Ta druga. |
||
+ | } |
||
− | A ta trzecia i zawiera taba,	tutaj. |
||
+ | </source> |
||
− | A ta	aż	dwa! |
||
− | To ostatnia linia. |
||
− | To jest drugi plik. |
||
− | Ma tylko 2 linie. |
||
− | </terminal> |
||
+ | Wyjście programu, po umieszczeniu tekstu w pliku <code>program.c</code>, wykonaniu trzech poleceń i wysłaniu po tym signału <code>SIGUSR1</code> dowolnym sposobem: |
||
− | === Przykład 3 - wypisanie treści pliku z numerowaniem wsystkich linii === |
||
− | Wywołanie <code>cat -n plik.txt</code> w przykładowym katalogu: |
||
<terminal> |
<terminal> |
||
+ | $ gcc program.c -o program |
||
− | $ cat -n plik.txt |
||
+ | $ chmod +x program |
||
− | 1 To jest pierwsza linia. |
||
+ | $ ./program |
||
− | 2 Ta druga. |
||
+ | Mam SIGUSR1. |
||
− | 3 A ta trzecia i zawiera taba,	tutaj. |
||
+ | Kończę pracę... |
||
− | 4 A ta	aż	dwa! |
||
− | 5 To ostatnia linia. |
||
</terminal> |
</terminal> |
||
+ | [[Kategoria:Komunikacja międzyprocesowa]] |
||
− | |||
− | === Przykład 4 - połączenie dwóch plików w jeden plik === |
||
− | Wywołanie <code>cat plik.txt drugi.txt > nowy.txt</code> w przykładowym katalogu spowoduje skopiowanie zawartości <code>plik.txt</code> i <code>drugi.txt</code> do nowego pliku o nazwie <code>nowy.txt</code>. |
||
− | |||
− | {{polecenia}} |
Wersja z 09:04, 6 wrz 2014
Sygnały – jeden z podstawowych i sposobów komunikacji międzyprocesowej w systemach uniksowych, w tym również w Linuksie.
Sygnałami są po prostu liczby określone całkowite. Jeśli jakiś proces otrzyma sygnał, jądro systemu zatrzyma na chwilę jego dotychczasowe działanie i sprawdzi, czy posiada on kod obsługujący dany sygnał. Jeśli tak - uruchomi go, w przeciwnym wypadku - kontynuuje normalne wykonywanie procesu.
Wysyłanie sygnałów
Z poziomu poleceń terminala
Do wysyłania procesów z poziomu konsoli służy polecenie kill
. Jej użycie ma postać
<terminal>
$ kill [przełączniki] <PID> ...
</terminal>
Jeśli nie podane zostaną żadne przełączniki zostanie wysłany sygnał SIGTERM
. Aby wysłać inny sygnał, wystarczy podać go poprzedzonego myślnikiem (-
). Przykładowo, wysłanie sygnału SIGUSR1
o wartości 10 do procesu o numerze 1234, wygląda tak:
<terminal>
$ kill -10 1234
</terminal>
Z poziomu programu
Wysłanie sygnału z poziomu programu jest możliwe dzięki wywołaniu systemowemu kill()
. Jako pierwszy parametr pobiera ono sygnał, który ma zostać wysłany (w przypadku języka C można posłużyć się makrami zdefiniowanymi w pliku nagłówkowym <signal.h>
), a jako drugi - PID procesu, który ma zostać zabity. Umożliwia zabicie tylko jednego procesu naraz. W przypadku powodzenia zwraca 0, w przeciwnym wypadku - -1. Użycie tego wywołania (w C) polegające na wysłaniu SIGUSR1
do procesu o numerze 1234, wygląda tak:
kill(10, 1234);
lub, by użyciu makr z nazwami (wymaga załączenia <signal.h>
):
kill(SIGUSR1, 1234);
Obsługa sygnałów
Za obsługę sygnałów odpowiada wywołanie systemowe signal()
. Jako pierwszy argument przyjmuje ona sygnał numer sygnału, a jako drugi - wskaźnik do funkcji, która ma odpowiadać za obsługę tego sygnału. W momencie wywołania do owej funkcji przekazany zostanie argument w postaci numeru sygnału (umożliwia to używanie wspólnej funkcji dla wielu sygnałów).
Przykładowy program
Poniższy program napisany w C po uruchomieniu czeka w nieskończoność, aż otrzyma sygnał SIGUSR1
. Po jego otrzymaniu wyświetli odpowiednią informację i zakończy działanie.
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
void funkcja_obslugujaca_sigusr1(int numer) {
puts("Mam SIGUSR1.");
puts("Kończę pracę...");
exit(0);
}
int main(void) {
signal(SIGUSR1, funkcja_obslugujaca_sigusr1);
while (1) {
sleep(3600);
}
return 0;
}
Wyjście programu, po umieszczeniu tekstu w pliku program.c
, wykonaniu trzech poleceń i wysłaniu po tym signału SIGUSR1
dowolnym sposobem:
<terminal>
$ gcc program.c -o program
$ chmod +x program
$ ./program
Mam SIGUSR1.
Kończę pracę...
</terminal>