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 . . . clockid . : CLOCK_REALTIME . CLOCK_MONOTONIC . CLOCK_PROCESS_CPUTIME_ID ( 2.6.12) ( ) ( ) . CLOCK_THREAD_CPUTIME_ID ( 2.6.12) ( ) . CLOCK_BOOTTIME ( 2.6.39) CLOCK_MONOTONIC . CLOCK_MONOTONIC CLOCK_BOOTTIME . . CLOCK_REALTIME . CLOCK_REALTIME_ALARM ( 3.0) CLOCK_REALTIME . CAP_WAKE_ALARM . CLOCK_BOOTTIME_ALARM ( 3.0) CLOCK_BOOTTIME . CAP_WAKE_ALARM . CLOCK_TAI ( 3.10) . clock_getres(2) . clockid clockid clock_getcpuclockid(3) pthread_getcpuclockid(3). sevp sigevent . sigevent(3type). sevp.sigev_notify : SIGEV_NONE . timer_gettime(2). SIGEV_SIGNAL sigev_signo . sigevent(3type) . si_code siginfo_t SI_TIMER. timer_getoverrun(2) . SIGEV_THREAD sigev_notify_function . sigevent(3type) . SIGEV_THREAD_ID ( ) SIGEV_SIGNAL sigev_notify_thread_id . sigev_notify_thread_id clone(2) gettid(2). . sevp NULL sigevent sigev_notify SIGEV_SIGNAL sigev_signo SIGALRM sigev_value.sival_int . timer_create() 0 *timerid. -1 errno . EAGAIN . EINVAL sigev_notify sigev_signo sigev_notify_thread_id . ENOMEM . ENOTSUP clockid . EPERM clockid CLOCK_REALTIME_ALARM CLOCK_BOOTTIME_ALARM CAP_WAKE_ALARM. C POSIX glibc. : o SIGEV_THREAD glibc . ( POSIX C.) NPTL sigev_notify SIGEV_THREAD_ID ( nptl(7)). o evp NULL glibc sigevent . o glibc . POSIX.1-2024. 2.6. POSIX.1-2001. 2.6 glibc ( CLOCK_REALTIME ) POSIX glibc 2.17 2.6. timer_create(). fork(2) execve(2). " " timer_create(). RLIMIT_SIGPENDING ( setrlimit(2)). timer_create() " POSIX ()". POSIX : timer_create() . timer_settime(2) () () . timer_gettime(2) . timer_getoverrun(2) . timer_delete(2) . 3.10 /proc/pid/timers POSIX PID pid. proc(5) . 4.10 POSIX . CONFIG_POSIX_TIMERS. : . . . . 100 . . $ ./a.out 1 100; Establishing handler for signal 34 Blocking signal 34 timer ID is 0x804c008 Sleeping for 1 seconds Unblocking signal 34 Caught signal 34 sival_ptr = 0xbfb174f4; *sival_ptr = 0x804c008 overrun count = 10004886 #include #include #include #include #include #include #include #define CLOCKID CLOCK_REALTIME #define SIG SIGRTMIN 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) err(EXIT_FAILURE, "timer_getoverrun"); 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) err(EXIT_FAILURE, "sigaction"); /* Block timer signal temporarily. */ printf("Blocking signal %d\n", SIG); sigemptyset(&mask); sigaddset(&mask, SIG); if (sigprocmask(SIG_SETMASK, &mask, NULL) == -1) err(EXIT_FAILURE, "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) err(EXIT_FAILURE, "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) err(EXIT_FAILURE, "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) err(EXIT_FAILURE, "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) 3 . . : . 6.18 29 2025 timer_create(2)