Advanced Programming in UNIX Environment Episode 94

Many implementations provide anonymous memory mapping, a facility similar to the /dev/zero feature. To use this facility, we specify the MAP_ANON flag to mmap and specify the file descriptor as −1. The resulting region is anonymous (since it’s not associated with a pathname through a file descriptor) and creates a memory region that can be shared with descendant processes.

The anonymous memory-mapping facility is supported by all four platforms discussed in this text. Note, however, that Linux defines the MAP_ANONYMOUS flag for this facility, but defines the MAP_ANON flag to be the same value for improved application portability.

The POSIX semaphore mechanism is one of three IPC mechanisms that originated with the real-time extensions to POSIX.1. The Single UNIX Specification placed the three mechanisms (message queues, semaphores, and shared memory) in option classes. Prior to SUSv4, the POSIX semaphore interfaces were included in the semaphores option. In SUSv4, these interfaces were moved to the base specification, but the message queue and shared memory interfaces remained optional.

The POSIX semaphore interfaces were meant to address several deficiencies with the XSI semaphore interfaces:

  • The POSIX semaphore interfaces allow for higher-performance implementations compared to XSI semaphores.
  • The POSIX semaphore interfaces are simpler to use: there are no semaphore sets, and several of the interfaces are patterned after familiar file system operations. Although there is no requirement that they be implemented in the file system, some systems do take this approach.
  • The POSIX semaphores behave more gracefully when removed. Recall that when an XSI semaphore is removed, operations using the same semaphore identifier fail with errno set to EIDRM. With POSIX semaphores, operations continue to work normally until the last reference to the semaphore is released.

POSIX semaphores are available in two flavors: named and unnamed. They differ in how they are created and destroyed, but otherwise work the same.

To create a new named semaphore or use an existing one, we call the sem_open
function.

#include 
sem_t *sem_open(const char *name, int oflag,

When using an existing named semaphore, we specify only two arguments: the name of the semaphore and a zero value for the oflag argument. When the oflag argument has the O_CREAT flag set, we create a new named semaphore if it does not yet exist. If it already exists, it is opened for use, but no additional initialization takes place.

To promote portability, we must follow certain conventions when selecting a semaphore name.

  • The first character in the name should be a slash (/).
  • The name should contain no other slashes to avoid implementation-defined behavior.
  • The maximum length of the semaphore name is implementation defined. The name should be no longer than _POSIX_NAME_MAX (Figure 2.8) characters, because this is the minimum acceptable limit to the maximum name length if the implementation does use the file system.

The sem_open function returns a semaphore pointer that we can pass to other semaphore functions when we want to operate on the semaphore.

#include 
int sem_close(sem_t *sem);

To destroy a named semaphore, we can use the sem_unlink function.

#include 
int sem_unlink(const char *name);

The sem_unlink function removes the name of the semaphore. If there are no open references to the semaphore, then it is destroyed. Otherwise, destruction is deferred until the last open reference is closed.

Unlike with XSI semaphores, we can only adjust the value of a POSIX semaphore by one with a single function call. Decrementing the count is analogous to locking a binary semaphore or acquiring a resource associated with a counting semaphore.

Note that there is no distinction of semaphore type with POSIX semaphores. Whether we use a binary semaphore or a counting semaphore depends on how we initialize and use the semaphore. If a semaphore only ever has a value of 0 or 1, then it is a binary semaphore. When a binary semaphore has a value of 1, we say that it is ‘‘unlocked;’’ when it has a value of 0, we say that it is ‘‘locked.’’

To decrement the value of a semaphore, we can use either the sem_wait or sem_trywait function.

#include 
int sem_trywait(sem_t *sem);
int sem_wait(sem_t *sem);

With the sem_wait function, we will block if the semaphore count is 0. We won’t return until we have successfully decremented the semaphore count or are interrupted by a signal.

A third alternative is to block for a bounded amount of time. We can use the sem_timedwait function for this purpose.

#include 
#include 
int sem_timedwait(sem_t *restrict sem,
const struct timespec *restrict tsptr);

To increment the value of a semaphore, we call the sem_post function. This is analogous to unlocking a binary semaphore or releasing a resource associated with a counting semaphore.

#include 
int sem_post(sem_t *sem);

When we want to use POSIX semaphores within a single process, it is easier to use unnamed semaphores. This only changes the way we create and destroy the semaphore. To create an unnamed semaphore, we call the sem_init function.

#include 
int sem_init(sem_t *sem, int pshared, unsigned int value);

When we are done using the unnamed semaphore, we can discard it by calling the sem_destroy function.

#include 
int sem_destroy(sem_t *sem);

One other function is available to allow us to retrieve the value of a semaphore. We call the sem_getvalue function for this purpose.

#include 
int sem_getvalue(sem_t *restrict sem, int *restrict valp);

Unless we use additional synchronization mechanisms to avoid this race, the sem_getvalue function is useful only for debugging.

The sem_getvalue function is not supported by Mac OS X 10.6.8.

你可能感兴趣的:(Advanced,Programming,in,the,Unix,Environment)