shm_open(3)

الاسم
shm_open, shm_unlink - إنشاء/فتح أو فصل كائنات الذاكرة المشتركة POSIX

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

موجز
#include <sys/mman.h>
#include <sys/stat.h>        /* For mode constants */
#include <fcntl.h>           /* For O_* constants */

int shm_open(const char *name, int oflag, mode_t mode);
int shm_unlink(const char *name);

الوصف
تنشئ وتفتح الدالة shm_open() كائن ذاكرة مشتركة POSIX جديدًا، أو تفتح كائنًا موجودًا. كائن الذاكرة المشتركة POSIX هو في الواقع مقبض يمكن استخدامه بواسطة عمليات غير مرتبطة لـ mmap(2) نفس منطقة الذاكرة المشتركة. تؤدي الدالة shm_unlink() العملية المعاكسة، بإزالة كائن أُنشئ سابقًا بواسطة shm_open().

عملية shm_open() مماثلة لعملية open(2). يحدد name كائن الذاكرة المشتركة الذي سيُنشأ أو يُفتح. للاستخدام المحمول، يجب تعريف كائن الذاكرة المشتركة باسم من الشكل /somename؛ أي سلسلة محارف منتهية بقيمة خالية يصل طولها إلى NAME_MAX (أي 255) حرفًا تتكون من شرطة مائلة أولية، متبوعة بحرف واحد أو أكثر، لا تحتوي أي منها على شرطات مائلة.

oflag هو قناع بتات يُنشأ بواسطة ORing معًا واحدًا بالضبط من O_RDONLY أو O_RDWR وأي من الأعلام الأخرى المدرجة هنا:

O_RDONLY
    يفتح الكائن للوصول للقراءة. يمكن لكائن الذاكرة المشتركة المفتوح بهذه الطريقة أن يُوصل بـ mmap(2) فقط للوصول للقراءة (PROT_READ).

O_RDWR
    يفتح الكائن للوصول للقراءة والكتابة.

O_CREAT
    ينشئ كائن الذاكرة المشتركة إذا لم يكن موجودًا. تُؤخذ ملكية المستخدم والمجموعة للكائن من المعرفات الفعالة المقابلة للعملية المستدعية، وتُضبط أذونات الكائن وفقًا للبتات التسع السفلى من mode، باستثناء أن تلك البتات المضبوطة في قناع إنشاء وضع ملف العملية (انظر umask(2)) تُمسح للكائن الجديد. مجموعة من ثوابت الماكرو التي يمكن استخدامها لتعريف mode مدرجة في open(2). (يمكن الحصول على التعريفات الرمزية لهذه الثوابت بتضمين <sys/stat.h>.)

    كائن الذاكرة المشتركة الجديد له طول صفري مبدئيًا—يمكن ضبط حجم الكائن باستخدام ftruncate(2). البايتات المخصصة حديثًا لكائن الذاكرة المشتركة تُهيأ آلي إلى 0.

O_EXCL
    إذا حُدد O_CREAT أيضًا، وكان كائن ذاكرة مشتركة بالاسم name المعطى موجودًا بالفعل، يُرجع خطأ. التحقق من وجود الكائن، وإنشاؤه إذا لم يكن موجودًا، يُنفذان ذريًا.

O_TRUNC
    إذا كان كائن الذاكرة المشتركة موجودًا بالفعل، يُقتص إلى صفر بايت.

يمكن الحصول على تعريفات قيم الأعلام هذه بتضمين <fcntl.h>.

عند الإكمال الناجح، تُرجع shm_open() واصف ملف جديد يشير إلى كائن الذاكرة المشتركة. يُضمن أن واصف الملف هذا هو واصف الملف ذو الرقم الأدنى الذي لم يُفتح سابقًا داخل العملية. يُضبط العلم FD_CLOEXEC (انظر fcntl(2)) لواصف الملف.

يُستخدم واصف الملف عادةً في الاستدعاءات اللاحقة لـ ftruncate(2) (لكائن منشأ حديثًا) و mmap(2). بعد استدعاء mmap(2)، يمكن إغلاق واصف الملف دون التأثير على تعيين الذاكرة.

عملية shm_unlink() مماثلة لـ unlink(2): تزيل اسم كائن الذاكرة المشتركة، وبمجرد أن تلغي جميع العمليات تعيين الكائن، تُحرر وتدمر محتويات منطقة الذاكرة المرتبطة. بعد shm_unlink() ناجح، تفشل محاولات shm_open() لكائن بنفس name (ما لم يُحدد O_CREAT، وفي هذه الحالة يُنشأ كائن جديد ومتميز).

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

الأخطاء

EACCES
    رُفض الإذن لـ shm_unlink() لكائن الذاكرة المشتركة.

EACCES
    رُفض الإذن لـ shm_open() name في mode المحدد، أو حُدد O_TRUNC وليس للمستدعي إذن كتابة على الكائن.

