timer_create(2) System Calls Manual timer_create(2) timer_create - POSIX (librt, -lrt) #include /* SIGEV_* */ #include int timer_create(clockid_t clockid, struct sigevent *_Nullable restrict sevp, timer_t *restrict timerid); glibc (. feature_test_macros(7)): timer_create(): _POSIX_C_SOURCE >= 199309L timer_create() . , timerid, null. , . . clockid , . : CLOCK_REALTIME . CLOCK_MONOTONIC , , , . CLOCK_PROCESS_CPUTIME_ID ( Linux 2.6.12) , ( ), ( ). CLOCK_THREAD_CPUTIME_ID ( Linux 2.6.12) , ( ), . CLOCK_BOOTTIME ( Linux 2.6.39) CLOCK_MONOTONIC, . , CLOCK_MONOTONIC (suspended), CLOCK_BOOTTIME . , . CLOCK_REALTIME , . CLOCK_REALTIME_ALARM ( Linux 3.0) CLOCK_REALTIME, , . CAP_WAKE_ALARM. CLOCK_BOOTTIME_ALARM ( Linux 3.0) CLOCK_BOOTTIME, , . CAP_WAKE_ALARM. CLOCK_TAI ( Linux 3.10) , , . See clock_getres(2) for some further details on the above clocks. , , clockid clockid, clock_getcpuclockid(3) pthread_getcpuclockid(3). The sevp argument points to a sigevent structure that specifies how the caller should be notified when the timer expires. For the definition and general details of this structure, see sigevent(3type). sevp.sigev_notify : SIGEV_NONE . timer_gettime(2). SIGEV_SIGNAL Upon timer expiration, generate the signal sigev_signo for the process. See sigevent(3type) for general details. The si_code field of the siginfo_t structure will be set to SI_TIMER. At any point in time, at most one signal is queued to the process for a given timer; see timer_getoverrun(2) for more details. SIGEV_THREAD Upon timer expiration, invoke sigev_notify_function as if it were the start function of a new thread. See sigevent(3type) for details. SIGEV_THREAD_ID ( Linux) SIGEV_SIGNAL, , ID sigev_notify_thread_id, . sigev_notify_thread_id ID , , clone(2) gettid(2). . sevp NULL sigevent, sigev_notify SIGEV_SIGNAL, sigev_signo SIGALRM sigev_value.sival_int ID . timer_create() 0 ID *timerid. -1, errno . EAGAIN , . EINVAL ID , sigev_notify, sigev_signo sigev_notify_thread_id. ENOMEM . ENOTSUP The kernel does not support creating a timer against this clockid. EPERM clockid was CLOCK_REALTIME_ALARM or CLOCK_BOOTTIME_ALARM but the caller did not have the CAP_WAKE_ALARM capability. C , POSIX glibc. : o SIGEV_THREAD glibc, ( , , C, POSIX). , NPTL SIGEV_THREAD_ID sigev_notify , ( nptl(7)). o , evp NULL, glibc, sigevent. o , , glibc, ID ID , . POSIX.1-2008. Linux 2.6. POSIX.1-2001. Prior to Linux 2.6, glibc provided an incomplete user-space implementation (CLOCK_REALTIME timers only) using POSIX threads, and before glibc 2.17, the implementation falls back to this technique on systems running kernels older than Linux 2.6. timer_create() . fork(2), execve(2). << >> , timer_create(). , RLIMIT_SIGPENDING ( setrlimit(2)). , timer_create(), <<() POSIX>>. POSIX : timer_create() Create a timer. timer_settime(2) Arm (start) or disarm (stop) a timer. timer_gettime(2) Fetch the time remaining until the next expiration of a timer, along with the interval setting of the timer. timer_getoverrun(2) Return the overrun count for the last timer expiration. timer_delete(2) Disarm and delete a timer. Linux 3.10, /proc/pid/timers POSIX PID pid. proc(5). Linux 4.10, POSIX . CONFIG_POSIX_TIMERS. : . , , , , , . , , . . 1 , 100 . , 10 . ./$ ./a.out 1 100 34 34 ID -- 0x804c008 1 34 34 sival_ptr = 0xbfb174f4; *sival_ptr = 0x804c008 = 10004886 #include #include #include #include #include #include #define CLOCKID CLOCK_REALTIME #define SIG SIGRTMIN #define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \ } while (0) static void print_siginfo(siginfo_t *si) { int or; timer_t *tidp; tidp = si->si_value.sival_ptr; printf(" sival_ptr = %p; ", si->si_value.sival_ptr); printf(" *sival_ptr = %#jx\n", (uintmax_t) *tidp); or = timer_getoverrun(*tidp); if (or == -1) errExit("timer_getoverrun"); else printf(" overrun count = %d\n", or); } static void handler(int sig, siginfo_t *si, void *uc) { /* Note: calling printf() from a signal handler is not safe (and should not be done in production programs), since printf() is not async-signal-safe; see signal-safety(7). Nevertheless, we use printf() here as a simple way of showing that the handler was called. */ printf("Caught signal %d\n", sig); print_siginfo(si); signal(sig, SIG_IGN); } int main(int argc, char *argv[]) { timer_t timerid; sigset_t mask; long long freq_nanosecs; struct sigevent sev; struct sigaction sa; struct itimerspec its; if (argc != 3) { fprintf(stderr, "Usage: %s \n", argv[0]); exit(EXIT_FAILURE); } /* Establish handler for timer signal. */ printf("Establishing handler for signal %d\n", SIG); sa.sa_flags = SA_SIGINFO; sa.sa_sigaction = handler; sigemptyset(&sa.sa_mask); if (sigaction(SIG, &sa, NULL) == -1) errExit("sigaction"); /* Block timer signal temporarily. */ printf("Blocking signal %d\n", SIG); sigemptyset(&mask); sigaddset(&mask, SIG); if (sigprocmask(SIG_SETMASK, &mask, NULL) == -1) errExit("sigprocmask"); /* Create the timer. */ sev.sigev_notify = SIGEV_SIGNAL; sev.sigev_signo = SIG; sev.sigev_value.sival_ptr = &timerid; if (timer_create(CLOCKID, &sev, &timerid) == -1) errExit("timer_create"); printf("timer ID is %#jx\n", (uintmax_t) timerid); /* Start the timer. */ freq_nanosecs = atoll(argv[2]); its.it_value.tv_sec = freq_nanosecs / 1000000000; its.it_value.tv_nsec = freq_nanosecs % 1000000000; its.it_interval.tv_sec = its.it_value.tv_sec; its.it_interval.tv_nsec = its.it_value.tv_nsec; if (timer_settime(timerid, 0, &its, NULL) == -1) errExit("timer_settime"); /* Sleep for a while; meanwhile, the timer may expire multiple times. */ printf("Sleeping for %d seconds\n", atoi(argv[1])); sleep(atoi(argv[1])); /* Unlock the timer signal, so that timer notification can be delivered. */ printf("Unblocking signal %d\n", SIG); if (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1) errExit("sigprocmask"); exit(EXIT_SUCCESS); } clock_gettime(2), setitimer(2), timer_delete(2), timer_getoverrun(2), timer_settime(2), timerfd_create(2), clock_getcpuclockid(3), pthread_getcpuclockid(3), pthreads(7), sigevent(3type), signal(7), time(7) () Azamat Hackimov , Dmitry Bolkhovskikh , Yuri Kozlov , Kirill Rekhov ; GNU (GNU General Public License - GPL, 3 ) , - . - , , () () () <>. Linux 6.9.1 15 2024 . timer_create(2)