• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Jak ustawić limit czasu odpalonej komendy w C++?

Object Storage Arubacloud
0 głosów
426 wizyt
pytanie zadane 30 kwietnia 2017 w C i C++ przez niezalogowany

Witam, chciałbym, odpalić pewną funkcję, ale dać limit, tak aby po np. 10 sekundach się wyłączyła. Słyszałem coś o: rlimit i ulimit.

Dodam, że korzystam z Linuxa.

Pozdrawiam

1 odpowiedź

+5 głosów
odpowiedź 30 kwietnia 2017 przez mokrowski Mędrzec (155,460 p.)
wybrane 2 maja 2017
 
Najlepsza

No i dobrze słyszałeś. Masz limit RLIMIT_CPU który podawany jest w sekundach działania procesu z przydzielonym czasem procesora. To oznacza że jeżeli proces jest zorientowany na I/O, sam czas pracy procesu może być dłuższy bo proces jest usypiany w trakcie reakcji np. dysku czy sieci. 

Masz 2 rodzaje limitów.

1. Twarde ustawia root i użytkownik nie może ich przekroczyć.

2. Miękkie gdzie użytkownik jest jedynie ostrzegany po osiągnięciu limitu.

Dla limitu RLIMIT_CPU, przy miękim proces otrzyma sygnał SIGXCPU a przy twardym ... SIGKILL :-/ Jak wiadomo po tym ostatnim .. kończy swój żywot. Jadnak SIGXCPU można obsłużyć. 

Dokumentacja:

man 2 setrlimit
$ bash
$ ulimit -aH
core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 12946
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 4096
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) unlimited
cpu time               (seconds, -t) unlimited
max user processes              (-u) 12946
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
$ ulimit -aS
core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 12946
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 12946
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
$ ulimit -St 3
$ ls -alR /
$ echo $?
152
$ kill -l
 1) SIGHUP     2) SIGINT     3) SIGQUIT     4) SIGILL     5) SIGTRAP
 6) SIGABRT     7) SIGBUS     8) SIGFPE     9) SIGKILL    10) SIGUSR1
11) SIGSEGV    12) SIGUSR2    13) SIGPIPE    14) SIGALRM    15) SIGTERM
16) SIGSTKFLT    17) SIGCHLD    18) SIGCONT    19) SIGSTOP    20) SIGTSTP
21) SIGTTIN    22) SIGTTOU    23) SIGURG    <strong>24) SIGXCPU</strong>    25) SIGXFSZ
26) SIGVTALRM    27) SIGPROF    28) SIGWINCH    29) SIGIO    30) SIGPWR
31) SIGSYS    34) SIGRTMIN    35) SIGRTMIN+1    36) SIGRTMIN+2    37) SIGRTMIN+3
38) SIGRTMIN+4    39) SIGRTMIN+5    40) SIGRTMIN+6    41) SIGRTMIN+7    42) SIGRTMIN+8
43) SIGRTMIN+9    44) SIGRTMIN+10    45) SIGRTMIN+11    46) SIGRTMIN+12    47) SIGRTMIN+13
48) SIGRTMIN+14    49) SIGRTMIN+15    50) SIGRTMAX-14    51) SIGRTMAX-13    52) SIGRTMAX-12
53) SIGRTMAX-11    54) SIGRTMAX-10    55) SIGRTMAX-9    56) SIGRTMAX-8    57) SIGRTMAX-7
58) SIGRTMAX-6    59) SIGRTMAX-5    60) SIGRTMAX-4    61) SIGRTMAX-3    62) SIGRTMAX-2
63) SIGRTMAX-1    64) SIGRTMAX   
$ exit

Po kolei dla komend (niestety nie potrafię ładnie pokolorować komend, są po prostu w kolejności wpisania czyli to co po $)

    bo limity są dziedziczone przez następne powłoki.

     limity twarde

     limity miękkie

    przestawienie miękkiego limitu czasu "na CPU" na 3 sek.

    listowanie wszystkich plików w systemie 

     wyświetlenie kodu powrotu programu i powodu jego zatrzymania. Program zakończył się błędem bo kod nie jest zerowy, skończył się otrzymaniem sygnału bo 128 + NR_SYGNAŁU  (tu 24 jak widzisz niżej).

     wyświetlenie nr sygnałów

    powrót do poprzedniej powłoki

W manualu masz przykład programu :-)

komentarz 1 maja 2017 przez niezalogowany

