Semaphores for Process Communication

Source: Internet
Author: User
Tags semaphore

 

1. semaphore

1.1. semaphore

Semaphore is a counter that allows multiple processes to access Shared data objects, that is, user management to access resources.

To obtain shared resources, the process must perform the following operations.

1). Test and Control the semaphore of the resource;

2) If the semaphore value is positive, the process can use this resource. A semaphores is reduced by one, indicating that a resource unit is used.

3) if the semaphore value is 0, the process enters the sleep state until the signal value is greater than 0. After a process is awakened, it returns to the first step.

When a process no longer uses a shared resource controlled by a semaphore, this signal value is increased by one. If a process is sleeping and waiting for this semaphore, wake them up.

Therefore, the test and subtraction operations on the signal value should be atomic operations. Therefore, semaphores are implemented in the kernel.

 

Xsi signal set is relatively complex:

1). the semaphore set is not a single non-negative value, but must be defined as a set containing one or more semaphores (values. When creating a semaphore set, you must specify the number of semaphores (values) in the Set;

2). Separate semget from semctl. This is a fatal weakness, because it is not possible to create a semaphore set with an atomic operation and assign an initial value to each semaphore (value) in the set.

3). Even if no process is using any form of xsi IPC, they still exist. Some programs do not release the semaphore set that has been allocated to it at the end of the process, which is worrying.

The kernel sets a semid_ds structure for each semaphore set:

Struct semid_ds {

Struct ipc_perm sem_perm ;//

Unsigned short sem_nsems; // # of semaphores in Set

Time_t sem_otime; // last-semop time

Time_t sem_ctime; // last-Change Time

.

.

.

};

Each semaphore is represented by an unknown structure and has at least the following members:

Struct {

Unsigned short semval; // semaphore value, always> = 0

Pid_t sempid; // PID for last operation

Unsigned short semncnt; // # processes awaiting semval> curval

Unsigned short semzcnt; // # processes awaiting semval = 0

.

.

.

};

 

To obtain a semaphore Set ID, the first function to be called is semget.

# Include <sys/SEM. h>

Int semget (key_t key, int nsems, int flag );

The key of the first parameter is an integer. Unrelated processes can use it to access the same semaphore. A special semaphore key value ipc_private (usually 0) is used to create a semaphore that can only be accessed by the creation process.

The num_sems parameter specifies the number of required semaphores, usually 1.

The flag parameter is a set of identifiers. Its low-end nine bits are the permissions of the semaphore, and its function is similar to the file access permissions. They can perform bitwise OR operations with the value ipc_creat to create a new semaphore. Even if the ipc_creat flag is set, the given key is a key with a semaphore and will not produce errors. Only ipc_creat and ipc_excl are used together to ensure that a new and unique semaphore is created. If the semaphore exists, an error is returned (errno is set to eexsit ).

When the semget function succeeds, a positive (not 0) value is returned, which is the semaphore identifier used by other semaphore functions. If it fails,-1 is returned.

 

The semctl function contains multiple semaphore operations.

# Include <sys/SEM. h>

Int semctl (INT Semid, int semnum, int cmd,

.../* Union semun Arg */);

The fourth parameter is optional. If this parameter is used, its type is semun, which is the union of multiple specific command parameters ):

Union senun {

Int val; // For setval

Struct semid_ds * Buf; // For ipc_stat and ipc_set

Unsigned short * array; // For getall and setall

};

Note: This is a union, not a pointer to the Union.

The parameter semnum is between 0 and nsems-1 (including 0 and nsems-1 ).

The cmd parameter is a type of command in the following 10. Execute this command on the signal set specified by Semid. Five of these commands are specific to a specific semaphore. They are used for semnum to specify a semaphore member in the signal set.

Ipc_stat removes the semid_ds structure from this set and stores it in the structure directed by Arg. Buf.

Ipc_set sets the following three fields in the structure related to this set based on the value pointed by Arg. Buf to the structure; sem_perm.uid, sem_perm.gid, and sem_perm.mode. This command can only be executed by the following two processes: one is the process whose valid user ID is equal to sem_perm.cuid or sem_perm.uid, and the other is a process with super user privileges.

Ipc_rmid: This semaphore set is deleted from the system. This deletion takes effect immediately. When other processes that are still using this semaphore set attempt to operate on this queue, an error is returned. This command can only be executed by two processes: one is that the valid user ID is sem_perm.cuid or sem_perm.uid, and the other is a process with super user privileges. (Common)

Getval returns the semval value of the member semnum.

