Section 9.13. POSIX IPC


9.13. POSIX IPC

The POSIX 1003.1b-1993 (POSIX93) standard introduced a set of IPC interfaces as part of the POSIX Real-time Extensions. Collectively known as POSIX IPC, these interfaces define functions for message queues, semaphores, and shared memory. The POSIX IPC functions are rather different from their XSI counterparts.

Mac OS X 10.4 does not provide POSIX message queues. It does, however, provide the POSIX semaphore and shared memory interfaces.


In contrast to XSI IPC, which uses keys as IPC identifiers, POSIX IPC uses string names for IPC objects. The Single UNIX Specification specifies several things about IPC names but leaves several other things unspecified and therefore open to implementation-specific behavior, as shown in the following examples.

  • It is unspecified whether an IPC name appears in the file system. Mac OS X does not require the name to be present in the file system, and if it is, its presence does not affect the behavior of POSIX IPC calls.

  • Mac OS X allows an IPC name to be at most 31 characters long (including the terminating NUL character).

  • If an IPC name begins with the slash character, any caller of an IPC open function (such as sem_open() or shm_open()) with the same name refers to the same IPC object, as long as that name has not been removed.

  • If an IPC name does not begin with the slash character, the effect is implementation-defined. Mac OS X treats this case identically to the case when the name does begin with a slash character.

  • The interpretation of slash characters other than the leading slash character in a name is implementation-defined. Mac OS X treats a slash character in an IPC name as any other character. In particular, unlike file system pathnames, it does not canonicalize multiple slash characters. For example, the following IPC names are valid and different on Mac OS X: ipcobject, /ipcobject, //ipcobject, and /ipcobject/.

9.13.1. POSIX Semaphores

A named POSIX semaphore is created using sem_open() and deleted using sem_unlink(). sem_open() is also used to connect the calling process to an existing semaphore. sem_close() closes an open semaphore. These functions resemble the open(), unlink(), and close() functions for files. In fact, like open(), sem_open() accepts the O_CREAT and O_EXCL flags to determine whether the named object is only being accessed or also being created. However, instead of integer-based file descriptors, the semaphore functions deal with pointers to sem_t structures.

POSIX semaphores are counting semaphores: A lock operation on a semaphore decrements its value by one, whereas an unlock operation increments its value by one. In the simplest sense, a POSIX semaphore is an integer variable that is accessed through two atomic operations: sem_wait() and sem_post(). Given an open semaphore, sem_wait() and sem_post() perform lock and unlock operations, respectively, on the semaphore. If the semaphore value is zero when sem_wait() is called, the caller blocks. Such blocking can be interrupted by a signal.

Figure 945 shows the source for the following four simple programs, which demonstrate the working of POSIX semaphores on Mac OS X.

  • sem_create creates a named semaphore if it does not already exist.

  • sem_unlink deletes an existing named semaphore.

  • sem_post unlocks an existing named semaphore.

  • sem_wait locks an existing named semaphore, blocking until it can do so.

The programs all include a common header file (sem_common.h).

Figure 945. Working with POSIX semaphores

// sem_common.h #ifndef _SEM_COMMON_H_ #define _SEM_COMMON_H_ #include <stdio.h> #include <stdlib.h> #include <semaphore.h> #define CHECK_ARGS(count, msg) {                          \     if (argc != count) {                                  \         fprintf(stderr, "usage: %s " msg "\n", PROGNAME); \         exit(1);                                          \     }                                                     \ } #endif // sem_create.c #include "sem_common.h" #define PROGNAME "sem_create" int main(int argc, char **argv) {     int    val;     sem_t *sem;     CHECK_ARGS(3, "<path> <value>");     val = atoi(argv[2]);     sem = sem_open(argv[1], O_CREAT | O_EXCL, 0644, val);     if (sem == (sem_t *)SEM_FAILED) {         perror("sem_open");         exit(1);     }     sem_close(sem);     exit(0); } // sem_unlink.c #include "sem_common.h" #define PROGNAME "sem_unlink" int main(int argc, char **argv) {     int ret = 0;     CHECK_ARGS(2, "<path>");     if ((ret = sem_unlink(argv[1])) < 0)         perror("sem_unlink");     exit(ret); } // sem_post.c #include "sem_common.h" #define PROGNAME "sem_post" int main(int argc, char **argv) {     int    ret = 0;     sem_t *sem;     CHECK_ARGS(2, "<path>");     sem = sem_open(argv[1], 0);     if (sem == (sem_t *)SEM_FAILED) {         perror("sem_open");         exit(1);     }     if ((ret = sem_post(sem)) < 0)         perror("sem_post");     sem_close(sem);     exit(ret); } // sem_wait.c #include "sem_common.h" #define PROGNAME "sem_wait" int main(int argc, char **argv) {     int    ret = 0;     sem_t *sem;     CHECK_ARGS(2, "<path>");     sem = sem_open(argv[1], 0);     if (sem == (sem_t *)SEM_FAILED) {         perror("sem_open");         exit(1);     }     if ((ret = sem_wait(sem)) < 0)         perror("sem_wait");     printf("successful\n");     sem_close(sem);     exit(ret); }

