| core(5) | File Formats Manual | core(5) |
core - plik zrzutu pamięci
Dla pewnych sygnałów domyślną akcją procesu jest zakończenie działania i utworzenie pliku zrzutu pamięci (core), czyli pliku zawierającego obraz pamięci procesu w czasie, gdy został on zakończony. Dowolny debugger (np. gdb(1)) może użyć tego obrazu do zbadania stanu programu w czasie jego zakończenia. Listę sygnałów powodujących utworzenie pliku core przez proces można znaleźć w signal(7).
Proces może ustawić miękki limit zasobów RLIMIT_CORE, aby ograniczyć maksymalny rozmiar pliku, który zostanie utworzony po otrzymaniu sygnału powodującego zrzut pamięci; szczegółowe informacje można znaleźć w getrlimit(2).
W następujących wypadkach plik zrzutu pamięci nie będzie utworzony:
Dodatkowo zrzut pamięci może nie zawierać części przestrzeni adresowej procesu jeśli użyto flagi MADV_DONTDUMP madvise(2).
W systemach korzystającym z systemd(1) jako init, pliki zrzutu pamięci mogą być w zamian umieszczane w położeniu wskazanym przez systemd(1). Więcej szczegółów poniżej.
Domyślnie plik zrzutu pamięci nazywa się core, jednakże w pliku /proc/sys/kernel/core_pattern (od wersji 2.6 i 2.4.21 Linuksa) można zdefiniować szablon, który będzie użyty do nazywania plików zrzutu pamięci. Szablon ten może zawierać specjalne znaczniki zaczynające się od „%”, które podczas tworzenia pliku zrzutu będą zastąpione następującymi wartościami:
Jeśli szablon kończy się pojedynczym znakiem %, to znak ten zostanie usunięty z nazwy pliku zrzutu. Podobnie zostaną usunięte wszelkie kombinacje % ze znakami innymi niż te, wymienione powyżej. Wszystkie inne znaki szablonu staną się częścią nazwy pliku zrzutu. Szablon może zawierać znaki „/”, które są interpretowane jako separatory nazw katalogów. Maksymalna długość wygenerowanej nazwy pliku wynosi 128 bajtów (64 bajty w wersjach wcześniejszych niż Linux 2.6.19). Domyślną wartością jest „core”. W celu zachowania wstecznej zgodności, jeśli /proc/sys/kernel/core_pattern nie zawiera %p, a /proc/sys/kernel/core_uses_pid (patrz niżej) ma niezerową wartość, to .PID będzie dołączony do nazwy pliku zrzutu.
Ścieżki są interpretowane zgodnie z ustawieniami aktywnymi dla załamującego się procesu. Oznacza to: przestrzeń nazw montowania (zob. mount_namespaces(7)), jego bieżący katalog roboczy (odnaleziony za pomocą getcwd(2)) oraz jego katalog główny (zob. chroot(2)).
Od Linuksa 2.4, Linux dostarcza również bardziej prymitywną metodę kontrolowania nazwy pliku zrzutu pamięci. Gdy plik /proc/sys/kernel/core_uses_pid zawiera wartość 0, plik zrzutu pamięci ma po prostu nazwę core. Gdy plik ten zawiera wartość niezerową, plik zrzutu pamięci będzie zawierał w swojej nazwie ID procesu, w postaci core.PID.
Od Linuksa 3.6 jeśli /proc/sys/fs/suid_dumpable ustawiono na 2 („suidsafe”) to wzorzec musi być albo ścieżką absolutną (zaczynającą się znakiem „/”) lub potokiem, zgodnie z poniższą definicją.
Od wersji Linuksa 2.6.19, Linux obsługuje alternatywną składnię pliku /proc/sys/kernel/core_pattern. Jeśli pierwszym znakiem pliki jest symbol potoku (|), to wszystko, co po nim występuje, jest interpretowane jako wiersz polecenia dla programu w przestrzeni użytkownika (lub skryptu), który ma być wykonany.
Od Linuksa 5.3.0, szablon potoku jest dzielony na spacjach na listę argumentów przed rozwinięciem parametrów szablonu. We wcześniejszych jądrach parametry szablonu były najpierw rozwijane, a wynikowy łańcuch był dzielony na spacjach na listę argumentów. Oznacza to, że we wcześniejszych jądrach, nazwy plików wykonywalnych dodawane za pomocą parametrów szablonu %e i %E mogły ulec podzieleniu na wiele argumentów. Procedura obsługi zrzutu pamięci musi zatem umieszczać nazwy plików wykonywalnych jako ostatni argument i upewnić się, że połączy wszystkie składowe nazwy pliku wykonywalnego używającego spacji. Nazwy plików wykonywalnych zawierające wiele spacji nie były prawidłowo reprezentowane we wcześniejszych jądrach, co oznacza, że procedura obsługi zrzutu pamięci musi używać mechanizmów do odnalezienia nazwy pliku wykonywalnego.
Zamiast zostać zapisanym na dysku, zrzut pamięci jest przekazywany na standardowe wejście programu. Proszę zauważyć, że:
Przy zbieraniu zrzutów pamięci za pomocą potoku do program w przestrzeni użytkownika, może okazać się przydatne zbieranie danych o załamującym się procesie z katalogu /proc/pid procesu. Aby uczynić to bezpiecznie, jądro musi zaczekać na wyjście przez program zbierający zrzut pamięci, aby nie usuwać przedwcześnie plików /proc/pid załamującego się procesu. Z drugiej jednak strony, daje to możliwość blokowania dorzynania (ang. reaping) załamanego procesu, przez niepoprawnie działający program zbierający, który może nigdy nie wyjść.
Od Linuksa 2.6.32, można użyć /proc/sys/kernel/core_pipe_limit do obrony przed taką ewentualnością. Wartość pliku definiuje, jak wiele współbieżnych załamujących się procesów można przekazać równolegle, potokiem, do programów w przestrzeni użytkownika. Po przekroczeniu tej wartości, załamujące się programy niemieszczące się w tej wartości są odnotowywane w dzienniku jądra, a ich zrzuty pamięci są pomijane.
Wartość 0 w tym pliku ma specjalne znaczenie. Oznacza, że równolegle może być przechwytywana nieograniczona liczba procesów, ale nie zajdzie żadne oczekiwanie (tj. program zbierający nie ma gwarancji dostępu do /proc/<załamujący-się-PID>). Domyślną wartością pliku jest 0.
Od Linuksa 2.6.23, można użyć specyficznego dla Linuksa pliku /proc/PID/coredump_filter do kontrolowania, które segmenty pamięci zostaną zapisane do pliku zrzutu pamięci, w przypadku gdy pamięć jest zrzucana przez proces o podanym identyfikatorze.
Wartość w tym pliku jest maską bitową typów mapowań pamięci (patrz mmap(2)). Jeśli bit jest ustawiony w masce, to odpowiadające mu mapowanie jest zapisywane w pliku, w przeciwnym wypadku - nie jest. Bity w masce mają następujące znaczenia:
Domyślnie ustawione są następujące bity: 0, 1, 4 (jeśli jest włączona opcja CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS konfiguracji jądra) oraz 5. Tę wartość domyślną można zmodyfikować przy rozruchu za pomocą opcji coredump_filter.
Wartość tego pliku jest wyświetlana szesnastkowo (z tego powodu domyślna wartość jest wyświetlana jako 33).
Strony wejścia/wyjścia mapowane w pamięci, takie jak bufor ramki, nigdy nie są zrzucane, a wirtualne strony DSO (vdso(7)) są zawsze zrzucane, niezależnie od wartości coredump_filter.
Proces-dziecko utworzony przez fork(2) dziedziczy wartość coredump_filter od swojego rodzica; wartość ta jest także zachowywana podczas execve(2).
Może być użyteczne ustawienie coredump_filter w powłoce przed uruchomieniem programu, na przykład:
$ echo 0x7 > /proc/self/coredump_filter $ ./some_program
Plik istnieje, jeśli jądro zostało zbudowane z włączoną opcją konfiguracji CONFIG_ELF_CORE.
W systemach korzystających z init w postaci systemd(1), zrzuty pamięci mogą być umieszczane w położeniu określanym przez systemd(1). systemd(1) używa do tego funkcji core_pattern, która pozwala na przekazywanie potokiem zrzutów pamięci do programu. Można to zweryfikować, sprawdzając czy zrzuty pamięci są przekazywane potokiem do programu systemd-coredump(8):
$ cat /proc/sys/kernel/core_pattern |/usr/lib/systemd/systemd-coredump %P %u %g %s %t %c %e
W tym przypadku, zrzuty pamięci będą umieszczane w położeniu skonfigurowanym dla systemd-coredump(8), zwykle jako pliki skompresowane lz4(1), w katalogu /var/lib/systemd/coredump/. Można wypisać listę zarejestrowanych przez systemd-coredump(8) zrzutów pamięci za pomocą coredumpctl(1):
$ coredumpctl list | tail -5 Wed 2017-10-11 22:25:30 CEST 2748 1000 1000 3 present /usr/bin/sleep Thu 2017-10-12 06:29:10 CEST 2716 1000 1000 3 present /usr/bin/sleep Thu 2017-10-12 06:30:50 CEST 2767 1000 1000 3 present /usr/bin/sleep Thu 2017-10-12 06:37:40 CEST 2918 1000 1000 3 present /usr/bin/cat Thu 2017-10-12 08:13:07 CEST 2955 1000 1000 3 present /usr/bin/cat
Informacje pokazywane dla każdego zrzutu pamięci obejmują datę i czas zrzutu, identyfikatory: procesu, użytkownika i grupy zrzucającego procesu, numer sygnału powodującego zrzut i ścieżka do pliku wykonywalnego, który był uruchomiony przez zrzucany proces. Można podać do coredumpctl(1) wiele opcji, które pozwalają wskazać plik zrzutu pamięci, który ma być wyciągnięty z lokalizacji systemd(1) do określonego pliku. Na przykład, aby wydobyć zrzut pamięci dla procesu o PID 2955 pokazanego powyżej, do pliku nazwanego core w bieżącym katalogu można użyć polecenia:
$ coredumpctl dump 2955 -o core
Więcej szczegółów znajduje się w podręczniku systemowym coredumpctl(1).
Aby (na stałe) wyłączyć mechanizm systemd(1) archiwizujący zrzuty pamięci, przywracając bardziej tradycyjne zachowanie linuksowe, można przesłonić mechanizm systemd(1), za pomocą konstrukcji podobnej do poniżej:
# echo "kernel.core_pattern=core.%p" > \
/etc/sysctl.d/50-coredump.conf # /lib/systemd/systemd-sysctl
Można również tymczasowo (do następnego przeładowania systemu) zmienić ustawienie core_pattern poleceniem podobnym do poniższego (które powoduje włączenie do nazw zrzutu pamięci również nazwy pliku wykonywalnego i numer sygnału wyzwalające zrzut pamięci):
# sysctl -w kernel.core_pattern="%e-%s.core"
Aby uzyskać zrzut pamięci działającego procesu, można użyć polecenia gcore programu gdb(1).
W wersjach jądra Linux do 2.6.27 włącznie, jeżeli pamięć zrzuca proces wielowątkowy (albo - bardziej precyzyjnie - proces, który dzieli swą pamięć z innym procesem utworzonym z flagą CLONE_VM funkcji clone(2)), to identyfikator procesu zawsze będzie dołączony do nazwy pliku zrzutu, chyba że ów identyfikator procesu już występuje w nazwie pliku, ponieważ w pliku /proc/sys/kernel/core_pattern użyto specyfikatora p (Jest to szczególnie użyteczne podczas stosowania przestarzałej implementacji LinuxThreads, w której każdy wątek procesu ma inny PID).
Poniższy program pokazuje użycie składni potoku w pliku /proc/sys/kernel/core_pattern. Poniższa sesja powłoki demonstruje użycie tego programu (skompilowanego do pliku o nazwie core_pattern_pipe_test):
$ cc -o core_pattern_pipe_test core_pattern_pipe_test.c $ su Hasło: # echo "|$PWD/core_pattern_pipe_test %p UID=%u GID=%g sig=%s" > \ /proc/sys/kernel/core_pattern # exit $ sleep 100 ^\ # wpisz control+odwrotny ukośnik Quit (core dumped) $ cat core.info argc=5 argc[0]=</home/mtk/core_pattern_pipe_test> argc[1]=<20575> argc[2]=<UID=1000> argc[3]=<GID=100> argc[4]=<sig=3> Całkowita liczba bajtów pliku core: 282624
/* core_pattern_pipe_test.c */
#define _GNU_SOURCE
#include <sys/stat.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define BUF_SIZE 1024
int
main(int argc, char *argv[])
{
ssize_t nread, tot;
char buf[BUF_SIZE];
FILE *fp;
char cwd[PATH_MAX];
/* Zmienia bieżący katalog roboczy na katalog procesu
który generuje zrzut pamięci. */
snprintf(cwd, PATH_MAX, "/proc/%s/cwd", argv[1]);
chdir(cwd);
/* Zapisuje wyjście do pliku "core.info" w tym katalogu. */
fp = fopen("core.info", "w+");
if (fp == NULL)
exit(EXIT_FAILURE);
/* Wyświetla argumenty wiersza poleceń przekazane do programu
filtrującego "core_pattern". */
fprintf(fp, "argc=%d\n", argc);
for (size_t j = 0; j < argc; j++)
fprintf(fp, "argc[%zu]=<%s>\n", j, argv[j]);
/* Zlicza bajty na standardowym wejściu (daje rozmiar
zrzutu pamięci). */
tot = 0;
while ((nread = read(STDIN_FILENO, buf, BUF_SIZE)) > 0)
tot += nread;
fprintf(fp, "Całkowita liczba bajtów pliku core: %zd\n", tot);
fclose(fp);
exit(EXIT_SUCCESS);
}
bash(1), coredumpctl(1), gdb(1), getrlimit(2), mmap(2), prctl(2), sigaction(2), elf(5), proc(5), pthreads(7), signal(7), systemd-coredump(8)
Tłumaczenie niniejszej strony podręcznika: Robert Luberda <robert@debian.org> i Michał Kułach <michal.kulach@gmail.com>
Niniejsze tłumaczenie jest wolną dokumentacją. Bliższe informacje o warunkach licencji można uzyskać zapoznając się z GNU General Public License w wersji 3 lub nowszej. Nie przyjmuje się ŻADNEJ ODPOWIEDZIALNOŚCI.
Błędy w tłumaczeniu strony podręcznika prosimy zgłaszać na adres listy dyskusyjnej manpages-pl-list@lists.sourceforge.net.
| 15 czerwca 2024 r. | Linux man-pages 6.9.1 |