getrlimit(2) System Calls Manual getrlimit(2) NAZWA getrlimit, setrlimit, prlimit - pobiera/ustawia limity zasobow BIBLIOTEKA Standardowa biblioteka C (libc, -lc) SKLADNIA #include int getrlimit(int resource, struct rlimit *rlim); int setrlimit(int resource, const struct rlimit *rlim); int prlimit(pid_t pid, int resource, const struct rlimit *_Nullable new_limit, struct rlimit *_Nullable old_limit); struct rlimit { rlim_t rlim_cur; /* Soft limit */ rlim_t rlim_max; /* Hard limit (ceiling for rlim_cur) */ }; typedef /* ... */ rlim_t; /* Unsigned integer type */ Wymagane ustawienia makr biblioteki glibc (patrz feature_test_macros(7)): prlimit(): _GNU_SOURCE OPIS The getrlimit() and setrlimit() system calls get and set resource limits. Each resource has an associated soft and hard limit, as defined by the rlimit structure. Ograniczenie miekkie jest wartoscia odpowiedniego zasobu wymuszona przez jadro. Ograniczenie sztywne dziala jako gorna granica dla ograniczenia miekkiego: proces nieuprzywilejowany moze sobie ustawic ograniczenie miekkie tylko w zakresie od 0 do ograniczenia sztywnego oraz (nieodwracalnie) obnizyc swoje ograniczenie sztywne. Proces uprzywilejowany (w Linuksie: proces z przywilejem CAP_SYS_RESOURCE (ang. capability) w swojej pierwotnej przestrzeni nazw uzytkownika) moze dowolnie zmieniac kazda z wartosci ograniczenia. Wartosc RLIM_INFINITY okresla brak ograniczenia dla zasobu (zarowno w strukturze zwracanej przez getrlimit(), jak i w strukturze przekazywanej do setrlimit()). Argument resource musi byc jednym z: RLIMIT_AS Jest to maksymalny rozmiar pamieci wirtualnej procesu (przestrzeni adresowej). Limit jest okreslony w bajtach i zaokraglony w dol, do systemowego rozmiaru strony. Limit dotyczy wywolan do brk(2), mmap(2) i mremap(2), ktore po jego przekroczeniu zawioda z bledem ENOMEM. Dodatkowo, zawiedzie automatyczne rozszerzenie stosu (i wygeneruje sygnal SIGSEGV zabijajacy proces, jesli za pomoca sigaltstack(2) nie stal sie dostepny alternatywny stos). Ze wzgledu na to, ze wartosc ta ma typ long, na komputerach z 32-bitowym long limit ten wynosi co najwyzej 2 GiB lub zasob ten jest nieograniczony. RLIMIT_CORE Maksymalny rozmiar pliku core (zob. core(5)) w bajtach, ktory moze zrzucic proces. Wartosc 0 oznacza, ze pliki zrzutu nie sa tworzone. Gdy wartosc jest niezerowa, wieksze zrzuty sa przycinane do wskazanego rozmiaru. RLIMIT_CPU Limit, w sekundach, czasu procesora (CPU), jaki moze uzyc proces. Gdy proces osiaga swoje ograniczenie miekkie, jest do niego wysylany sygnal SIGXCPU. Domyslna reakcja na ten sygnal jest przerwanie procesu. Jednakze, sygnal moze zostac przechwycony i procedura obslugi moze przekazac sterowanie do programu glownego. Jesli proces nadal bedzie uzywac zasoby procesora, bedzie do niego co sekunde wysylany sygnal SIGXCPU az do osiagniecia ograniczenia sztywnego, kiedy to wysylany jest sygnal SIGKILL. (Ostatni punkt opisuje zachowanie Linuksa. W zaleznosci od implementacji procesy kontynuujace uzywanie zasobow procesora po osiagnieciu ograniczenia miekkiego sa roznie traktowane. Aplikacje przenosne, ktore maja potrzebe przechwycenia tego sygnalu, powinny zakonczyc sie w sposob kontrolowany w chwili otrzymaniu pierwszego SIGXCPU.) RLIMIT_DATA Maksymalny rozmiar segmentu danych procesu (dane zainicjowane, dane niezainicjowane i sterta). Limit jest podawany w bajtach i jest zaokraglany w dol, do systemowego rozmiaru strony. Ograniczenie to wplywa na wywolania brk(2), sbrk(2) i (od Linuksa 4.7) mmap(2), ktore koncza sie niepomyslnie, zglaszajac blad ENOMEM w momencie natrafienia na miekkie ograniczenie tego zasobu. RLIMIT_FSIZE Maksymalny rozmiar plikow w bajtach, jakie moze utworzyc dany proces. Proba rozszerzenia pliku ponad to ograniczenie konczy sie otrzymaniem sygnalu SIGXFSZ. Domyslnie, sygnal ten konczy dzialanie procesu, ale proces moze go przechwycic. Wowczas odpowiednia funkcja systemowa (np. write(2), truncate(2)) konczy sie bledem EFBIG. RLIMIT_LOCKS (Linux 2.4.0 do Linuksa 2.4.24) Ograniczenie lacznej liczby blokad flock(2) i dzierzaw fcntl(2), ktore moze ustanowic proces. RLIMIT_MEMLOCK Maksymalna liczba bajtow pamieci, ktore moga byc zablokowane w RAM. Limit jest w praktyce zaokraglany w dol do najblizszej wielokrotnosci systemowego rozmiaru strony. Limit dotyczy mlock(2), mlockall(2) oraz operacji MAP_LOCKED mmap(2). Od Linuksa 2.6.9, limit dotyczy rowniez operacji SHM_LOCK shmctl(2), gdzie ustawia maksymalna sume bajtow segmentow pamieci dzielonej (zob. shmget(2)), ktore moga byc zablokowane przez rzeczywisty identyfikator uzytkownika procesu wywolujacego. Blokady SHM_LOCK shmctl(2) sa liczone oddzielnie od blokad pamieci na proces, ustanowionych przez mlock(2), mlockall(2) i MAP_LOCKED mmap(2); proces moze zablokowac bajty do tego limitu w kazdej z tych dwoch kategorii. Przed Linuksem 2.6.9, limit ten kontrolowal wielkosc pamieci, ktora mogla byc zablokowana przez proces uprzywilejowany. Od Linuksa 2.6.9, na wielkosc pamieci, jaka moze byc zablokowana przez proces uprzywilejowany nie sa nakladane limity, a opisywany limit dotyczy w zamian procesow nieuprzywilejowanych. RLIMIT_MSGQUEUE (od Linuksa 2.6.8) Limit liczby bajtow, ktore moga byc przydzielone kolejkom komunikatow POSIX dla rzeczywistego identyfikatora uzytkownika procesu wywolujacego. Limit ten jest wymuszony na mq_open(3). Kazda kolejka komunikatow, ktora tworzy uzytkownika wlicza sie do tego limitu (do momentu jej usuniecia) zgodnie ze wzorem: Od Linuksa 3.5: bytes = attr.mq_maxmsg * sizeof(struct msg_msg) + MIN(attr.mq_maxmsg, MQ_PRIO_MAX) * sizeof(struct posix_msg_tree_node)+ /* Do narzutu */ attr.mq_maxmsg * attr.mq_msgsize; /* Do danych komunikatow */ Linux 3.4 i wczesniejsze: bytes = attr.mq_maxmsg * sizeof(struct msg_msg *) + /* Do narzutu */ attr.mq_maxmsg * attr.mq_msgsize; /* Do danych komunikatow */ gdzie attr jest struktura mq_attr okreslona jako czwarty argument do mq_open(3), a struktury msg_msg i posix_msg_tree_node sa wewnetrznymi strukturami jadra. Skladowa ,,narzutu" we wzorze bierze pod uwage bajty narzutu wymagane przez implementacje i zapewnia, ze uzytkownik nie moze utworzyc nieskonczonej liczby komunikatow o zerowej dlugosci (takie komunikaty wciaz zajmuja nieco pamieci systemowej ze wzgledu na narzut ksiegowania). RLIMIT_NICE (od Linuksa 2.6.12, lecz zob. USTERKI ponizej) Okresla gorna granice, do ktorej mozna zwiekszyc wartosc nice procesu za pomoca setpriority(2) lub nice(2). Rzeczywista gorna granica jest obliczana jako 20 - rlim_cur. Uzyteczny zakres tego limitu wynosi zatem od 1 (co odpowiada wartosci nice 19) do 40 (co odpowiada wartosci nice -20). Ten nietypowy zakres byl konieczny, poniewaz liczby ujemne nie moga stanowic wartosci limitow zasobow, gdyz zwykle maja specjalne znaczenie. Na przyklad RLIM_INFINITY jest zwykle rownowazne -1. Wiecej szczegolow na temat wartosci nice mozna znalezc w podreczniku sched(7). RLIMIT_NOFILE Okresla wartosc o jeden wieksza niz maksymalna liczba deskryptorow plikow, ktore dany proces moze otworzyc. Proby (open(), pipe(), dup() itd.) przekroczenia tego limitu daja blad EMFILE (historycznie limit ten nosil nazwe RLIMIT_OFILE na BSD). Od Linuksa 4.5, limit ten definiuje rowniez maksymalna liczbe deskryptorow pliku, jakie proces nieuprzywilejowany (bez przywileju CAP_SYS_RESOURCE (ang. capability)) moze miec ,,w locie" do innych procesow, przy przekazywaniu za pomoca gniazd domeny Uniksa. Limit ten dotyczy wywolania systemowego sendmsg(2). Wiecej szczegolow w podreczniku unix(7). RLIMIT_NPROC Limit liczby istniejacych procesow (lub, precyzyjniej w Linuksie, watkow) dla rzeczywistego identyfikatora uzytkownika procesu wywolujacego. Jesli liczba biezacych procesow, bedacych wlasnoscia rzeczywistego identyfikatora uzytkownika tego procesu, jest wieksza lub rowna limitowi, fork() zawiedzie z bledem EAGAIN. Limit RLIMIT_NPROC nie jest wymuszany na procesach z przywilejem CAP_SYS_ADMIN lub CAP_SYS_RESOURCE (ang. capability) i procesach z rzeczywistym identyfikatorem uzytkownika rownym 0. RLIMIT_RSS Limit (w bajtach) rezydentnych stron procesu (liczba stron pamieci wirtualnej pozostajacych w RAM). Ograniczenie to dziala tylko w Linuksie 2.4.x, gdzie x < 30, i dotyczy jedynie wywolan madvise(2) z uzyciem MADV_WILLNEED. RLIMIT_RTPRIO (od Linuksa 2.6.12, lecz zob. USTERKI) Gorna granica, jaka mozna ustawic dla priorytetu czasu rzeczywistego, dla danego procesu, za pomoca sched_setscheduler(2) i sched_setparam(2). Wiecej informacji o politykach szeregowania zadan czasu rzeczywistego opisano w podreczniku sched(7). RLIMIT_RTTIME (od Linuksa 2.6.25) Limit (w mikrosekundach) czasu procesora, jaki proces korzystajacy z szeregowania zadan czasu rzeczywistego moze uzyc, bez czynienia blokujacego wywolania systemowego. Do celu tego limitu, za kazdym razem, gdy proces tworzy blokujace wywolanie systemowe, licznik uzytego czasu procesora jest resetowany do zera. Licznik czasu procesora nie jest resetowany, jesli proces kontynuuje probe uzycia procesora, lecz jest wywlaszczony, przydzielona mu jednostka czasu wyczerpala sie lub wywola sched_yield(2). Po osiagnieciu limitu miekkiego, do procesu wysylany jest sygnal SIGXCPU. Jesli proces go przechwyci lub zignoruje i bedzie kontynuowal uzywanie czasu procesora, sygnal SIGXCPU bedzie generowany co sekunde, do momentu osiagniecia limitu sztywnego, gdy proces otrzyma sygnal SIGKILL. Limit ten ma na celu zapobiegniecie zablokowania systemu przez zbiegle procesy czasu rzeczywistego. Wiecej informacji o politykach szeregowania zadan czasu rzeczywistego opisano w podreczniku sched(7). RLIMIT_SIGPENDING (od Linuksa 2.6.8) Limit liczby sygnalow, jakie moga byc zakolejkowane dla rzeczywistego identyfikatora uzytkownika procesu wywolujacego. Do celu sprawdzania tego limitu licza sie sygnaly zwykle i czasu rzeczywistego. Limit jest jednak wymuszany jedynie dla sigqueue(3); mozna zawsze skorzystac z kill(2), aby zakolejkowac po jednym z kazdego sygnalu, ktory nie wystepuje w kolejce do procesu. RLIMIT_STACK Maksymalny rozmiar stosu procesu w bajtach. W chwili osiagniecia tego ograniczenia, generowany jest sygnal SIGSEGV. W celu obsluzenia tego sygnalu proces musi zalozyc alternatywny stos dla sygnalow (sigaltstack(2)). Od Linuksa 2.6.23, limit ten okresla rowniez wielkosc przestrzeni uzywanej dla argumentow wiersza polecenia oraz zmiennych srodowiskowych procesu; wiecej szczegolow w podreczniku execve(2). prlimit() Typowo linuksowe wywolanie systemowe prlimit() laczy i rozszerza funkcjonalnosc setrlimit() i getrlimit(). Mozna go uzywac do ustawienia i pobrania limitow zasobow dowolnego procesu. Argument resource ma takie samo znaczenie jak w przypadku setrlimit() i getrlimit(). Jesli argument new_limit nie wynosi NULL, to struktura rlimit, na ktora on wskazuje, jest uzywana do ustawienia nowych wartosci limitow miekkich i sztywnych resource. Jesli argument old_limit nie wynosi NULL, to pomyslne wywolanie prlimit() umieszcza poprzednie limity miekkie i sztywne resource w strukturze rlimit, na ktora wskazuje old_limit. Argument pid okresla identyfikator procesu, na ktorym wywolanie ma operowac. Jesli pid wynosi 0, to wywolanie stosuje sie do procesu wywolujacego. Aby ustawic lub pobrac zasoby procesu innego niz wlasny, wywolujacy musi miec przywilej CAP_SYS_RESOURCE (ang. capability) w przestrzeni nazw uzytkownika procesu, ktorego limity zasobow sa zmieniane lub identyfikatory: rzeczywisty, efektywny i zapisany suid procesu docelowego musza odpowiadac identyfikatorowi rzeczywistemu procesu wywolujacego oraz identyfikatory: rzeczywisty, efektywny i zapisany suid procesu docelowego musza odpowiadac rzeczywistemu identyfikatorowi grupy wywolujacego. WARTOSC ZWRACANA W przypadku powodzenia, te wywolania zwracaja 0. W razie wystapienia bledu zwracane jest -1 i ustawiane errno, wskazujac blad. BLEDY EFAULT Argument wskaznika wskazuje na polozenie poza dostepna przestrzen adresowa. EINVAL WArtosc okreslona w resource nie jest prawidlowa; albo -- w przypadku setrlimit() lub prlimit(): rlim->rlim_cur byl wiekszy niz rlim->rlim_max. EPERM Proces nieuprzywilejowany probowal zwiekszyc limit sztywny; do dokonania tego konieczny jest przywilej CAP_SYS_RESOURCE (ang. capability). EPERM Wywolujacy probowal zwiekszyc limit sztywny RLIMIT_NOFILE ponad wartosc maksymalna okreslona w /proc/sys/fs/nr_open (zob. proc(5)) EPERM (prlimit()) Proces wywolujacy nie mial uprawnien do ustawiania limitow dla procesu podanego w pid. ESRCH Nie udalo sie znalezc procesu o identyfikatorze podanym w pid. ATRYBUTY Informacje o pojeciach uzywanych w tym rozdziale mozna znalezc w podreczniku attributes(7). +---------------------------+--------------------------+---------------+ |Interfejs | Atrybut | Wartosc | +---------------------------+--------------------------+---------------+ |getrlimit(), setrlimit(), | Bezpieczenstwo watkowe | MT-bezpieczne | |prlimit() | | | +---------------------------+--------------------------+---------------+ STANDARDY getrlimit() setrlimit() POSIX.1-2008. prlimit() Linux. RLIMIT_MEMLOCK i RLIMIT_NPROC pochodza z BSD i nie sa okreslone w POSIX.1; sa obecne w systemach BSD i Linux, ale z roznymi implementacjami. RLIMIT_RSS pochodzi z BSD i nie jest okreslone w POSIX.1; jest jednak obecne w wiekszosci implementacji. RLIMIT_MSGQUEUE, RLIMIT_NICE, RLIMIT_RTPRIO, RLIMIT_RTTIME i RLIMIT_SIGPENDING sa typowo linuksowe. HISTORIA getrlimit() setrlimit() POSIX.1-2001, SVr4, 4.3BSD. prlimit() Linux 2.6.36, glibc 2.13. UWAGI Proces potomny utworzony za pomoca fork(2) dziedziczy limity zasobow swojego procesu macierzystego. Limity zasobow sa zachowywane przez execve(2). Limity zasobow sa atrybutami przypisanymi procesowi i sa dzielone przez wszystkie watki procesu. Zmniejszenie miekkiego limitu zasobu ponizej jego aktualnego uzycia przez proces powiedzie sie (lecz zapobiegnie dalszemu zwiekszeniu uzycia zasobu przez proces). Mozna ustawic limity zasobow powloki za pomoca wbudowanego polecenia ulimit (limit w csh(1)). Limity zasobow powloki sa dziedziczone przez procesy tworzone do wykonywania polecen powloki. Od Linuksa 2.6.24, limity zasobow dowolnego procesu mozna sprawdzic za pomoca /proc/pid/limits; zob. proc(5). Dawne systemy udostepnialy funkcje vlimit() o podobnym zastosowaniu do setrlimit(). Ze wzgledu na kompatybilnosc wsteczna, glibc rowniez udostepnia vlimit(). Wszystkie nowe aplikacje powinny uzywac wylacznie setrlimit(). Roznice ABI biblioteki C/jadra Od glibc 2.13, funkcje opakowujace getrlimit() i setrlimit() z glibc nie przywoluja juz odpowiadajacych im wywolan systemowych, lecz uzywaja prlimit(), ze wzgledow opisanych w USTERKACH. Nazwa opakowujacej funkcji z glibc jest prlimit(); nazwa wywolania systemowego jest prlimit64(). USTERKI W starszych jadrach Linux, sygnaly SIGXCPU i SIGKILL dostarczane, gdy proces napotkal miekkie i sztywne limity RLIMIT_CPU, dostarczano jedna sekunde (procesorowa) pozniej, niz powinno to nastapic. Poprawiono to w Linuksie 2.6.8. W jadrach Linux 2.6.x wczesniejszych niz Linux 2.6.17, limit RLIMIT_CPU wynoszacy 0 byl nieprawidlowo traktowany jako ,,brak limitu" (jak RLIM_INFINITY). Od Linuksa 2.6.17, ustawienie limitu 0 jest stosowane, ale faktycznie skutkuje limitem 1 sekundy. Blad jadra powodowal, ze RLIMIT_RTPRIO nie dzialal w Linuksie 2.6.12; problem poprawiono w Linuksie 2.6.13. W Linuksie 2.6.12, istniala niezgodnosc o jeden pomiedzy zakresami priorytetow zwracanymi przez getpriority(2) i RLIMIT_NICE. Dawalo te efekt, ze faktyczna gorna granica wartosci nice byla obliczana jako 19 - rlim_cur. Poprawiono to w Linuksie 2.6.13. Od Linuksa 2.6.12, jesli proces osiaga swoj miekki limit RLIMIT_CPU i posiada procedure obslugi SIGXCPU, to, oprocz przywolania procedury obslugi, jadro zwieksza miekki limit o jedna sekunde. Zachowanie to powtarza sie, jesli proces kontynuuje uzywanie czasu procesora, az do osiagniecia limitu sztywnego, gdy proces jest zabijany. Inne implementacje nie zmieniaja miekkiego limitu RLIMIT_CPU w ten sposob, a zachowanie Linuksa prawdopodobnie nie jest zgodne ze standardami; przenosne aplikacje powinny unikac polegania na tym typowo linuksowym zachowaniu. Typowo linuksowy limit RLIMIT_RTTIME dziala w ten sam sposob, gdy osiagnie sie miekki limit. Jadra przed Linuksem 2.4.22 nie diagnozuja bledu EINVAL w przypadku setrlimit(), gdy rlim->rlim_cur bylo wieksze niz rlim->rlim_max. Ze wzgledu na kompatybilnosc, Linux nie zwraca bledu, gdy proba ustawienia RLIMIT_CPU zawodzi. Reprezentacja ,,duzych" wartosci limitu zasobu na platformach 32-bitowych Funkcje opakowujace getrlimit() i setrlimit() z glibc uzywaja 64-bitowego typu danych rlim_t, nawet na platformach 32-bitowych. Jednakze typ danych rlim_t uzywany w wywolaniach systemowych getrlimit() i setrlimit() jest (32-bitowym) unsigned long. Co wiecej, w Linuksie jadro reprezentuje limit zasobow na platformach 32-bitowych jako unsigned long. Jednak 32-bitowy typ danych nie jest wystarczajaco szeroki. Najtrudniejsza sytuacja wystepuje odnosnie limitu RLIMIT_FSIZE okreslajacego maksymalny rozmiar, do jakiego moze zostac zwiekszony plik: aby byc uzytecznym, limit ten musi byc reprezentowany przez typ, ktory jest tak szeroki, jak typ uzywany do reprezentowania przesuniec pliku tj. tak szeroki jak 64-bitowe off_t (zakladajac, ze program skompilowano z _FILE_OFFSET_BITS=64). Aby obejsc to ograniczenie, w przypadku gdy program probowal ustawic limit zasobow na wartosc wieksza niz moze byc reprezentowana w 32-bitowym unsigned long, funkcja opakowujaca setrlimit() z glibc po cichu konwertowala wartosc limitu na RLIM_INFINITY. Innymi slowy, zadany limit zasobow byl po cichu ignorowany. OD glibc 2.13, glibc obchodzi to ograniczenie wywolan systemowych getrlimit() i setrlimit() implementujac setrlimit() i getrlimit() jako funkcje opakowujace wywolujace prlimit(). PRZYKLADY Ponizszy program demonstruje uzycie prlimit(). #define _GNU_SOURCE #define _FILE_OFFSET_BITS 64 #include #include #include #include #include #include int main(int argc, char *argv[]) { pid_t pid; struct rlimit old, new; struct rlimit *newp; if (!(argc == 2 || argc == 4)) { fprintf(stderr, "Usage: %s [ " "]\n", argv[0]); exit(EXIT_FAILURE); } pid = atoi(argv[1]); /* PID of target process */ newp = NULL; if (argc == 4) { new.rlim_cur = atoi(argv[2]); new.rlim_max = atoi(argv[3]); newp = &new; } /* Set CPU time limit of target process; retrieve and display previous limit */ if (prlimit(pid, RLIMIT_CPU, newp, &old) == -1) err(EXIT_FAILURE, "prlimit-1"); printf("Previous limits: soft=%jd; hard=%jd\n", (intmax_t) old.rlim_cur, (intmax_t) old.rlim_max); /* Retrieve and display new CPU time limit */ if (prlimit(pid, RLIMIT_CPU, NULL, &old) == -1) err(EXIT_FAILURE, "prlimit-2"); printf("New limits: soft=%jd; hard=%jd\n", (intmax_t) old.rlim_cur, (intmax_t) old.rlim_max); exit(EXIT_SUCCESS); } ZOBACZ TAKZE prlimit(1), dup(2), fcntl(2), fork(2), getrusage(2), mlock(2), mmap(2), open(2), quotactl(2), sbrk(2), shmctl(2), malloc(3), sigqueue(3), ulimit(3), core(5), capabilities(7), cgroups(7), credentials(7), signal(7) TLUMACZENIE Autorami polskiego tlumaczenia niniejszej strony podrecznika sa: Przemek Borys , Andrzej Krzysztofowicz i Michal Kulach Niniejsze tlumaczenie jest wolna dokumentacja. Blizsze informacje o warunkach licencji mozna uzyskac zapoznajac sie z GNU General Public License w wersji 3 lub nowszej. Nie przyjmuje sie ZADNEJ ODPOWIEDZIALNOSCI. Bledy w tlumaczeniu strony podrecznika prosimy zglaszac na adres listy dyskusyjnej . Linux man-pages 6.9.1 17 czerwca 2024 r. getrlimit(2)