We can test the programs by using sem_create to create a semaphore with some initial count, say, 2. We should then be able to call sem_wait on that semaphore twice without blocking. The third call would block and can be unblocked by calling sem_post once. Finally, we can delete the semaphore using sem_unlink.

$ gcc -Wall -o sem_create sem_create.c ... $ ./sem_create /semaphore 2 $ ./sem_create /semaphore 2 sem_open: File exists $ ./sem_wait /semaphore successful $ ./sem_wait /semaphore successful $ ./sem_wait /semaphore     # blocks                             # another shell prompt                             $ ./sem_post /semaphore successful $ ./sem_unlink /semaphore $ ./sem_wait /semaphore sem_open: No such file or directory


Besides named POSIX semaphores, there also exist unnamed POSIX semaphores, which can be initialized and destroyed by calling sem_init() and sem_destroy(), respectively. These two system calls are not supported on Mac OS X 10.4.

Named POSIX semaphores are implemented atop Mach semaphores, which we will discuss in Section 9.18.5.


9.13.2. POSIX Shared Memory

A named POSIX shared memory segment can be created using shm_open(), which is also used to open an existing segmentsimilar to using sem_open(). An existing segment can be deleted using shm_unlink().

shm_open() returns a file descriptor that can be mapped into memory through the mmap() system call. Once access to the memory is no longer needed, it can be unmapped through munmap(), and the descriptor can be closed through close(). Thus, POSIX shared memory objects resemble memory-mapped files. Note that the initial size of a newly created segment is zero. A specific size can be set using ftruncate(). Information about an existing segment can be retrieved by calling stat() on the file descriptor obtained from shm_open().

Figure 946 shows the source for the following three simple programs, which demonstrate the working of POSIX shared memory on Mac OS X.

  • shm_create creates a named shared memory segment and copies a given string to it.

  • shm_info displays information about an existing segment.

  • shm_unlink deletes an existing segment.

The programs all include a common header file (shm_common.h).

Figure 946. Working with POSIX shared memory

// shm_common.h #ifndef _SHM_COMMON_H_ #define _SHM_COMMON_H_ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/mman.h> #define CHECK_ARGS(count, msg) {                          \     if (argc != count) {                                  \         fprintf(stderr, "usage: %s " msg "\n", PROGNAME); \         exit(1);                                          \     }                                                     \ } #endif // shm_create.c #include "shm_common.h" #include <string.h> #define PROGNAME "shm_create" int main(int argc, char **argv) {     char   *p;     int     shm_fd;     size_t  len;     CHECK_ARGS(3, "<path> <shared string>");     if ((shm_fd = shm_open(argv[1], O_CREAT | O_EXCL | O_RDWR, S_IRWXU)) < 0) {         perror("shm_open");         exit(1);     }     len = strlen(argv[2]) + 1;     ftruncate(shm_fd, len);     if (!(p = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0))) {         perror("mmap");         shm_unlink(argv[1]);         exit(1);     }     // copy the user-provided data into the shared memory     snprintf(p, len + 1, "%s", argv[2]);     munmap(p, len);     close(shm_fd);     exit(0); } // shm_info.c #include "shm_common.h" #include <sys/stat.h> #include <pwd.h> #include <grp.h> #define PROGNAME "shm_info" void print_stat_info(char *name, struct stat *sb) {     struct passwd *passwd;     struct group  *group;     char           filemode[11 + 1];     passwd = getpwuid(sb->st_uid);     group = getgrgid(sb->st_gid);     strmode(sb->st_mode, filemode);     printf("%s", filemode);     if (passwd)         printf("%s", passwd->pw_name);     else         printf("%d", sb->st_uid);     if (group)         printf("%s", group->gr_name);     else         printf("%d", sb->st_gid);     printf("%u %s\n", (unsigned int)sb->st_size, name); } int main(int argc, char **argv) {     char        *p;     int          shm_fd;     struct stat  sb;     CHECK_ARGS(2, "<path>");     if ((shm_fd = shm_open(argv[1], 0)) < 0) {         perror("shm_open");         exit(1);     }     if (fstat(shm_fd, &sb)) {         perror("fstat");         exit(1);     }     print_stat_info(argv[1], &sb);     p = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, shm_fd, 0);     printf("Contents: %s\n", p);     munmap(p, sb.st_size);     close(shm_fd);     exit(0); } // shm_unlink.c #include "shm_common.h" #define PROGNAME "shm_unlink" int main(int argc, char **argv) {     int ret = 0;     CHECK_ARGS(2, "<path>");     if ((ret = shm_unlink(argv[1])))         perror("shm_unlink");     exit(ret); } $ gcc -Wall -o shm_create shm_create.c $ gcc -Wall -o shm_info shm_info.c $ gcc -Wall -o shm_unlink shm_unlink.c $ ./shm_create /shm "what the world wants is character" $ ./shm_info /shm rwx------  amit  amit  4096 /shm Contents: what the world wants is character $ ./shm_unlink /shm $ ./shm_info /shm shm_open: No such file or directory




Mac OS X Internals. A Systems Approach
Mac OS X Internals: A Systems Approach
ISBN: 0321278542
EAN: 2147483647
Year: 2006
Pages: 161
Authors: Amit Singh

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net