Linux inter-process communication-Traffic Signals

Source: Internet
Author: User
Tags posix

Https://www.ibm.com/developerworks/cn/linux/l-ipc/part4/ from

 

Introduction:The traffic signal is not the same as that of other processes. It mainly provides resource access control for inter-process sharing. It is equivalent to a memory flag. A process can determine whether it can access some shared resources. At the same time, the process can modify the flag. In addition to access control, it can also be used for process synchronization.

Label of this article:Inter-process communication in linux environment, linux Process, signal light, kernel, encoding

 

 

I. Traffic Signal Overview

The traffic signal is not the same as that of other processes. It mainly provides resource access control for inter-process sharing. It is equivalent to a memory flag. A process can determine whether it can access some shared resources. At the same time, the process can modify the flag. In addition to access control, it can also be used for process synchronization. There are two types of traffic signals:

  • Binary signal light: the simplest form of signal light. The signal light value can only be 0 or 1, similar to mutex lock.
    Note: the binary signal lamp can implement the mutex lock function, but the two have different concerns. The signal lamp emphasizes shared resources. As long as the shared resources are available, other processes can also modify the signal lamp value. The mutex also emphasizes the process. After resources are used by the process, it must be unlocked by the process itself.
  • Computing traffic signal: the traffic signal value can be any non-negative value (of course, subject to the kernel constraints ).
 

Ii. Linux traffic signals

Linux supports traffic signals in the same way as message queue. In red had 8.0 release, the traffic signals of System V are supported. Therefore, this article mainly introduces the system V signal lamp and its corresponding APIs. If there is no declaration, the System V signal lights are described below.

Note that the System V signal lamp usually refers to the Count signal lamp set.

 

3. Signal lights and Kernel

1. The System V traffic signal is continuously maintained with the kernel. This traffic signal set will be deleted only when the kernel restarts or is displayed and deleted. Therefore, the data structure (struct ipc_ids sem_ids) of the recorded signal lights in the system is located in the kernel. All the signal lights in the system can find the access entry in the structure sem_ids.

2. Explain how the kernel is connected with the signal light:

Here, struct ipc_ids sem_ids is the global data structure of the signal lamp recorded in the kernel. It describes a specific signal lamp and its related information.

 

The structure of struct sem is as follows:

struct sem{int semval;// current valueint sempid// pid of last operation}

It can be seen that the global data structure struct ipc_ids sem_ids can access the first member of struct kern_ipc_perm: struct kern_ipc_perm; while each struct kern_ipc_perm can correspond to a specific traffic signal in this structure, there is a key_t member key, and the key uniquely identifies a signal set. At the same time, the last member of the structure struct kern_ipc_perm sem_nsems determines the sequence of the signal lights in the signal set, in this way, the kernel can record the information of each traffic signal. For the kern_ipc_perm structure, see inter-process communication in Linux (3): Message queue. For struct sem_array, see Appendix 1.

 

Iv. Operation signal lights

There are three types of Message Queue operations:

1. Enable or create a signal light
It is basically the same as creating and opening a message queue.

2. Traffic Signal Value operation
In linux, you can increase or decrease the traffic signal value, and release and occupy shared resources accordingly. For more information, see semop system call.

3. Obtain or set the traffic signal properties:
Each traffic signal set in the system corresponds to a struct sem_array structure, which records various information of the traffic signal set and exists in the system space. In order to set and obtain various information and attributes of the traffic signal set, there is an important joint structure in the user space, that is, union semun.

 

For the meanings of the members of the combined semun data structure, see appendix 2.

Signal lamp API

1. file name to key value

#include <sys/types.h>#include <sys/ipc.h>key_t ftok (char*pathname, char proj);

It returns a key value corresponding to the path pathname. For specific usage, see inter-process communication in Linux (3): Message queue.

2. linux-specific ipc () call:

Int ipc (unsigned int call, int first, int second, int third, void * ptr, long second th );

When the call parameter is set to a different value, the three system calls of the corresponding signal are as follows:
When the call is SEMOP, the corresponding int semop (int semid, struct sembuf * sops, unsigned nsops) call;
When the call is SEMGET, the corresponding int semget (key_t key, int nsems, int semflg) call;
When the call is SEMCTL, the corresponding int semctl (int semid, int semnum, int cmd, union semun arg) call;
These calls will be described later.

Note: I do not advocate using the system to call ipc (), but prefer to use the System V or POSIX inter-process communication API. Cause: inter-process communication in Linux (3) is provided in message queue.

3. System V signal lamp API

There are only three System V Message Queue APIs, which must contain several header files:

#include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>

1) int semget (key_t key, int nsems, int semflg)
The parameter key is a key value obtained by ftok and uniquely identifies a signal set. Its usage is the same as the key in msgget; the nsems parameter specifies the number of signals in the enabled or newly created signal set. The semflg parameter indicates some signs. The values of the parameter key and semflg, and when to enable an existing traffic signal set or create a new traffic signal set are the same as those in msgget.
This call returns the signal set description corresponding to the key.
Call and return: The Signal Set description is returned. Otherwise,-1 is returned.
Note: If the signal lamp represented by the key already exists and semget specifies IPC_CREAT | IPC_EXCL, The EEXIST error is returned even if the nsems parameter is different from the number of the original signal lamp; if only the IPC_CREAT flag is specified for semget, The nsems parameter must be consistent with the original value, which will be further described in the subsequent program instance.