Setval: Set the semval value of the member semnum. This value is specified by Arg. Val. (Common)

Gettpid returns the sempid value of the member semnum.

Getncnt returns the semncnt value of the member semnum.

Getzcnt returns the semzcnt value of the member semnum.

Getall takes the values of all semaphores in the set and stores them in the array directed by Arg. array.

Setval: Set the values of all semaphores in the set according to the values in the array pointed to by Arg. array.

For all get commands except grtall, The semctl function returns the corresponding value. The return value of other commands is 0.

 

The semop function automatically executes the operation data on the semaphore set, which is an atomic operation.

# Include <sys/SEM. h>

Int semop (INT Semid, struct sembuf semoparray [], size_t NOPs );

The semoparray parameter is a pointer pointing to a semaphore array. The semaphore operation is represented by the sembuf structure:

Struct sembuf {

Unsigned Shor sem_num; // member # In set (, 2,..., nsem-1)

Short sem_op; // operation (negative, 0, or positive)

Shor sem_flg; // ipc_nowait, sem_undo

};

The NOPs parameter specifies the number of operations in the array (meta quantity ).

The following is the Undo flag of the semaphore, which also corresponds to the sem_undo bit of the sem_flg member.

1) The easiest case to handle is that sem_op is positive. This corresponds to the number of resources occupied by the process release. The sem_op value is added to the semaphore value. If the Undo flag is specified, sem_op is also subtracted from the semaphore adjustment value of the process.

2) If sem_op is negative, it indicates that the process needs to obtain resources controlled by the semaphore.

If the semaphore value is greater than or equal to the absolute value of sem_op (with required resources), the absolute value of sem_op is subtracted from the semaphore. This ensures that the result value of the semaphore is greater than or equal to 0. If the Undo flag is specified, sem_op

The absolute value of is also added to the semaphore adjustment value of the process.

If the signal value is smaller than the absolute value of sem_op (the resource cannot meet the requirement), then:

A) if ipc_nowait is specified, an eagain error is returned for semop;

B). If ipc_nowait is not specified, the semncnt value of the semaphore plus one (because the calling process will enter the sleep state), and then the calling process will be suspended until one of the following events occurs:

I). This semaphore is greater than or equal to the absolute value of semp_op (that is, a process has released some resources ). The semncnt value of this semaphore is reduced by one (because the wait has ended), and the absolute value of sem_op is subtracted from the signal value. If the Undo flag is specified, the absolute value of sem_op is also added to the semaphore adjustment value of the process.

Ii). This semaphore is deleted from the system. If a function error occurs, eidrm is returned.

Iii). The process captures a signal and returns it from the signal processing program. In this case, the semncnt value of this semaphore is reduced by one (because the calling process is no longer waiting), and the function returns eintr error.

3). If sem_op is 0, it indicates that the calling process wants to wait until the semaphore value changes to 0.

If the current signal value is 0, this function returns immediately.

If the signal value is not 0:

A) if ipc_nowait is specified, an eagain error is returned for semop;

B). If ipc_nowait is not specified, the semncnt value of the semaphore plus one (because the calling process enters the sleep state), and then the calling process is suspended until one of the following events occurs:

I). The semaphore is 0. The semncnt value of this semaphore is reduced by one (because the call process has finished waiting ).

Ii). This semaphore is deleted from the system. If a function error occurs, eidrm is returned.

Iii). The process captures a signal and returns it from the signal processing program. In this case, the semncnt value of this semaphore is reduced by one (because the calling process is no longer waiting), and the function returns eintr error.

Note: Set it to the Undo flag. If the process terminates without releasing the semaphore, the Operating System Automatically releases the semaphore held by the process.

 

1.2. semaphore and record lock

If multiple processes share one resource, you can use semaphores or record locks.

If semaphores are used, a set of semaphores containing a member is created, and the initial value of the signal value is assigned. To allocate resources, use sem_op as-1 to call semop; to release resources, use sem_op as + 1 to call semop. Specify the sem_undo flag for each operation to terminate the process without releasing resources.

If record lock is used, an empty file is created first, and the first byte (no need to exist) of the file is used as the lock byte. In order to allocate resources, a write lock is obtained for this byte. when resources are released, the byte is unlocked. Record the nature of the lock to ensure that the kernel Automatically releases the lock when the owner process of a lock terminates.

Compared with semaphores, record locks consume much time, but are easy to use.

 

1.3. Instance

This program semaphore. C is used to test semaphores. This program can be called multiple times. An optional parameter is used to specify whether the program is responsible for creating or deleting a semaphore.

