Communication between Linux Environment (IV): Signals
content:
Signature Light Overview Linux Signal Light Signal Lights and Kernel Operation Signals Lights Limits Competition Issues Signals Application Example Reference About the author
related information:
Linux Environment Process Communication (1): Pipelines and Among the Linux Environment Processes (II): Signals (Part) Linux Environment Processes Communication (2): Signal (below) Linux Environment Process Communication (3): Message Queue
In the Linux area:
Tutorial Tools & Product Codes & Component Articles
Zheng Yanxing (mlinux@163.com) National Defense Science Defense University In April 2003, the signal light overview signal light is not large, it mainly provides a shared resource access control mechanism between processes. The process equivalent to the memory, the process can determine if some shared resources can be accessed, and the process can also modify the flag. In addition to access control, you can also be used in process synchronization. The signal light has two types:
Two-value signal light: The simplest signal light form, the value of the signal light can only be 0 or 1, similar to the mutex lock. Note: The two-value signal light can realize the function of mutex, but the two concerns are different. The signal light emphasizes the shared resource, as long as the share resources are available, other processes can also modify the value of the signal light; the mutex is more emphasized, and the process of occupying the resource uses the resource, it must be unlocked by the process itself. Calculate the signal light: The value of the signal light can take any non-negative value (of course by the constraint of the kernel itself). Second, Linux signal Linux is the same as the message queue, in the RED HAD 8.0 release, is the signal light of the system V, like the message queue. Therefore, this article will mainly introduce the system V signal light and its corresponding API. In the case where there is no declaration, the following discussion is all system V signal lights. Note that the system V signal light refers to the count signal set. Third, the signal light and the kernel 1, the system V signal light is continuous, and the signal light set will be truly deleted when the kernel is restored or displayed to delete a signal set. Therefore, the data structure of the recording signal light in the system (Struct IPC_IDS SEM_IDS) is located in the kernel, and all signal lights in the system can find access inlets in structure SEM_IDS. 2, the following figure illustrates how the kernel and the signal light set up: where: struct IPC_IDS SEM_IDS is the global data structure of the record signal light in the kernel; describes a specific signal light and related information.
Among them, the Struct Sem structure is as follows: struct sem {
INT SEMVAL; // Current Value
INT SEMPID / / PID OF Last Operation
}
As can be seen from the above figure, the global data structure Struct IPC_IDS SEM_IDS can access the first member of Struct Kern_iPC_Perm: struct kern_ipc_perm; and each struct kern_ipc_perm can correspond to the specific signal light because there is a key_t type Members Key, and Key uniquely determines a signal set; at the same time, the last member SEM_NSEMS of Structure Struct Kern_ipc_perm determines the order in which the signal is concentrated, so the kernel can record the information of each signal. Kern_IPC_PERM Structure See "Communication between Linux Environment Process (3): Message Queue". Struct Sem_Array See Appendix 1. Fourth, the operation signal light does not have the following three types of message queues: 1. Open or create a signal light and the creation of the message queue is basically the same, no more detailed. 2, the signal light value operation Linux can increase or reduce the value of the signal light, corresponding to the release and possession of the shared resource. See the Semop system calls later. 3, gain or set the signal light attribute: Each of the signal lights in the system corresponds to a Struct Sem_Array structure, which records various information of the signal set, exists in system space. For setting, various information and attributes of the signal set are obtained, and there is an important federal structure in the user space, that is, Union Semun. Members of the joint semun data structure See Appendix 2 Signal Light API 1, File Name to Key Value #include
#include
Key_T FTOK (Char * Pathname, Char Proj);
It returns a key value corresponding to the path PathName, please refer to the communication between Linux Environment Process (3): Message Queue ". 2, Linux unique IPC () call: int ipc (unsigned int call, int first, int second, int third, void * ptr, long fiffh); When the parameter CALL takes different values, three system calls corresponding to the signal light: When Call is Semop, correspond to int SMOP (INT SEMID, STRUCT SEMBUF * SOPS, UNSIGNED NSOPS); When Call is a Semget, correspond to int SMGET (key_t key, int nsems, int SMFLG) call; when Call is Semctl, correspond INT SemctL (int SEMID, INT SEMNUM, INT CMD, Union Semun Arg) is called; these calls will be explained later. Note: I don't advocate the use of the system to call IPC (), and more inclined to use the system V or POSIX process communication API. The reason has been communicated between Linux Environment Processes (3): Message queues are given. 3, the system V signal light API system v message queue API only three, need to include several headers: #include
#include
#include
1) INT SEMGET (key_t key, int nSems, int SMFLG) Parameter key is a key value, obtained by ftok, uniquely identifies a signal set, usage is the same as the key in the msgget (); parameter nSEMS specifies the open or newly created signal light The focus will contain the number of signal lights; the SEMFLG parameter is some flag. The value of the parameter key and semflg, and when to open an existing signal set or create a new signal set is the same as the corresponding part in the msgget (), no longer profit. This call returns a signal set description word corresponding to the health check Key. Call Return: Successfully Returns the signal set description word, otherwise returns -1. Note: If the signal light represented by Key already exists, the semget specifies the IPC_CREAT | IPC_EXCL flag, even if the number of parameters NSEMS is not equal, the return is also an Eexist error; if the semget specifies the IPC_CREAT flag, the parameter NSEMS must Consistent with the original value, further explanatory in the later program example. 2) INT SEMOP (INT SEMID, STRUCT SEMBUF * SOPS, UNSIGNED NSOPS); SEMID is the signal light set ID, and SOPS points to each SEMBUF structure of the array portrayed an operation on a particular signal. NSOPS points to the size of the array to SOPS. The SEMBUF structure is as follows: struct sembuf {
Unsigned short sem_num; / * semaphore index in array * /
Short Sem_op; / * Semaphore Operation * /
Short Sem_flg; / * Operation Flags * /
}
SEM_NUM corresponds to signal lights in the signal set, 0 corresponds to the first signal light. SEM_FLG can take two flags of IPC_nowait and SEM_UNDO. If the SEM_UNDO flag is set, the corresponding operation will be canceled at the end of the process, which is a more important flag. If the flag is set, the kernel will be released when you exit when the process does not release the shared resource. If the flag is set for a signal, the kernel is to allocate a SEM_UNDO structure to record it, which is to ensure that the resource is securely released. In fact, if the process exits, then it is released, but the signal light value has not changed. At this time, the signal light value reflects the actual situation of resources, in which case the problem solves the kernel To be done. This is a bit like a zombie process, although the process is exited, the resources are all released, but there is still its record in the kernel process table. At this time, the parent process calls WaitPid to solve the problem. The value of SEM_OP is greater than 0, equal to 0 and less than 0, and three operations performed on the signal specified by SEM_NUM are determined. Please refer to the Linux corresponding manual page for details. Here, it is important to emphasize Semop simultaneously to operate multiple signal lights, in practical applications, corresponding to the application or release of multiple resources. Semop ensures atomicity of operation, this is especially important. Especially for the application of a variety of resources, all resources will be obtained in one time, or give it to the application, either continue to wait in any resource situation, so that on the one hand, avoid the waste of resources; on the other hand, avoid the process Deadlocking is caused by applying for a shared resource. Perhaps better understanding these operations from the actual meaning: the current value of the signal light records the current available number; SEM_OP> 0 corresponds to the corresponding process to release the number of share resources of SEM_OP; SEM_OP = 0 can be used to use whether the shared resource has been used Test; SEM_OP <0 is equivalent to the process to apply for -Sem_op shared resources. The atomicity of the Lenovo operation is more unharmonic to understand when the system calls back, when sleeps waiting. Call Return: Returns 0 successfully, otherwise returns -1. 3) INT SEMCTL (int SemID, int SMNUM, INT CMD, Union Semun Arg) This system call implements various control operations for the signal light, parameter SEMID specifies signal light set, parameter cmd specifies specific operation type; parameter semnum specifies which signal light Operation, only make sense to several special CMD operations; Arg is used to set or return signal light information. Please refer to its manual page for details, and only the operations specified by the parameter CMD here are given here.
IPC_STAT Gets the signal information, the information is returned by arg.buf; IPC_set sets the signal information, and the information to be set is saved in arg.buf (which information can be set); GetAll returns all signal lights, and the result is saved in arg In. ax, parameter SENNUM is ignored; getncnt returns the number of processes that wait for the value of the signal indicating the SEMNUM, which is equivalent to a shared resource represented by the signal light waiting for the Semnum represented; getPid returns the last pair of Semnum Representative Perform the process ID of the Semop operation; getVal returns the value of the signal light representative of semnum; getzcnt returns the number of processes that are waiting for the signal indicating the SEMNUM; setall updates the value of all signal lights through arg.Array; at the same time, update and this signal set sem_ctime semid_ds members associated structure; SETVAL lights is provided semnum arg.val represented; call return: call failed returns -1, associated with the successful return cmd: Cmdreturn valueGETNCNTSemncntGETPIDSempidGETVALSemvalGETZCNTSemzcnt five restriction lights 1, a system may call semop At the same time, the number of signal lights in Semopm, and the parameter nsops in Semop will return E2BIG errors if exceeded this. Semopm size specific and system, redhat 8.0 is 32. 2, the maximum number of signal lights: SEMVMX, when setting the signal value exceeds this limit, the ERANGE error is returned. This value is 32767 in RedHat 8.0. 3, the maximum number of SemMNIs in the system range SemMNI and the maximum number of SEMMNs within the system range. More than these two restrictions will return ENOSPC errors. This value is 32000 in RedHat 8.0. 4, the maximum number of signal lights in each signal set SEMMSL, RedHat 8.0 is 250. Semopm and SemVMX should be noted when using Semop calls; SemMNI and SEMMNS should be noted when calling semget. Semvmx should also be noted at SemctL calls. 6. The first process of competition issues is also initializing the signal light at the same time, so that the system calls the SEMGET contains two steps: create a signal, initializing the signal. This may result in a competitive state: the first process of creating a signal is initialized, the second process calls the semget, and the signal light already exists. At this time, the second process must have a process of determining whether there is a process is being The ability to initialize the signal light. In Reference [1], a method in which this competitive state is given: When the Semget creates a new signal, the Sem_otime member of the SMD_DS is initialized after 0. Therefore, after the second process is successfully called SemGet, the Semctl can be called again in the IPC_STAT command, waiting for SEM_OTIME to become a non-0 value, at this time, it can be determined that the signal lamp has been initialized. The following figure depicts the production and solution of the competition:
In fact, this solution is based on such a assumption: the first process of creating a signal must call Semop, so SEM_OTIME can become a non-zero value. In addition, because the first process may not be called Semop, or the Semop operation takes a long time, the second process may wait for a long time, or wait for a long time. 7. Signal Light Application Example This instance has two purposes: 1. Get various signal light information; 2. Use the signal light to implement the application and release of shared resources. Detailed comments are given in the program. #include
#include
#include
#define sem_path "/ unix / my_sem"
#define max_tries 3
Int semid;
Main ()
{
INT FLAG1, FLAG2, Key, I, Init_ok, TMPERRNO;
Struct Semid_DS SEM_INFO;
Struct Seminfo Sem_info2;
Union semun arg; // union semun: please refer to Appendix 2
Struct Sembuf askFOR_RES, FREE_RES;
FLAG1 = IPC_CREAT | IPC_EXCL | 00666;
FLAG2 = IPC_CREAT | 00666;
Key = fTOK (SEM_PATH, 'A');
// Error Handling for FTOK Here;
INIT_OK = 0;
Semid = Semget (Key, 1, Flag1); // CREATE A Semaphore Set That Only Includes One Semphore.
IF (SEMID <0)
{
TMPERRNO = Errno;
PERROR ("Semget");
IF (TMPERRNO == EEXIST)
// Errno is undefined After a successful library call (include "SO it is saved // in TmPerrno.
{
SEMID = SEMGET (Key, 1, FLAG2);
// Flag2 only contains the IPC_CREAT flag, the parameter NSEMS (here 1) must match the number of the original signal lights
Arg.buf = & sem_info;
For (i = 0; i { IF (Semctl (SemID, 0, IPC_STAT, ARG) == - 1) {PERROR ("Semctl Error"); i = max_tries;} Else { IF (arg.buf-> sem_otime! = 0) {i = max_Tries; init_ok = 1;} Else Sleep (1); } } IF (! init_ok) // do some initializing, here we associate That the first process That Creates The Sem Will // Finish Initialize The Sem and Run Semop in Max_Tries * 1 Seconds. Else It Will Not Run // Semop Any More. { Arg.val = 1; IF (SemCTL (SEMID, 0, SetVal, Arg) == - 1) PERROR ("Semctl SetVal Error"); } } Else {PERROR ("Semget Error, Process Exit"; exit ();}} Else // Semid> = 0; do some initializing { Arg.val = 1; IF (SemctL (SemID, 0, SetVal, Arg) == - 1) PERROR ("Semctl SetVal Error"; } // Get Some Information About The Semaphore and The Limit of Semaphore In RedHat 8.0 Arg.buf = & sem_info; IF (Semctl (SemID, 0, IPC_STAT, ARG) == - 1) PERROR ("SemctL IPC Stat"); Printf ("Owner's UID IS% D / N", arg.buf-> sem_perm.uid); Printf ("Owner's GID IS% D / N", arg.buf-> sem_perm.gid); Printf ("Creater's UID IS% D / N", Arg.buf-> SEM_PERM.CUID); Printf ("Creater's GID IS% D / N", Arg.buf-> SEM_PERM.CGID); Arg .__ buf = & sem_info2; IF (SemcTl (SemID, 0, IPC_INFO, ARG) == - 1) PERROR ("SemctL IPC_INFO"); Printf ("THE NUMBER OF ENTRIES IN SEMAPHORE MAP IS% D / N", arg .__ buf-> semmap; Printf ("Max Number of Semaphore Identifiers IS% D / N", arg .__ buf-> semmni); Printf ("Mas Number of Semaphores in System IS% D / N", arg .__ buf-> semmp); Printf ("THE NUMBER OF STRUCTURES SYSTEM WIDE IS% D / N", arg .__ buf-> semnu); Printf ("Max Number of Semaphores Per Semid IS% D / N", arg .__ buf-> semmsl); Printf ("Max Number of Ops Per Semop Call IS% D / N", arg .__ buf-> semopm; Printf ("Max Number of undo Entries Per Process IS% D / N", arg .__ buf-> semume); Printf ("THE SIZEOF OF OF STRUCT SEM_UNDO IS% D / N", arg .__ buf-> semusz); Printf ("THE MAXIMUM SEMAPHORE VALUE IS% D / N", arg .__ buf-> semvmx); // Now ask for available resource: askFOR_RES.SEM_NUM = 0; askFOR_RES.SEM_OP = -1; askFOR_RES.SEM_FLG = SEM_UNDO; IF (Semop (SemID, & askFOR_RES, 1) == - 1) // ask for resourceperror ("semop error"); Sleep (3); // do some handling on the sharing resource here, Just Sleep On It 3 Seconds Printf ("now free the resource / n"); // Now free resource Free_res.sem_num = 0; Free_res.sem_op = 1; Free_res.sem_flg = SEM_UNDO; IF (Semop (SemID, & Free_RES, 1) == - 1) // Free the resource. IF (errno == EIDRM) Printf ("The Semaphore Set Was Removed / N); // you can comment out the code Below to Compile A Different Version: IF (SemctL (SemID, 0, IPC_rmid) == - 1) PERROR ("SemctL IPC_rmid"); Else Printf ("REMOVE SEM OK / N"); } Note: The reader can try to release the initialization steps, what is the situation in the process (sleep when the process is applied), while the procedure is given to two different versions . Below is the operation result of this program (operating system redhat 8.0): Owner's Uid IS 0 Owner's GID IS 0 Creater's Uid IS 0 Creater's GID IS 0 The Number of Entries in SemaPhore Map IS 32000 Max Number of Semaphore Identifiers IS 128 Mas Number of semaphores in system is 32000 The Number of undo structures system wide is 32000 Max number of semaphores per semi is 250 Max Number of Ops Per Semop Call IS 32 Max Number of undo entries per process is 32 The sizeof of struct SEM_UNDO IS 20 The maximum semaphore value is 32767 Now free the resource REMOVE SEM OK Summary: The signal light is different from other processes. It is mainly used for synchronization between processes. Usually, the system V signal light is actually a collection of signal lights, which can be used inter-synchronization between multiple shared resources. Each signal is a value, which can be used to represent the number of shared resources represented by the signal indicator. If a process is to apply for a shared resource, then subtract the number of applications from the signal light value, if there is not enough current The available resources, the process can sleep, or return it immediately. When the process is to apply for a variety of shared resources, Linux ensures the atomicity of the operation, that is, please apply to all shared resources, or give up all resources, this can ensure that multiple processes will not lock. Linux has a variety of restrictions on the signal light, and the output is given in the program. In addition, if the reader wants to make a further understanding of the signal light, it is recommended to read the SEM.H source code, which is not long, but gives an important data structure related to the signal light. Appendix 1: Struct Sem_Array as follows: / * Each signal light set in the system corresponds to a SEM_ARRAY structure * / Struct Sem_Array { Struct Kern_iPC_Perm Sem_Perm; / * permissions .. see ipc.h * / Time_t sem_otime; / * Last Semop Time * / Time_t sem_ctime; / * last change time * / Struct Sem * Sem_Base; / * Ptr To First Semaphore in Array * / Struct Sem_queue * Sem_pend; / * Pending Operations To Be Processed * / Struct Sem_Queue ** SEM_PENDING_LAST; / * Last Pending Operation * / Struct Sem_undo * Undo; / * undo requests on this array * / Unsigned long sem_nsems; / * no. of semaphores in array * / } Among them, the SEM_QUEUE structure is as follows: / * In the system, every time due to the signal light, there correspond to a SEM_QUEUE structure * / Struct Sem_Queue { Struct Sem_Queue * next; / * Next Entry in the queue * / Struct Sem_queue ** prev; / * previous entry in queue, * (q-> prev) == q * / Struct Task_struct * Sleeper; / * this process * / Struct Sem_undo * Undo; / * undo structure * / Int pid; / * process id of requesting process * / Int status; / * Completion status of operation * / Struct Sem_Array * SMA; / * Semaphore Array for Operations * / INT ID; / * Internal SEM ID * / Struct Sembuf * SOPS; / * Array of Pending Operations * / Int nsops; / * number of operations * / Int alter; / * Operation will alter semaphore * /}; Appendix 2: Union semun is an important parameter in the system calling SemCTL: Union semun { Int val; / * value for setval * / Struct Semid_ds * buf; / * buffer for ipc_stat & ipc_set * / Unsigned short * array; / * array for getall & setall * / Struct seminfo * __ buf; / * buffer for IPC_INFO * / / / TEST !! Void * __Pad; } Struct seminfo { Int semmap; Int semni; Int semmp; Int semnu; Int Semmsl; int SMOPM; Int semume; Int semusz; Int semvmx; Int semaem; } References: [1] UNIX Network Programming Volume II: inter-process communication, Author: W.Richard Stevens, translator: Yang Ji Zhang, Tsinghua University Press. It has an explanation of POSIX and system V signal lights that have great inspiration for procedures in the Linux environment. [2] Linux kernel source code scenario analysis (on), Maunde, Hu Ximing, Zhejiang University Press, gives the source code analysis related to the system V signal light, especially in terms of ensuring operational atomicity, and elaborating the UNDO logo The discussion is very profound. [3] GNU / Linux Programming Guide, Second Edition, Kurt Wall waiting, Zhang Hui translation [4] semget, semop, semctl Manual About the author: Zheng Yanxing, National Defense Science and PhD. Contact: mlinux@163.com