2) int semop (int semid, struct sembuf * sops, unsigned nsops );
Semid is the Signal Set ID, and sops points to each sembuf structure of the array to depict an operation on a specific signal. Nsops is the size of the sops pointing to the array.
The sembuf structure is as follows:

struct sembuf {unsigned short  sem_num;/* semaphore index in array */shortsem_op;/* semaphore operation */shortsem_flg;/* operation flags */};

Sem_num corresponds to the signal light in the signal set, and 0 corresponds to the first signal light. Sem_flg can be 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 an important flag. If this flag is set, the kernel is released when the process does not release shared resources. If this flag is set for a traffic signal, the kernel will allocate a sem_undo structure to record it, in order to ensure that future resources can be safely released. In fact, if the process exits, the occupied traffic is released, but the traffic signal value is not changed. At this time, the traffic signal value does not reflect the actual resource occupation, in this case, the kernel is used to solve the problem. This is a bit like a zombie process. Although the process has exited and the resources have been released, its records still exist in the kernel table. In this case, the parent process needs to call waitpid to solve the problem.
The sem_op value is greater than 0, equal to 0, and less than 0. Three operations are performed on the signal lamp specified by sem_num. For details, refer to the corresponding linux manual page.
It should be emphasized that semop operates multiple signal lights at the same time. In actual application, it applies for or releases multiple resources. This is especially important when semop ensures the atomicity of operations. Especially for applications with multiple resources, you can either obtain all resources at a time, or give up the application, or continue to wait without occupying any resources. In this way, the waste of resources is avoided, this avoids deadlocks between processes due to resource sharing applications.
These operations may be better understood from the actual meaning: the current value of the signal lamp records the current available number of resources; sem_op> 0 corresponds to the process to release the shared resources of the number of sem_op; sem_op = 0 can be used to test whether shared resources are used up; sem_op <0 is equivalent to the process requesting-sem_op shared resources. Considering the atomicity of the operations, it is more difficult to understand when the system calls a normal response, and when the system waits for sleep.
Call return: 0 is returned if the call is successful. Otherwise,-1 is returned.

3) int semctl (int semid, int semnum, int cmd, union semun arg)
The system calls various control operations on traffic signals. The semid parameter specifies the traffic signal set, and the cmd parameter specifies the specific operation type. The semnum parameter specifies the traffic signal to operate on, only a few special cmd operations are meaningful; arg is used to set or return signal light information.
For more information about the system call, see the manual page. Only the operation that can be specified by the cmd parameter is provided here.

IPC_STAT Obtains the signal light information, which is returned by arg. buf;
IPC_SET Set the traffic signal information. The information to be set is saved in arg. buf (which information can be set in manpage );
GETALL Returns the values of all traffic signals. The results are saved in arg. array, and the parameter sennum is ignored;
GETNCNT Return the number of processes that increase when the value of the waiting semnum represents the signal lamp, which is equivalent to the number of processes that are currently waiting for the shared resources represented by the signal lamp represented by the semnum;
GETPID Returns the ID of the last process that performs the semop operation on the signal lamp represented by semnum;
GETVAL Returns the value of the signal lamp represented by semnum;
GETZCNT Returns the number of processes that wait for semnum to change the value of the signal lamp to 0;
SETALL Update the values of all traffic signals through arg. array. At the same time, update the sem_ctime Member of the semid_ds structure related to the current signal set;
SETVAL Set the value of the signal lamp represented by semnum to arg. val;

Call return:-1 is returned if the call fails. If the call succeeds, it is related to cmd:

Cmd Return value
GETNCNT Semncnt
GETPID Sempid
GETVAL Semval
GETZCNT Semzcnt
 

5. Restrictions on Traffic Signals

1. SEMOPM is the number of signals that the system can simultaneously operate on when calling semop. If the nsops parameter in semop exceeds this number, the E2BIG error will be returned. SEMOPM size is specific to the system, and redhat 8.0 is 32.

2. Maximum number of traffic signals: SEMVMX. If the traffic signal value exceeds this limit, an ERANGE error is returned. In redhat 8.0, this value is 32767.

3. the maximum number of SEMMNI signal sets in the system range and the maximum number of SEMMNS signals in the system range. If these two limits are exceeded, an ENOSPC error is returned. In redhat 8.0, this value is 32000.

