semget(2)

الاسم
semget - الحصول على معرّف مجموعة إشارات System V

المكتبة
مكتبة سي المعيارية (libc، -lc)

موجز
#include <sys/sem.h>

int semget(key_t key, int nsems, int semflg);

الوصف
استدعاء النظام semget() يُرجع معرف مجموعة إشارات System V المرتبط بالوسيط key. يمكن استخدامه إما للحصول على معرف مجموعة إشارات مُنشأة سابقًا (عندما يكون semflg صفرًا و key لا يحمل القيمة IPC_PRIVATE)، أو لإنشاء مجموعة جديدة.

يتم إنشاء مجموعة جديدة من nsems إشارة إذا كان key يحمل القيمة IPC_PRIVATE أو إذا لم تكن هناك مجموعة إشارات موجودة مرتبطة بـ key وتم تحديد IPC_CREAT في semflg.

إذا حدد semflg كلاً من IPC_CREAT و IPC_EXCL وكانت مجموعة إشارات موجودة بالفعل لـ key، فإن semget() يفشل مع تعيين errno إلى EEXIST. (هذا مماثل لتأثير الجمع O_CREAT | O_EXCL لـ open(2).)

عند الإنشاء، تحدد أقل 9 بتات أهمية من الوسيط semflg الأذونات (للمالك والمجموعة والآخرين) لمجموعة الإشارات. هذه البتات لها نفس التنسيق ونفس المعنى مثل وسيط mode لـ open(2) (على الرغم من أن أذونات التنفيذ ليست ذات معنى للإشارات، وأذونات الكتابة تعني الإذن بتغيير قيم الإشارات).

عند إنشاء مجموعة إشارات جديدة، يقوم semget() بتهيئة بنية البيانات المرتبطة بالمجموعة، semid_ds (انظر semctl(2))، على النحو التالي:

•   يتم تعيين sem_perm.cuid و sem_perm.uid إلى معرف المستخدم الفعّال للعملية المستدعية.

•   يتم تعيين sem_perm.cgid و sem_perm.gid إلى معرف المجموعة الفعّال للعملية المستدعية.

•   يتم تعيين أقل 9 بتات أهمية من sem_perm.mode إلى أقل 9 بتات أهمية من semflg.

•   يتم تعيين sem_nsems إلى قيمة nsems.

•   يتم تعيين sem_otime إلى 0.

•   يتم تعيين sem_ctime إلى الوقت الحالي.

يمكن أن يكون الوسيط nsems 0 (غير مهم) عندما لا يتم إنشاء مجموعة إشارات. وإلا، يجب أن يكون nsems أكبر من 0 وأقل من أو يساوي الحد الأقصى لعدد الإشارات لكل مجموعة إشارات (SEMMSL).

إذا كانت مجموعة الإشارات موجودة بالفعل، يتم التحقق من الأذونات.

قيمة الإرجاع
عند النجاح، يُرجع semget() معرف مجموعة الإشارات (عدد صحيح غير سالب). عند الفشل، يتم إرجاع -1، ويتم تعيين errno للإشارة إلى الخطأ.

الأخطاء

EACCES
    توجد مجموعة إشارات لـ key، لكن العملية المستدعية لا تملك الإذن بالوصول إلى المجموعة، ولا تملك القدرة CAP_IPC_OWNER في مساحة المستخدم التي تحكم مساحة IPC الخاصة بها.

EEXIST
    تم تحديد IPC_CREAT و IPC_EXCL في semflg، لكن مجموعة إشارات موجودة بالفعل لـ key.

EINVAL
    nsems أقل من 0 أو أكبر من الحد الأقصى لعدد الإشارات لكل مجموعة إشارات (SEMMSL).

EINVAL
    توجد مجموعة إشارات مقابلة لـ key بالفعل، لكن nsems أكبر من عدد الإشارات في تلك المجموعة.

ENOENT
    لا توجد مجموعة إشارات لـ key ولم يحدد semflg IPC_CREAT.

ENOMEM
    يجب إنشاء مجموعة إشارات لكن النظام لا يملك ذاكرة كافية لبنية البيانات الجديدة.

ENOSPC
    يجب إنشاء مجموعة إشارات لكن سيتم تجاوز حد النظام للحد الأقصى لعدد مجموعات الإشارات (SEMMNI)، أو الحد الأقصى لعدد الإشارات على مستوى النظام (SEMMNS).

المعايير
POSIX.1-2024.

التاريخ
SVr4, POSIX.1-2001.

ملاحظات
IPC_PRIVATE ليس حقل علم بل هو نوع key_t. إذا تم استخدام هذه القيمة الخاصة لـ key، يتجاهل استدعاء النظام كل شيء باستثناء أقل 9 بتات أهمية من semflg وينشئ مجموعة إشارات جديدة (عند النجاح).

  تهيئة الإشارة
قيم الإشارات في مجموعة منشأة حديثًا غير محددة. (POSIX.1-2001 و POSIX.1-2008 صريحان في هذه النقطة، على الرغم من أن POSIX.1-2008 يلاحظ أن إصدارًا مستقبليًا من المعيار قد يتطلب من التنفيذ تهيئة الإشارات إلى 0.) على الرغم من أن Linux، مثل العديد من التطبيقات الأخرى، يقوم بتهيئة قيم الإشارات إلى 0، لا يمكن لتطبيق محمول الاعتماد على هذا: يجب عليه تهيئة الإشارات صراحةً إلى القيم المطلوبة.