EEXIST
    حُدد كل من O_CREAT و O_EXCL لـ shm_open() وكائن الذاكرة المشتركة المحدد بواسطة name موجود بالفعل.

EINVAL
    وسيطة name للدالة shm_open() كانت غير صالحة.

EMFILE
    وُصل إلى الحد الأقصى لواصفات الملفات المفتوحة لكل عملية.

ENAMETOOLONG
    طول name يتجاوز PATH_MAX.

ENFILE
    وُصل إلى الحد الأقصى لإجمالي عدد الملفات المفتوحة على مستوى النظام.

ENOENT
    جرت محاولة لاستدعاء shm_open() على name غير موجود، ولم يُحدد O_CREAT.

ENOENT
    جرت محاولة لاستدعاء shm_unlink() على name غير موجود.

السمات
للاطلاع على شرح للمصطلحات المستخدمة في هذا القسم، انظر attributes(7).
الواجهة | السمة | القيمة
shm_open(), shm_unlink() | سلامة الخيوط | المنطقة (locale) آمنة لتعدد المسالك (MT-Safe)

الإصدارات
يترك POSIX سلوك الجمع بين O_RDONLY و O_TRUNC غير محدد. في لينكس، سيؤدي هذا إلى اقتطاع كائن ذاكرة مشتركة موجود بنجاح—قد لا يكون هذا هو الحال في أنظمة UNIX الأخرى.

يستخدم تطبيق كائن الذاكرة المشتركة POSIX في لينكس نظام ملفات tmpfs(5) مخصص يُوصل عادة تحت /dev/shm.

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

التاريخ
glibc 2.2. POSIX.1-2001.

ينص POSIX.1-2001 على أن ملكية المجموعة لكائن ذاكرة مشتركة مُنشأ حديثًا تُضبط إما على معرف المجموعة الفعّال للعملية المستدعية أو "معرف مجموعة مبدئي للنظام". ينص POSIX.1-2008 على أن ملكية المجموعة قد تُضبط إما على معرف المجموعة الفعّال للعملية المستدعية أو، إذا كان الكائن مرئيًا في نظام الملفات، معرف مجموعة الدليل الأصلي.

أمثلة
تستخدم البرامج أدناه الذاكرة المشتركة POSIX والإشارات غير المسماة POSIX لتبادل قطعة من البيانات. برنامج "bounce" (الذي يجب تشغيله أولاً) يرفع حالة سلسلة محارف تُوضع في الذاكرة المشتركة بواسطة برنامج "send". بمجرد تعديل البيانات، يطبع برنامج "send" محتويات الذاكرة المشتركة المعدلة. مثال على تنفيذ البرنامجين هو التالي:

    $ ./pshm_ucase_bounce /myshm &
    [1] 270171
    $ ./pshm_ucase_send /myshm hello;
    HELLO

يُقدم تفصيل إضافي حول هذه البرامج أدناه.

  مصدر البرنامج: pshm_ucase.h
يُضمن ملف الرأس التالي بواسطة كلا البرنامجين أدناه. غرضه الرئيسي هو تعريف بنية ستُفرض على كائن الذاكرة المشترك بين البرنامجين.

    #ifndef PSHM_UCASE_H
    #define PSHM_UCASE_H

    #include <err.h>
    #include <semaphore.h>
    #include <stddef.h>
    #include <stdio.h>
    #include <stdlib.h>

    #define BUF_SIZE 1024   /* Maximum size for exchanged string */

    /* Define a structure that will be imposed on the shared
       memory object */

    struct shmbuf {
        sem_t  sem1;            /* POSIX unnamed semaphore */
        sem_t  sem2;            /* POSIX unnamed semaphore */
        size_t cnt;             /* Number of bytes used in 'buf' */
        char   buf[BUF_SIZE];   /* Data being transferred */
    };

    #endif  // include guard

  مصدر البرنامج: pshm_ucase_bounce.c
ينشئ برنامج "bounce" كائن ذاكرة مشتركة جديدًا بالاسم المُعطى في وسيطة سطر الأوامر ويُحدد حجم الكائن ليطابق حجم بنية shmbuf المُعرفة في ملف الرأس. ثم يُخطط الكائن في مساحة عناوين العملية، ويُهيئ إشارتين POSIX داخل الكائن إلى 0.