4. the maximum number of SEMMSL signals in each traffic signal set. The value of redhat 8.0 is 250. SEMOPM and SEMVMX should be noted when using semop; SEMMNI and SEMMNS should be noted when calling semget. SEMVMX is also worth noting when calling semctl.

 

Vi. competitive issues

The first process to create a signal lamp also initializes the signal lamp. In this way, the system calls semget and involves two steps: creating a signal lamp and initializing a signal lamp. This may lead to a competition: when the first process that creates a signal lamp initializes the signal lamp, the second process calls semget again and finds that the signal lamp already exists. At this time, the second process must be able to determine whether a process is initializing the traffic signal. In reference [1], a method is provided to bypass this competition: When semget creates a new traffic signal, the value of sem_otime after initialization of the semid_ds traffic signal structure is 0. Therefore, after the second process successfully calls semget, you can use the IPC_STAT command to call semctl again, and wait until sem_otime changes to a non-0 value. At this time, you can determine that the signal lamp has been initialized. Describes the competition status generation and solution:

 

In fact, this solution is based on the assumption that the first process that creates a traffic signal must call semop so that sem_otime can be changed to a non-zero value. In addition, because the first process may not call semop, or the semop operation takes a long time, the second process may wait for an indefinite period of time, or wait for a long time.

 

VII. Traffic Signal Application Example

This instance has two purposes: 1. To obtain information about various traffic signals; 2. To use traffic signals to apply for and release shared resources. Detailed comments are provided in the program.

# Include <linux/sem. h> # include <stdio. h> # include <errno. h> # 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: See 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_o K = 0; semid = semget (key, 1, flag1); // create a semaphore set that only includes des one semphore. if (semid <0) {tmperrno = errno; perror ("semget"); if (tmperrno = EEXIST) // errno is undefined after a successful library call (including perror call) // so it is saved in tmperrno. {semid = semget (key, 1, flag2); // flag2 only contains the IPC_CREAT sign. The parameter nsems (1 here) must be consistent with the number of original signal lights arg. buf = & sem_info; for (I = 0; I <max_tries; I ++) {if (semctl (se Mid, 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 assume 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 redhat8.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-> semmns); printf ("the number of undo structures system wide is % d \ n", arg. _ buf-> semmnu); 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 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; region =-1; region = SEM_UNDO; if (semop (semid, & askfor_res, 1) =-1) // ask for resource perror ("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 codes below to compile a different version: if (semctl (semid, 0, IPC_RMID) =-1) perror ("semctl IPC_RMID"); else printf ("remove sem OK \ n ");}

Note: You can try to comment out the initialization steps, what will happen to the process during running (the process will sleep when applying for resources), and the comments at the end of the program, compile the program into two different versions. The following is the running result of the Program (operating system redhat8.0 ):

owner's uid is 0owner's gid is 0creater's uid is 0creater's gid is 0the 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 semid 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 resourceremove sem ok

Summary: The traffic signal is different from other processes. It is mainly used for inter-process synchronization. Generally speaking, the System V signal lamp is actually a collection of signal lights and can be used for synchronization between processes sharing multiple resources. Each traffic signal has a value that indicates the number of available shared resources (available) represented by the current traffic signal. If a process wants to apply for shared resources, then subtract the number of requests from the traffic signal value. If there is not enough available resources, the process can wait for sleep or return immediately. When a process needs to apply for multiple types of shared resources, linux can ensure the atomicity of operations, that is, either applying for all shared resources or giving up all resources, this ensures that multiple processes do not cause mutual locks. Linux has various restrictions on traffic signals, and the output result is provided in the program. In addition, if you want to further understand the signal lamp, it is recommended to read the sem. h source code. This file is not long, but provides an important data structure related to the signal lamp.

Appendix 1: struct sem_array:

/* Each traffic signal 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_pending;/* 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 */};

The sem_queue structure is as follows:

/* Every process sleeping due to a signal lamp in the system corresponds to a sem_queue structure */struct sem_queue {struct sem_queue * next; /* next entry in the queue */struct sem_queue ** prev;/* previous entry in the 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 Call 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 semmni;int semmns;int semmnu;int semmsl;int semopm;int semume;int semusz;int semvmx;int semaem;};

References

[1] second volume of UNIX Network Programming: inter-process communication, Author: W. Richard Steven S, Translator: Yang jizhang, Tsinghua University Press. Both POSIX and System V signal lights are described, which is of great inspiration for program development in Linux.

[2] Linux kernel source code scenario analysis (I), by Mao decao, Hu Ximing, Zhejiang University Press, provides source code analysis related to system V signal lights, especially in the aspect of ensuring the atomicity of operations and the undo flag, we have discussed it very deeply.

[3] GNU/Linux programming guide, second edition, and Kurt Wall

[4] semget, semop, semctl Manual

About the author

Zheng yanxing, male, is now pursuing a doctorate degree in network direction from the computer College of the National Defense University. You can contact him by email mlinux@163.com.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.