Dzięki, ale mam jeden problem. Znalazłem kod w dokumentacji:

       #define _GNU_SOURCE
       #define _FILE_OFFSET_BITS 64
       #include <stdio.h>
       #include <time.h>
       #include <stdlib.h>
       #include <unistd.h>
       #include <sys/resource.h>

       #define errExit(msg)                                do { perror(msg); exit(EXIT_FAILURE); \
                               } while (0)

       int
       main(int argc, char *argv[])
       {
           struct rlimit old, new;
           struct rlimit *newp;
           pid_t pid;

           if (!(argc == 2 || argc == 4)) {
               fprintf(stderr, "Usage: %s <pid> [<new-soft-limit> "
                       "<new-hard-limit>]\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)
               errExit("prlimit-1");
           printf("Previous limits: soft=%lld; hard=%lld\n",
                   (long long) old.rlim_cur, (long long) old.rlim_max);

           /* Retrieve and display new CPU time limit */

           if (prlimit(pid, RLIMIT_CPU, NULL, &old) == -1)
               errExit("prlimit-2");
           printf("New limits: soft=%lld; hard=%lld\n",
                   (long long) old.rlim_cur, (long long) old.rlim_max);

           exit(EXIT_FAILURE);
       }

Ten kod, jest dość rozbudowany, a co za tym idzie troszkę mało dla mnie zrozumiały. Czy nie dałoby się poprzez komendy system(), ustawić limity.

Chodzi mi o takie coś:

system("USTAWIENIE LIMITU");
int n = system("./z");
if(n==152)
{
    cout<<"LIMIT CZASU PRZEKROCZONY";
}

 

komentarz 1 maja 2017 przez mokrowski Mędrzec (155,460 p.)
edycja 1 maja 2017 przez mokrowski

No może nie przez sam system(...) tylko przez fork() (czyli powołanie procesu potomnego) i wysłanie sygnału. Tylko za chwilę znów zapytasz o limit np. pamięci lub ilości otwartych plików programu i.. znów wrócisz do limitów :-/ No ale jak chcesz tylko czas, to rozwiązanie (nie ukrywam) "prostackie", może wyglądać tak:

#include <iostream>
#include <thread>
#include <chrono>
#include <cstdlib>

#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <wait.h>

void childWork() {
    // Proces dziecka
    // XXX: Tu dla testów zwykły sleep ale docelowo progam.. 
    std::system("sleep 3");
    std::clog << "Zakończenie procesu dziecka." << std::endl;
}

int main() {
    pid_t childPid;
    if(!(childPid = fork())) {
        // Proces dziecka
        childWork();
    } else {
        // Proces rodzica
        // XXX: Jedną z poniższych odkomentuj dla testów
        //std::this_thread::sleep_for(std::chrono::seconds(1));
        std::this_thread::sleep_for(std::chrono::seconds(5));
        kill(childPid, SIGKILL);
        std::clog << "Wysłano sygnał do procesu dziecka." << std::endl;
        wait(NULL);
    }
}

 

komentarz 2 maja 2017 przez niezalogowany

Dzięki, mam jeszcze mały techniczny problem, pozmieniałem troszkę twój:

#include <iostream>
#include <thread>
#include <chrono>
#include <cstdlib>
 
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <wait.h>
 
using namespace std;
 
bool z = false;
 
void childWork() {
	
    system("sleep 3");
    z = true;
    cout<<"OK"<<endl;
}
 
int main() {
    pid_t childPid;
    if(!(childPid = fork())) {
        childWork();
    } else {
        this_thread::sleep_for(std::chrono::seconds(5));
        kill(childPid, SIGKILL);
        if(z==true)
        {
			cout<<"UDALO SIE!"<<endl;
		}
		else
		{
			cout<<"LIMIT"<<endl;
		}
        wait(NULL);
    }
}

Chciałem mieć w zmiennej czy wyrobił się program. Wyświetla się po 3 sekundach OK, a po 5 LIMIT. A powinno po 5 być UDAŁO SIĘ!

 

komentarz 2 maja 2017 przez mokrowski Mędrzec (155,460 p.)

Super.. :-/ a rozumiesz że to są oddzielne procesy? Tak więc nie będziesz współdzielił zmiennej z :-)

komentarz 2 maja 2017 przez niezalogowany
No dobra, a znasz może jakiś sposób, którym się uda?
komentarz 2 maja 2017 przez mokrowski Mędrzec (155,460 p.)
Oczywiście. Doczytaj jak funkcjonuje wai() z parametrem WNOHANG oraz jak działa kill() z sygnałem 0 (zero). To powinno Ci wystarczyć.
komentarz 3 maja 2017 przez niezalogowany
Ogarnąłem, ale mam jeszcze jedną prośbę. Chciałbym, aby kiedy się skończy program, przed limitem, to aby ten mój program już nie czekał aż minie limit. Mam nadzieję, że wiesz o co mi chodzi.
komentarz 3 maja 2017 przez mokrowski Mędrzec (155,460 p.)
No i wracasz (jak wykrakałem) do punktu wyjścia. Limity ustawione z użyciem setrlimit(..) ten problem by załatwiły. W tym "prostackim" rozwiązaniu nie jest to możliwe. Za każdym razem proces oczekujący (czyli główny dla tego programu) poczeka określony czas przed wysłaniem sygnału kill(...).
komentarz 7 maja 2017 przez niezalogowany
edycja 7 maja 2017

No ok, postanowiłem, spróbować, to zrobić. Skompilowałem ten kod przykładowy, i wywala mi:

g++ -Wall -o "z" "z.cpp" (w katalogu /home/kacper/Pulpit)
z.cpp:1:0: warning: "_GNU_SOURCE" redefined
 #define _GNU_SOURCE
<command-line>:0:0: note: this is the location of the previous definition
z.cpp: In function ‘int main(int, char**)’:
z.cpp:15:24: error: expected unqualified-id before ‘new’
     struct rlimit old, new;
                        ^~~
z.cpp:29:12: error: expected type-specifier before ‘.’ token
         new.rlim_cur = atoi(argv[2]);
            ^
z.cpp:30:12: error: expected type-specifier before ‘.’ token
         new.rlim_max = atoi(argv[3]);
            ^
z.cpp:31:20: error: expected type-specifier before ‘;’ token
         newp = &new;
                    ^
Kompilacja nie powiodła się

Dodam, jeszcze, że próbowałem zamiast g++, gcc, i to samo.

komentarz 8 maja 2017 przez mokrowski Mędrzec (155,460 p.)

Przy g++ masz takie błędy a przy gcc nie. Jeśli jednak chcesz aby kompilował się i pod gcc i g++, mała poprawka wystarczy:

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#define _FILE_OFFSET_BITS 64
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/resource.h>
 
#define errExit(msg)                                do { perror(msg); exit(EXIT_FAILURE); \
                        } while (0)
 