يمكن إجراء التهيئة باستخدام عملية semctl(2) SETVAL أو SETALL. عندما لا يعرف عدة نظراء من سيكون أول من يهيئ المجموعة، يمكن استخدام التحقق من وجود قيمة غير صفرية لـ sem_otime في بنية البيانات المرتبطة التي يتم استردادها بواسطة عملية semctl(2) IPC_STAT لتجنب حالات التزاحم.

  حدود السيمافور
الحدود التالية على موارد مجموعة الإشارات تؤثر على استدعاء semget():

SEMMNI
    حد على مستوى النظام لعدد مجموعات الإشارات. قبل Linux 3.19، كانت القيمة المبدئية لهذا الحد 128. منذ Linux 3.19، القيمة المبدئية هي 32,000. في Linux، يمكن قراءة هذا الحد وتعديله عبر الحقل الرابع من /proc/sys/kernel/sem.

SEMMSL
    الحد الأقصى لعدد الإشارات لكل معرف إشارة. قبل لينكس 3.19، كانت القيمة المبدئية لهذا الحد 250. منذ لينكس 3.19، القيمة المبدئية هي 32,000. على لينكس، يمكن قراءة هذا الحد وتعديله عبر الحقل الأول من /proc/sys/kernel/sem.

SEMMNS
    الحد على مستوى النظام لعدد الإشارات: يعتمد على السياسة (على لينكس، يمكن قراءة هذا الحد وتعديله عبر الحقل الثاني من /proc/sys/kernel/sem). لاحظ أن عدد الإشارات على مستوى النظام محدود أيضًا بحاصل ضرب SEMMSL وSEMMNI.

العلل
ربما كان اختيار الاسم IPC_PRIVATE غير موفق، فاسم IPC_NEW كان سيظهر وظيفتها بشكل أوضح.

أمثلة
البرنامج الموضح أدناه يستخدم semget() لإنشاء مجموعة إشارات جديدة أو استرداد معرف مجموعة موجودة. يولد key لـ semget() باستخدام ftok(3). تُستخدم الوسيطتان الأوليان لسطر الأوامر كوسيطتي pathname وproj_id لـ ftok(3). الوسيطة الثالثة لسطر الأوامر هي عدد صحيح يحدد وسيطة nsems لـ semget(). يمكن استخدام خيارات سطر الأوامر لتحديد علمي IPC_CREAT (-c) وIPC_EXCL (-x) لاستدعاء semget(). استخدام هذا البرنامج موضح أدناه.

ننشئ أولاً ملفين سيُستخدمان لتوليد المفاتيح باستخدام ftok(3)، وننشئ مجموعتي إشارات باستخدام هذين الملفين، ثم ندرج المجموعات باستخدام ipcs(1):

    $ touch mykey mykey2;
    $ ./t_semget -c mykey p 1;
    ID = 9
    $ ./t_semget -c mykey2 p 2;
    ID = 10
    $ ipcs -s;

    ------ Semaphore Arrays --------
    key        semid      owner      perms      nsems
    0x7004136d 9          mtk        600        1
    0x70041368 10         mtk        600        2

بعد ذلك، نوضح أنه عندما يُعطى semctl(2) نفس key (كما يُولد بواسطة نفس الوسائط لـ ftok(3))، فإنه يعيد معرف مجموعة الإشارات الموجودة بالفعل:

    $ ./t_semget -c mykey p 1;
    ID = 9

أخيرًا، نوضح نوع التصادم الذي يمكن أن يحدث عندما يُعطى ftok(3) وسيطات pathname مختلفة لها نفس رقم inode:

    $ ln mykey link;
    $ ls -i1 link mykey;
    2233197 link
    2233197 mykey
    $ ./t_semget link p 1;       # Generates same key as 'mykey'
    ID = 9

  مصدر البرنامج
    /* t_semget.c

       Licensed under GNU General Public License v2 or later.
    */
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/ipc.h>
    #include <sys/sem.h>
    #include <unistd.h>

    static void
    usage(const char *pname)
    {
        fprintf(stderr, "Usage: %s [-cx] pathname proj-id num-sems\n",
                pname);
        fprintf(stderr, "    -c           Use IPC_CREAT flag\n");
        fprintf(stderr, "    -x           Use IPC_EXCL flag\n");
        exit(EXIT_FAILURE);
    }

    int
    main(int argc, char *argv[])
    {
        int    semid, nsems, flags, opt;
        key_t  key;

        flags = 0;
        while ((opt = getopt(argc, argv, "cx")) != -1) {
            switch (opt) {
            case 'c': flags |= IPC_CREAT;   break;
            case 'x': flags |= IPC_EXCL;    break;
            default:  usage(argv[0]);
            }
        }

        if (argc != optind + 3)
            usage(argv[0]);

        key = ftok(argv[optind], argv[optind + 1][0]);
        if (key == -1) {
            perror("ftok");
            exit(EXIT_FAILURE);
        }

        nsems = atoi(argv[optind + 2]);

        semid = semget(key, nsems, flags | 0600);
        if (semid == -1) {
            perror("semget");
            exit(EXIT_FAILURE);
        }

        printf("ID = %d\n", semid);

        exit(EXIT_SUCCESS);
    }

انظر أيضًا
semctl(2), semop(2), ftok(3), capabilities(7), sem_overview(7), sysvipc(7)

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

هذه الترجمة هي وثيقة مجانية؛ راجع رخصة جنو العامة الإصدار 3 (https://www.gnu.org/licenses/gpl-3.0.html) أو ما بعده للاطلاع على شروط حقوق النشر. لا توجد أي ضمانات.

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