Linux Wiki
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>
$ cat [opcje] <plik> {{...}}
+
$ kill [przełączniki] <PID> {{...|identyfikatory wielu procesów}}
 
</terminal>
  +
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:
 
<terminal>
  +
$ 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łady ==
+
=== 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,&#9;tutaj.
 
A ta&#9;aż&#9;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ę...");
<terminal>
 
  +
exit(0);
$ cat plik.txt
 
  +
}
To jest pierwsza linia.
 
Ta druga.
 
A ta trzecia i zawiera taba,&#9;tutaj.
 
A ta&#9;aż&#9;dwa!
 
To ostatnia linia.
 
</terminal>
 
   
  +
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,&#9;tutaj.
 
  +
</source>
A ta&#9;aż&#9;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,&#9;tutaj.
 
  +
Kończę pracę...
4 A ta&#9;aż&#9;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>