describe
edit
Take the operation of a parking lot as an example. For simplicity, suppose there are only three parking spaces in the parking lot, and all three parking spaces are empty at first. At this time, if five cars come at the same time, the doorman will directly let three of them in and then put down the car block. The rest of the cars must wait at the entrance, and the following cars must wait at the entrance. At this moment, a car left the parking lot. When the doorman learned about it, he opened the parking station and put one outside. If he keeps two cars, he can put two more, and so on.
In this parking system, parking spaces are public resources, each car is like a line, and the gatekeeper plays the role of semaphore.
classify
edit
Integer semaphore: The semaphore is an integer.
Record semaphore: In addition to an integer value s.value (count), each semaphore S also has a process waiting queue s.L, which is the identification of each process blocked in the semaphore.
Binary semaphore: only semaphores are allowed to take 0 or 1 values.
Each semaphore must record at least two pieces of information: the value of the semaphore and the process queue waiting for the semaphore. Its type definition is as follows: (expressed in PASCAL-like language)
Semaphore = record
Value: integer;
Queue: ^pcb;;
End;
Among them, PCB is a process control block and a data structure established by the operating system for each process.
S.value & gt=0, and s.queue is empty;
The absolute value of value & lt0, s.value is the number of processes waiting in s.queue;
characteristic
edit
In the abstract, the characteristic of semaphore is that semaphore is a non-negative integer (the number of cars), and all threads/processes (cars) passing through it will subtract one from this integer (of course, to use resources). When the integer value is zero, all threads trying to pass it will be in a waiting state. On the semaphore, we define two operations: wait and release. When a thread calls a wait operation, it either acquires resources and subtracts the semaphore by 1, or waits until the semaphore is greater than or equal to 1. Release is actually the addition of semaphores, which corresponds to the vehicle leaving the parking lot. This operation is called "release" because the resources guarded by semaphores are released.
Operation mode
edit
Semaphores have four operations (including
1.initialize, also known as create int SEM _ init (SEM _ t * SEM, int pshared, unsigned int value);
2.wait, which can also be called suspended int SEM _ wait (SEM _ t * SEM);
3.signal or post int SEM _ post (SEM _ t * SEM);
4.destroy int SEM _ destruction(SEM _ t * SEM); [ 1]
build
edit
Like * * * shared memory, the system also needs to customize a series of proprietary operation functions (semget, semctl, etc. ) is used for the semaphore set. The system command ipcs can view the current status of the system IPC and use the -s parameter after the command. Use the function semget to create or get a semaphore set ID. The prototype of this function is as follows:
# include & ltsys/shm . h & gt;
int semget( key_t key,int nsems,int flag);
The parameter key in the function is used to convert it into an identifier, and each IPC object corresponds to a key. When creating a new * * * shared memory segment, the mode field in ipc_perm structure is assigned with the permission bit corresponding to the parameter flag, and the initialization value of shmid_ds corresponding to the semaphore set is shown in table 1.
Shmid_ds structure initialization value table
Ipc_perm structure data
initial value
Ipc_perm structure data
initial value
Time _ o
Sem_nsems
Nsems
Sem_ctime
System current value
The parameter nsems is a value greater than or equal to 0, which indicates the number of available resources in the semaphore set (when the semaphore is created). When an existing semaphore set is opened, the value of this parameter is 0. This function returns the identifier of the semaphore set (an integer greater than or equal to 0) on success, and–1on failure. The semop function is used to manipulate the semaphore set. The prototype of this function is as follows:
# include & ltsys/SEM . h & gt;
int semop( int semid,struct sembuf semoparray[],size _ t nops);
The parameter semid in the function is the semaphore identifier returned by the semget function, and the parameter nops represents the number of elements in the array pointed by the parameter semoparray. The parameter semoparray is an array pointer of struct sembuf structure type, and the structure sembuf is used to explain the operation to be performed, which is defined as follows:
Structure sembuf{
Unsigned short sem _ num
Short sem _ op
Short sem _ flg
}
In the sembuf structure, sem_num is a resource in the corresponding semaphore set, so its value is an integer from 0 to the total number of resources in the corresponding semaphore set (ipc_perm.sem_nsems). Sem_op indicates the operation to be performed, and sem_flg describes the behavior of the function semop. The value of sem_op is an integer, as shown in Table 2, which lists the detailed value of sem_op and the corresponding operations.
Detailed description of sem_op value
Sem_op
take exercise
positive number
Release the corresponding amount of resources, and add the value of sem_op to the value of semaphore.
The process will block until the corresponding value of the semaphore is 0. When the semaphore is already 0, the function returns immediately. If the value of the semaphore is not 0, the function action is determined according to the IPC_NOWAIT bit of sem_flg. Sem_flg specifies IPC_NOWAIT, and the semop function returns an EAGAIN error. Sem_flg does not specify IPC_NOWAIT, then adds 1 to the semncnt value of the semaphore, and then the process hangs until the following happens. When the semaphore is 0, subtract 1 from the semzcnt value of the semaphore, and the function semop returns successfully. This semaphore is deleted (only the super user or the process that created the user has this permission), and the function smeop returns EIDRM with an error; The process captures the signal and returns it from the signal processing function. In this case, the semncnt value of this semaphore is reduced by 1, and the function semop returns to EINTR with an error.
negative number
Request resources of sem_op absolute value. If the corresponding number of resources can meet the request, the absolute value of SEM _ op is subtracted from the value of the semaphore, and the function returns successfully. This operation is related to sem_flg when the corresponding number of resources cannot satisfy the request. Sem_flg specifies IPC_NOWAIT, and the semop function returns an EAGAIN error. If IPC_NOWAIT is not specified by sem_flg, the semncnt value of the semaphore is increased by 1, and then the process is suspended until the following happens: when the corresponding number of resources can satisfy the request, the absolute value of sem_op is subtracted from the value of the signal. Successfully returned; This semaphore is deleted (only the super user or the process that created the user has this right), and the function smeop returns EIDRM in case of error: the process captures the signal and returns it from the signal processing function, in which case the semncnt value of this semaphore is reduced by 1, and the function semop returns EINTR in case of error.
Basic process
edit
The following example demonstrates the basic flow of semaphore operation. The Semget function is used to create a semaphore set, and the semop function is used to perform a resource release operation on this semaphore set. And use the commands in the shell to view the status of the system IPC.
(1) Edit the program in the vi editor.
Program listing14-10create _ sem.c uses the semget function to create a semaphore.
# include & ltsys/types . h & gt;
# include & ltsys/IPC . h & gt;
# include & ltsys/SEM . h & gt;
# include & ltstdio.h & gt
# include & ltstdlib.h & gt
int main( void)
{
int sem _ id
int nsems = 1;
int flags = 0666
struct sembuf buf
sem_id = semget(IPC_PRIVATE,nsems,flags); /* Create a new semaphore set */
if(SEM _ id & lt; 0 ){
perror(“SEM get”);
Exit (1);
}
/* Output the corresponding semaphore set identifier */
Printf ("Semaphore successfully created: %d\n", SEM _ id);
buf . SEM _ num = 0; /* Define semaphore operations */
buf . SEM _ op = 1; /* Perform resource release operation */
Buf.sem _ flg = IPC _ NOWAIT/* Define the behavior of the semop function */
if ( (semop( sem_id,& ampbuf,nsems))& lt; 0) {/* Perform the operation */
perror(“semop”);
Exit (1);
}
System ("IPCS-S"); /* View system IPC status */
Exit (0);
}
(2) Compile the program in vmware, as shown below:
gcc -o a.o testc_semaphore.c
(3) Run the program in the shell, as shown below:
. /a3.o
Successfully created semaphore: 0
-semaphore array-
Key semi-owner license
0x 000000000 0 zcr 666 1
In the above program, a semaphore set is created with the semget function, and the number of resources in the semaphore set is defined as 1. Then, use the semop function to release the resources. At the end of the program, use the shell command ipcs to check the status of the system IPC.
% Note: The command ipcs parameter -s identifies the semaphore set state of the system IPC.
I hope I can help you, and I hope I can adopt it satisfactorily.