بعد أن يُرسل برنامج "send" أول إشارة، يرفع برنامج "bounce" حالة البيانات التي وُضعت في الذاكرة بواسطة برنامج "send" ثم يُرسل الإشارة الثانية ليُخبر برنامج "send" أنه يمكنه الآن الوصول إلى الذاكرة المشتركة.

    /* pshm_ucase_bounce.c

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

    #include "pshm_ucase.h"

    int
    main(int argc, char *argv[])
    {
        int            fd;
        char           *shmpath;
        struct shmbuf  *shmp;

        if (argc != 2) {
            fprintf(stderr, "Usage: %s /shm-path\n", argv[0]);
            exit(EXIT_FAILURE);
        }

        shmpath = argv[1];

        /* Create shared memory object and set its size to the size
           of our structure.  */

        fd = shm_open(shmpath, O_CREAT | O_EXCL | O_RDWR, 0600);
        if (fd == -1)
            err(EXIT_FAILURE, "shm_open");

        if (ftruncate(fd, sizeof(struct shmbuf)) == -1)
            err(EXIT_FAILURE, "ftruncate");

        /* Map the object into the caller's address space.  */

        shmp = mmap(NULL, sizeof(*shmp), PROT_READ | PROT_WRITE,
                    MAP_SHARED, fd, 0);
        if (shmp == MAP_FAILED)
            err(EXIT_FAILURE, "mmap");

        /* Initialize semaphores as process-shared, with value 0.  */

        if (sem_init(&shmp->sem1, 1, 0) == -1)
            err(EXIT_FAILURE, "sem_init-sem1");
        if (sem_init(&shmp->sem2, 1, 0) == -1)
            err(EXIT_FAILURE, "sem_init-sem2");

        /* Wait for 'sem1' to be posted by peer before touching
           shared memory.  */

        if (sem_wait(&shmp->sem1) == -1)
            err(EXIT_FAILURE, "sem_wait");

        /* Convert data in shared memory into upper case.  */

        for (size_t j = 0; j < shmp->cnt; j++)
            shmp->buf[j] = toupper((unsigned char) shmp->buf[j]);

        /* Post 'sem2' to tell the peer that it can now
           access the modified data in shared memory.  */

        if (sem_post(&shmp->sem2) == -1)
            err(EXIT_FAILURE, "sem_post");

        /* Unlink the shared memory object.  Even if the peer process
           is still using the object, this is okay.  The object will
           be removed only after all open references are closed.  */

        shm_unlink(shmpath);

        exit(EXIT_SUCCESS);
    }

  مصدر البرنامج: pshm_ucase_send.c
يأخذ برنامج "send" وسيطتين لسطر الأوامر: اسم مسار كائن ذاكرة مشتركة مُنشأ سابقًا بواسطة برنامج "bounce" وسلسلة محارف ستُنسخ إلى ذلك الكائن.

يَفتَح البرنامج كائن الذاكرة المُشتركة ويَربِط الكائن في نطاق عناوينه. ثم يَنسَخ البيانات المُحدَّدة في وسيطه الثاني إلى الذاكرة المُشتركة، ويُطلِق الإشارة الأولى، التي تُخبِر برنامج "الارتداد" أنه يمكنه الآن الوصول إلى تلك البيانات. بعد أن يُطلِق برنامج "الارتداد" الإشارة الثانية، يَطبَع برنامج "الإرسال" محتويات الذاكرة المُشتركة على الخرج القياسي.

    /* pshm_ucase_send.c

       Licensed under GNU General Public License v2 or later.
    */
    #include <fcntl.h>
    #include <stddef.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/mman.h>
    #include <unistd.h>

    #include "pshm_ucase.h"

    int
    main(int argc, char *argv[])
    {
        int            fd;
        char           *shmpath, *string;
        size_t         len;
        struct shmbuf  *shmp;

        if (argc != 3) {
            fprintf(stderr, "Usage: %s /shm-path string\n", argv[0]);
            exit(EXIT_FAILURE);
        }

        shmpath = argv[1];
        string = argv[2];
        len = strlen(string);

        if (len > BUF_SIZE) {
            fprintf(stderr, "String is too long\n");
            exit(EXIT_FAILURE);
        }

        /* Open the existing shared memory object and map it
           into the caller's address space.  */

        fd = shm_open(shmpath, O_RDWR, 0);
        if (fd == -1)
            err(EXIT_FAILURE, "shm_open");

        shmp = mmap(NULL, sizeof(*shmp), PROT_READ | PROT_WRITE,
                    MAP_SHARED, fd, 0);
        if (shmp == MAP_FAILED)
            err(EXIT_FAILURE, "mmap");

        /* Copy data into the shared memory object.  */

        shmp->cnt = len;
        memcpy(&shmp->buf, string, len);

        /* Tell peer that it can now access shared memory.  */

        if (sem_post(&shmp->sem1) == -1)
            err(EXIT_FAILURE, "sem_post");

        /* Wait until peer says that it has finished accessing
           the shared memory.  */

        if (sem_wait(&shmp->sem2) == -1)
            err(EXIT_FAILURE, "sem_wait");

        /* Write modified data in shared memory to standard output.  */

        if (write(STDOUT_FILENO, &shmp->buf, len) == -1)
            err(EXIT_FAILURE, "write");
        if (write(STDOUT_FILENO, "\n", 1) == -1)
            err(EXIT_FAILURE, "write");

        exit(EXIT_SUCCESS);
    }

انظر أيضًا
close(2), fchmod(2), fchown(2), fcntl(2), fstat(2), ftruncate(2), memfd_create(2), mmap(2), open(2), umask(2), shm_overview(7)

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

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

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