**************************************************************************************************The POSIX semaphore semaphore is a primitive that is used to provide synchronization between different threads of different processes or a given process. This book discusses the types of semaphores in 3. POSIX-known semaphores: Use the POSIX IPC name identifier, which can be used for synchronization between processes or threads. POSIX memory-based semaphores: stored in shared memory and can be used for synchronization between processes or threads. System V semaphores: maintained in the kernel and can be used for synchronization between processes or threads. The function Sem_open creates a new known semaphore or opens a known semaphore that already exists. A well-known semaphore can always be used for inter-thread synchronization and for inter-process synchronization. #include<semaphore.h>sem_t*sem_open (Const Char*name,intFlag,.../*mode_t mode,unsigned int value*/); return: The pointer to the semaphore if successful, or the Sem_failedoflag parameter can be 0,o_creat or o_creat if an error occurs|O_excl, if the O_CREAT flag is specified, then the third and fourth parameters are required: Where the mode parameter specifies the permission bit, the value parameter specifies the initial value of the semaphore. The initial value cannot exceed Zsem_value_max (this constant must be at least 32767). The initial value of the binary semaphore is typically 1, and the initial value of the count semaphore is often greater than 1. If O_creat is specified (without o_excl, it is initialized only if the required semaphore is not already present.) However, specifying O_EXCL is not an error when the required semaphore is already present. This flag simply means that if the required semaphore does not already exist, create and initialize it. However, if the required semaphore is present, the specified o_creat|O_excl is indeed a mistake. The return value of Sem_open is a pointer to a sem_t data type. The pointer is then Sem_close,sem_wait,sem_trywait,sem_post, along with the parameters of the Sem_getvalue. Use Sem_open to open a known semaphore and turn it off using Sem_close. #include<semaphore.h>intSem_close (sem_t *sem_t); Returns: 0 if successful, if the error is-1when a process terminates, the kernel also automatically performs such semaphore shutdown on all known semaphores that are still open on it. This automatic shutdown occurs regardless of whether the process is voluntarily terminated (by calling exit or _exit) or involuntary termination. Closing a semaphore does not remove him from the system. This means that the POSIX-known semaphore is at least persistent with the kernel: even if no process currently has a semaphore open, his value remains. A well-known semaphore is removed from the system using Sem_unlink. #include<semaphore.h>#sem_unlink (Const Char*name); Each semaphore has a counter that records the current number of open times (just like a file), sem_unlink similar to file I/O's unlink function: When the reference count is greater than 0 o'clock, name can be removed from the file system, but the destructor of its semaphore (unlike deleting his name from the file system) waits until the last sem_close occurs. The sem_wait and Sem_trywait functions sem_wait function tests the value of the semaphore specified, and if the value is greater than 0, subtract 1 and return immediately. If the value equals 0, the calling thread is put into sleep until the value becomes greater than 0, and then it is reduced by 1, and the function then returns. #include<semaphore.h>intSem_wait (sem_t *sem)intSem_trywait (sem_t *SEM) are returned: If the success is 0, if the error is-1the difference between sem_wait and sen_trywait is that when the value of the specified semaphore is already 0 o'clock, the latter does not put the calling thread to sleep, instead he returns an error; Sem_post and Sem_getvalue functions when a thread uses a semaphore to complete, He should call Sem_post. This function adds 1 to the specified semaphore, and then wakes up any thread that is waiting for the semaphore value to become a positive number. #include<semaphore.h>intSem_post (sem_t *sem);intSem_getvalue (sem_t *sem,int*Valp); all success: 0 If successful, if the error is-1Sem_getvalue Returns the current value of the specified semaphore in the integer pointed to by Valp. If the semaphore is locked above the current value, the return value or 0, or a negative number, is the absolute value of the thread waiting for the semaphore to be unlocked. The preceding content deals with POSIX-known semaphores. These semaphores are identified by a name parameter, which usually refers to a file in a system file. However, POSIX also provides memory-based semaphores, which are allocated by the application to the memory space of the semaphore (that is, allocating a memory space of the sem_t data type), and then the system initializes their values. #include<semaphore.h>intSem_init (sem_t *sem,intshared,unsignedintvalue); return: If an error occurs-1;intSem_destory (sem_t *( SEM); Returns: 0 if successful, if error is-1The memory-based semaphore is initialized by Sem_init. The SEM parameter points to the sem_t variable that the application must allocate. If shared is 0, the amount of semaphore to initialize is shared among threads in the same process, otherwise the semaphore is shared between processes. When shared is non-0 o'clock, the semaphore must be placed in a certain type of shared memory, and all processes that are about to use it will be able to access the shared memory area. As with Sem_open, the value parameter is the initial value of the semaphore. After using a memory-based semaphore, we call Sem_destory to destroy it. Sem_open does not require a shared-like parameter, because a well-known signal can always be shared between different processes. Note that memory-based semaphores do not use anything similar to the O_CREAT flag, that is, Sem_init always initializes the value of the semaphore. Therefore, for a given semaphore, we must be careful to ensure that only sem_init is called once. For an initialized semaphore call Sem_init the result is undefined. Your assurance understands the fundamental differences between Sem_open and Sem_init. The former returns a pointer to a sem_t variable that is assigned and initialized by the Sem_open function itself. The first argument of the latter points to a pointer to a sem_t variable that is assigned by the caller and then initialized by Sem_init. The amount of memory-based semaphores can be changed when the name associated with the semaphore is not required. A well-known semaphore is typically used when the semaphore is used by different processes that are not related to each other. Memory-based semaphores have at least the continuity of the process, but their true durability depends on the type of memory that holds the semaphore. This semaphore persists as long as the memory area containing a memory semaphore is valid. 1>if the semaphore based on one memory is shared by each thread of a single process (Sem_init's shared parameter is 0), then the semaphore has the duration of the process and it disappears when the process terminates. 2>if a memory-based semaphore is shared between different processes (the shared parameter of Sem_init is 1), the semaphore must be placed in the shared memory area so that the semaphore continues to exist as long as the shared memory area persists. Both the POSIX shared memory area and the System V shared memory area have persistence with the kernel. This means that the server creates a shared memory area, and then initializes a POSIX memory-based semaphore in that memory area, and then terminates. After a period of time, one or more customers can open the shared memory area to access the memory-based semaphores in which they exist. Be careful, the following code does not work as expected. sem_t Mysem;sem_init (&mysem,1,0)if(fork () = =0){// Child.... Sem_post (&Mysem);} Sem_wait (&MYSEM);//parent;wait for childthe problem is that the semaphore Mysem is not in the shared memory area, and the child processes that fork out typically do not share the memory space of the parent process. A child process is started on a copy of the parent process's memory space, which is not the same as the shared memory area. Inter-process shared semaphores the rules for sharing semaphores in memory-based semaphores are simple: the semaphore itself (whose address as the sem_t data type variable of the first parameter of Semz_init) must reside in the memory area shared by all the processes that want to share it, and sem_ The second parameter of Init must be 1. As for the well-known semaphores, the different processes (whether or not they are related to each other) always have enough access to the same famous semaphore, as long as they specify the same name when calling Sem_open. Even for a given name, the Sem_open call may return different pointers in each process, and the semaphore functions that use that pointer (Sem_post and sem_wait) are still referenced by the same well-known semaphore. What if we call fork after calling Sem_open to return a pointer to a sem_t data type variable? In POSIX, the fork function describes "if any signal is opened in the parent process, it should still be opened in the child process." "This means that the following code is correct: sem_t*mutex;/*global pointer that's copied across the fork*///parent creates named semaphoreMutex=sem_open (name,o_creat| O_excl,file_mode,0)if((Child==fork ()) = =0){ // Child... sem_wait (mutex);}//ParentSem_post (mutex); We must carefully figure out when it is possible or not to share a semaphore between different processes: the state of a semaphore can be contained in its own sem_t data type, but it may also use other information such as file descriptors. We'll see in the next chapter that the only handle to a System V semaphore is the integer identifier returned by Semget. Any process that knows about this identifier can access the semaphore. All states of the System V semaphore are contained in the kernel, and their integer identifiers simply tell the kernel to specifically reference that semaphore. ***************************************************************************************POSIX shared memory area memory map file-mmaped file): Shared Memory Area object (shared--mmaped file), opened by the Open function, which is mapped to a file in the current process address space by the MMAP function: A POSIX is opened by Shm_open.1The IPC name (perhaps a path name in the file system), and the descriptor returned is mapped by the MMAP function to the current process address space. Both techniques use the mmap technique, the difference being the acquisition of descriptors as one of the parameters of the mmap: by open or through Shm_pen. POSIX memory map file FD=Open (pathname,....); PTR=mmap (..., fd,.....); POSIX shared memory Area object FD=shm_open (name, ...) ); PTR=Mmap (.... , FD,.....); The POSIX memory sharing area involves the following two step requirements. (1specifies a name parameter called Shm_open to create a new shared memory area object or to open an existing shared memory area object. (2call Mmap to map this shared memory area to the address space of the calling process. The name parameter passed to Shm_open is then used by any process that wants to share the memory area. #include<sys/mman.h>intShm_open (Const Char*name,intoflag,mode_t mode); Returns: a non-negative descriptor if successful;-1;intShm_unlink (Const Char*name); Returns: 0 if successful, or if the error is-1; Name parameter: The name of the shared memory area, you can define a name yourself; the Oflag parameter must either contain a o_rdonly (read-only) flag, or contain a o_rdwr (read-write) flag, or you can specify the following flag: O_CREAT,O_EXCL, or O_ TRUNC. If the O_TRUNC flag is specified with O_RDWR and the required memory space already exists, then he will be truncated to 0 length. The mode parameter specifies the permission bit, which is used if the O_CREAT flag is specified. Note Unlike the Mq_open and Sem_open functions, the mode parameter of the Shm_open must always be specified. If the O_CREAT flag is not specified, then the parameter can be specified as the return value of 0;shm_open is an integer descriptor, which is then used as the 5th parameter of the mmap. The Shm_unlink function deletes the name of a shared memory area object. Like all the other unlink functions (removing the unlink of a pathname from a file system, deleting a POSIX message queue mq_unlink, and deleting a POSIX-known semaphore Sem_unlink), Deleting a name does not affect existing references to its underlying support object until all of the references are closed. Deleting a name only prevents the subsequent open or Sem_open call from succeeding. When the ftruncate and Fstat functions handle mmap, the size of the normal file or the shared memory area object can be modified by calling Ftruncate. # include<unistd.h>POSIX has a slightly different definition of the function's handling of normal files and shared memory area objects. 1>for a normal file: If the file size is larger than the length parameter, the additional data is discarded. If the file size is less than length, then the file is unmodified and its size is not increased. Actually for an ordinary file, the portable method of expanding his size to length byte is: first lseek to offset to length-1, and then write 1 bytes of data. Fortunately, almost all UNIX implementations support the use of Ftruncate to extend a file. 2>for a shared Memory area object: Ftruncate Sets the size of the object to length bytes. We call Ftruncate to specify the size of the newly created shared memory area object, or to modify the size of an existing object. When opening a shared memory area object that already exists, we can call Fstat to get information about the object. #include<sys/type.h>#include<sys/stat.h>intFstat (intFdstructStat *buf); Returns: 0 if successful, if the error is-1;
POSIX interprocess communication