The output of two different characters indicates entering and leaving the critical area. If the program starts with a parameter, it prints the character X in the Entry and Exit critical areas, and other running instances of the program print O in the Entry and Exit critical areas. The characters X and O should appear in pairs.

At the beginning of the program, call the ftok and semget functions to obtain the semaphore identifier. Ipc_creat is used to create a semaphore if it does not exist. The function sleep is used to call other program instances before executing multiple cycles. Before the semaphore is deleted, the startup program with parameters enters the waiting state to allow other instances to be executed completely.

The execution result is as follows:

#./Semaphore 1 &

[1] 2072

#./Semaphore

Ooxxooxxooxxooxxooxxooxxooxxooxxooxxooxxxx

2073-finished

2072-finished

#

The source program is as follows:

# Include <stdlib. h> <br/> # include <stdio. h> <br/> # include <string. h> <br/> # include <unistd. h> <br/> # include <errno. h> <br/> # include <sys/types. h> <br/> # include <sys/IPC. h> <br/> # include <sys/SEM. h> </P> <p> # define my_sem_proc_id 4 <br/> # define my_proc_path "/user/local/wzhwho" <br/> static int setsemvalue (void ); // <br/> static void delsemvalue (void); // <br/> static int passerensem (void); // <br/> static I NT vrijgevensem (void); // <br/> static int sem_id; </P> <p> int main (INT argc, char * argv []) <br/>{< br/> int I; <br/> int pausetime; <br/> char opchar = 'O'; <br/> key_t my_sem_kt; </P> <p> srand (unsigned INT) getpid (); <br/>/* obtain the semaphore ID */<br/> my_sem_kt = ftok (my_proc_path, my_proc_rcv_id); <br/> sem_id = semget (my_sem_kt, 1, 0666 | ipc_creat); <br/> // called for the first time, initial semaphores <br/> If (argc> 1) <br/>{< br/> If (0! = Setsemvalue () <br/>{< br/> printf ("failed to initialize semaphore/N"); <br/> exit (exit_failure ); <br/>}< br/> opchar = 'X'; <br/> sleep (2); <br/>}< br/> for (I = 0; I <10; I ++) <br/>{< br/> // enter the critical area and perform the P operation <br/> If (0! = Passerensem () <br/>{< br/> exit (exit_failure); <br/>}< br/> printf ("% C", opchar ); <br/> fflush (stdout); <br/> pausetime = rand () % 3; <br/> sleep (pausetime ); <br/> printf ("% C", opchar); <br/> fflush (stdout); <br/> // exit the critical area, perform the V Operation <br/> If (0! = Vrijgevensem () <br/>{< br/> exit (exit_failure); <br/>}< br/> pausetime = rand () % 2; <br/> sleep (pausetime); <br/>}< br/> printf ("/n % d-finished", getpid ()); <br/> // The first call to delete the semaphore set <br/> If (argc> 1) <br/>{< br/> sleep (10 ); <br/> delsemvalue (); <br/>}< br/> exit (exit_success); <br/>}</P> <p> static int setsemvalue (void) <br/>{< br/> Union semun sem_union; <br/> sem_union.val = 1; <br/> If (semctl (sem_id, 0, setval, sem_union) =-1) <br/>{< br/> return-1; <br/>}< br/> return 0; <br/>}</P> <p> static void delsemvalue (void) <br/>{< br/> Union semun sem_union; <br/> sem_union.val = 1; <br/> If (semctl (sem_id, 0, ipc_rmid, sem_union) =-1) <br/>{< br/> printf ("failed to delete semaphore/N "); <br/>}</P> <p> static int passerensem (void) <br/>{< br/> struct sembuf sem_p; <br/> sem_p.sem_num = 0; <br/> sem_p.sem_op =-1; <br/> sem_p.sem_flg = sem_undo; <br/> If (semop (sem_id, & sem_v, 1) =-1) <br/>{< br/> printf ("failed to passeren semaphore/N"); <br/> return-1; <br/>}< br/> return 0; <br/>}</P> <p> static int vrijgevensem (void) <br/>{< br/> struct sembuf sem_v; <br/> sem_v.sem_num = 0; <br/> sem_v.sem_op = 1; <br/> sem_v.sem_flg = sem_undo; <br/> If (semop (sem_id, & sem_v, 1) =-1) <br/>{< br/> printf ("failed to vrijgeven semaphore/N"); <br/> return-1; <br/>}< br/> return 0; <br/>}

 

 

 

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.