C Programming

POSIX Shared Memory with C Programming

POSIX shared memory is a framework for inter-process communication (IPC) specified in the POSIX specifications. Two (or more) tasks can read from it and write to the shared memory zone while establishing the shared memory. POSIX shared memory does not always enforce copy disbursements, in contrast to other IPC structures (e.g., pipe, socket, etc.), and is desirable for certain programs.

POSIX Shared Memory Calls

The POSIX shared memory functions focused on the UNIX concept that the object must be a document when performing input/output activities on an entity. Therefore, because you recite and inscribe to a mutual POSIX memory entity, the latter must be considered as a document. A memory-mapped document is a POSIX shared memory entity. To use the shm_open system call function beneath /dev/shm, separate shared memory documents are generated. There are only two dedicated shared memory system calls from POSIX, shm_open, and shm_unlink, which are closely related to opening and unlinking file system calls. The ftruncate, mmap, and munmap framework calls for documents are used to perform other tasks on POSIX shared memory. It is necessary to connect a program that uses POSIX shared memory calls to -lrt.

Programs using POSIX shared memory calls must go through the following steps:

Using shm_open(), form a shared memory object. The document descriptor can be reverted if the formation of the object is successful.

With ftruncate(), the size of the object will be fixed.

With map() and MAP_SHARED, delineate this object into the present address space.

Read/write the shared memory.

Via munmap(), un-delineate the shared memory.

Use close() to shut the object.

Through shm_unlink(), delete the object in the shared memory.

shm_open()

As described above, shm_open() is used to generate a new shared memory object. It makes the object accessible to the calling procedure using the reverted descriptor. The following is the definition of this function call:

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

The first parameter is the shared memory object’s name. It is a null-terminated string of the /name type, with the stipulation that no other character can be a slash other than its first character. Oflag is a small veil created with several of the preceding flags by OR-ing, whether via O_RDONLY or O_RDWR. The parameters described indicate that its shared-memory object must be formed (O_CREAT) when it does not already exist and also the object is available for reading and writing (O_RDWR). The very last argument sets the directory approvals for the shared-memory object.

shm_unlink()

Shm_unlink() eliminates the POSIX shared memory entity that was formerly developed. The integer document descriptor for the shared-memory object is returned via an effective call to shm_open(). As defined beneath the shm_open(), the parameter name is the title of the shared memory entity. The following is the definition of the shm_unlink() function:

>> Int shm_unlink( const char *name);

ftruncate()

Upon setting the object, the ftruncate() method is cast off to set up the entity size in bytes. The function definition is as follows:

>> Int ftruncate( int fd, off_t length);

When constructing a shared POSIX memory, it is indeed zero bytes in size capacity. You may render the POSIX shared memory entity with bytes of size length via ftruncate. Ftruncate yields zero on execution. Ftruncate outputs -1 in case of a failure and errno is set to trigger the error.

mmap()

Eventually, a memory-mapped document with the shared-memory entity is set via the mmap() method. Then, it yields a memory-mapped document pointer that is cast off to reach the shared-memory entity. The following is the definition of the mmap() function:

>> Void *mmap ( void *addr, size_t length, int prot, int flags, int fd, off_t offset);

In this, ‘addr’ is the address to which it will be mapped. The ‘length’ is the range of the shared memory entity. The values for prot may differ, but we will use the PROT READ | PROT WRITE. There are several flags, but MAP SHARED is essential for shared memory. Now, ‘fd’ is a document descriptor that was obtained earlier. Offset is the point where the mapping begins in the shared memory entity; the 0 offset value can also be used. On completion, mmap() yields the pointer to the mapping position of the shared memory entity.

munmap()

At the position directed by addr and getting size, length, munmap unmaps the shared memory item. Munmap yields 0 upon completion and -1 in the situation of inaccuracy, in which case errno is assigned to trigger the error.

>> Void munmap ( void *addr, size_t length);

Example: Sender and Receiver

Let us take the example of the sender and the receiver. The sender will create a new shared-memory object with the name /shmem-example and inscribe three numerals into the shared memory through it. Now, the receiver may expose the shared-memory object and recite the three numerals from the memory. We will create three files with the names protocol.h, sender.c, and receiver.c.

$ touch protocol.h

$ touch sender.c

$ touch receiver.c

Next, we will add the below source code to the files ‘protocol.h,’ ‘sender.c,’ and ‘receiver.c.’ Now, we will save all and close them.

Now we will be compiling and joining the above code using the keyword –lrt separately for the sender.c and receiver.c file. Here is the command to do so:

$ gcc –o sender sender.c –lrt

$ gcc –o receiver receiver.c –lrt

Now, we will run the sender code using the following command. The output is given below.

$ ./sender

Running the sender code, the shared memory object has been generated and can be found beneath /dev/shm using the command below:

$ ls –l /dev/shm | grep shmem-example

When we run the receiver code, we will obtain the output below:

$ ./receiver

Whenever the function gm_unlink() is called using the file ‘receiver.c,’ the object /dev/shm/shmem-example will be detached. In this case, you will obtain no object on output, as shown below.

$ ls –l /dev/shm/shmem-example

Conclusion

In this article, you learned how to use POSIX Shared Memory with C programming in Ubuntu 20.04, including every function call used to establish shared memory. I hope that this article helped you to improve your programming knowledge and covered every doubt you have on this subject.

About the author

Aqsa Yasin

Aqsa Yasin

I am a self-motivated information technology professional with a passion for writing. I am a technical writer and love to write for all Linux flavors and Windows.