Scroll to navigation

timer_create(2) System Calls Manual timer_create(2)

الاسم

timer_create - إنشاء مؤقت POSIX لكل عملية

المكتبة

مكتبة الوقت الحقيقي (librt، -lrt)

موجز

#include <signal.h>           /* تعريف ثوابت SIGEV_* */
#include <time.h>
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_MONOTONIC، هذه ساعة تتزايد برتابة. ومع ذلك، فبينما لا تقيس ساعة CLOCK_MONOTONIC الوقت أثناء تعليق النظام، فإن ساعة CLOCK_BOOTTIME تشمل الوقت الذي يكون فيه النظام معلقاً. هذا مفيد للتطبيقات التي تحتاج أن تكون مدركة للتعليق. ساعة CLOCK_REALTIME ليست مناسبة لمثل هذه التطبيقات، لأن تلك الساعة تتأثر بالتغيرات غير المستمرة في ساعة النظام.
هذه الساعة تشبه CLOCK_REALTIME، لكنها ستوقظ النظام إذا كان معلقًا. يجب أن يتمتع المستدعِي بصلاحية CAP_WAKE_ALARM لضبط مؤقت لهذه الساعة.
هذه الساعة تشبه CLOCK_BOOTTIME، لكنها ستوقظ النظام إذا كان معلقًا. يجب أن يتمتع المستدعِي بصلاحية CAP_WAKE_ALARM لضبط مؤقت لهذه الساعة.
ساعة على مستوى النظام مشتقة من وقت الساعة الجدارية ولكنها تحسب الثواني الكبيسة.

انظر clock_getres(2) لمزيد من التفاصيل حول الساعات المذكورة أعلاه.

بالإضافة إلى القيم أعلاه، يمكن تحديد clockid كـ clockid المُعاد بواسطة استدعاء clock_getcpuclockid(3) أو pthread_getcpuclockid(3).

تشير الوسيطة sevp إلى بنية sigevent تحدد كيف ينبغي إعلام المستدعي عند انتهاء المؤقت. للتعريف والتفاصيل العامة لهذه البنية، انظر sigevent(3type).

يمكن أن يأخذ الحقل sevp.sigev_notify القيم التالية:

لا تُعلم بشكل غير متزامن عند انتهاء المؤقت. يمكن مراقبة تقدم المؤقت باستخدام timer_gettime(2).
عند انتهاء المؤقت، يُولد الإشارة sigev_signo للعملية. انظر sigevent(3type) للتفاصيل العامة. سيُضبط الحقل si_code من بنية siginfo_t إلى SI_TIMER. في أي نقطة زمنية، يُصطف إشارة واحدة على الأكثر للعملية لمؤقت معين؛ انظر timer_getoverrun(2) لمزيد من التفاصيل.
عند انتهاء المؤقت، يُستدعى sigev_notify_function كما لو كانت دالة بدء خيط جديد. انظر sigevent(3type) للتفاصيل.
كما في 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 للإشارة إلى الخطأ.

الأخطاء

خطأ مؤقت أثناء تخصيص النواة لبنى المؤقت.
معرف الساعة، أو sigev_notify، أو sigev_signo، أو sigev_notify_thread_id غير صالح.
تعذر تخصيص الذاكرة.
لا تدعم النواة إنشاء مؤقت مقابل clockid هذا.
كان clockid هو CLOCK_REALTIME_ALARM أو CLOCK_BOOTTIME_ALARM ولكن المستدعي لم يمتلك قدرة CAP_WAKE_ALARM.

الإصدارات

الاختلافات بين مكتبة C والنواة

جزء من تنفيذ واجهة برمجة تطبيقات مؤقتات POSIX يُوفر بواسطة glibc. على وجه الخصوص:

معظم وظائف SIGEV_THREAD مُنفذة داخل glibc، وليس النواة. (هذا ضروري، لأن الخيط المشارك في معالجة الإعلام هو خيط يجب إدارته بواسطة تنفيذ خيوط POSIX لمكتبة C.) على الرغم من أن الإعلام المُسلم للعملية يكون عبر خيط، داخليًا يستخدم تنفيذ NPTL قيمة sigev_notify من SIGEV_THREAD_ID مع إشارة زمن حقيقي محجوزة بواسطة التنفيذ (انظر nptl(7)).
تنفيذ الحالة المبدئية حيث evp هو NULL يُعالج داخل glibc، الذي يستدعي استدعاء النظام الأساسي مع بنية sigevent مملوءة بشكل مناسب.
معرفات المؤقت المُقدمة على مستوى المستخدم تُحافظ عليها 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_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 <err.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#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 <sleep-secs> <freq-nanosecs>\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)

ترجمة

تُرجمت هذه الصفحة من الدليل بواسطة زايد السعيدي <zayed.alsaidi@gmail.com>

هذه الترجمة هي وثيقة مجانية؛ راجع رخصة جنو العامة الإصدار 3 أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات.

إذا وجدت أي أخطاء في ترجمة صفحة الدليل هذه، يرجى إرسال بريد إلكتروني إلى قائمة بريد المترجمين: kde-l10n-ar@kde.org.

29 أكتوبر 2025 صفحات دليل لينكس 6.18