int
main(int argc, char *argv[])
{
    struct rlimit old, new_limit;
    struct rlimit *new_limitp;
    pid_t pid;
 
    if (!(argc == 2 || argc == 4)) {
        fprintf(stderr, "Usage: %s <pid> [<new_limit-soft-limit> "
                "<new_limit-hard-limit>]\n", argv[0]);
        exit(EXIT_FAILURE);
    }
 
    pid = atoi(argv[1]);        /* PID of target process */
 
    new_limitp = NULL;
    if (argc == 4) {
        new_limit.rlim_cur = atoi(argv[2]);
        new_limit.rlim_max = atoi(argv[3]);
        new_limitp = &new_limit;
    }
 
    /* Set CPU time limit of target process; retrieve and display
       previous limit */
 
    if (prlimit(pid, RLIMIT_CPU, new_limitp, &old) == -1)
        errExit("prlimit-1");
    printf("Previous limits: soft=%lld; hard=%lld\n",
            (long long) old.rlim_cur, (long long) old.rlim_max);
 
    /* Retrieve and display new_limit CPU time limit */
 
    if (prlimit(pid, RLIMIT_CPU, NULL, &old) == -1)
        errExit("prlimit-2");
    printf("New limits: soft=%lld; hard=%lld\n",
            (long long) old.rlim_cur, (long long) old.rlim_max);
 
    exit(EXIT_FAILURE);
}

 

Podobne pytania

0 głosów
1 odpowiedź 788 wizyt
pytanie zadane 9 lutego 2016 w C i C++ przez adojado Początkujący (420 p.)
0 głosów
2 odpowiedzi 639 wizyt
pytanie zadane 23 października 2016 w C i C++ przez Elenek Nowicjusz (160 p.)
0 głosów
2 odpowiedzi 450 wizyt
pytanie zadane 13 czerwca 2017 w C i C++ przez niezalogowany

92,551 zapytań

141,393 odpowiedzi

319,523 komentarzy

61,936 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...