# Include <unistd. h>
# Include <stdlib. h>
# Include <stdio. h>
# Include <sys/types. h>
# Include <sys/IPC. h>
# Include <sys/SEM. h>
# Ifndef _ semun_h // Conditional compilation. If semun is not defined in the header file, compile the following code:
# DEFINE _ semun_h
Union semun {
Int val; // set the semaphore value specified by semnum
Struct semid_ds * Buf;
Unsigned short int * array;
Struct seminfo * _ Buf;
};
# Endif
Static int set_semvalue (void );
Static void del_semvalue (void );
Static int semaphore_p (void );
Static int semaphore_v (void );
Static int sem_id;
Int main (INT argc, char * argv []) {
Int I;
Int pause_time;
Char * op_in = "first in/N ";
Char * op_out = "first out/N ";
Srand (unsigned INT) getpid (); // seeds whose random sequence is getpid ()
Sem_id = semget (key_t) 0666, | ipc_creat);/* returns an identifier for a newly created set,
Or return the identifier of an existing signal set with the same key value */
If (argc> 1 ){
If (! Set_semvalue () {// signal initialization failed
Fprintf (stderr, "failed to initialize semaphore/N ");
}
Op_in = "second in/N ";
Op_out = "second out/N ";
Sleep (2 );
}
For (I = 0; I <5; I ++ ){
If (! Semaphore_p ())
Exit (exit_failure );
Printf ("% s", op_in );
Fflush (stdout );
Pause_time = rand () % 3;
Sleep (pause_time );
Printf ("% s", op_out );
Fflush (stdout );
If (! Semaphore_v ())
Exit (exit_failure );
Pause_time = rand () % 2;
Sleep (pause_time );
}
Printf ("/n % d-finished/N", getpid ());
If (argc> 1 ){
Sleep (10 );
Del_semvalue ();
}
Exit (exit_success );
}
Static int set_semvalue (void ){
Union semun sem_union;
Sem_union.val = 1;
If (semctl (sem_id, 0, setval, sem_union) =-1)/* set the semaphore value specified by sem_union.val,
Error returned-1, success returned positive number */
Return (1); // if the preceding condition is true,-1 is returned, and 1 is returned.
}
Static void del_semvalue (void ){
Union semun sem_union;
If (semctl (sem_id, 0, ipc_rmid, sem_union) =-1)/* deletes a signal set with the identifier sem_id from the system,
-1 is returned. A positive number is returned */
Fprintf (stderr, "failed to delete semaphore/N ");
}
Static int semaphore_p (void ){
Struct sembuf sem_ B; // The sembuf structure is defined in Linux/SEM. h.
Sem_ B .sem_num = 0; // index of the signal in the array
Sem_ B .sem_op =-1;/* This is a negative number, which is equivalent to the P operation. Subtract the absolute value of sem_op from the semaphore (1 )*/
Sem_ B .sem_flg = sem_undo;/* The operation flag is sem_undo. When a process changes the semaphore value and enters the critical section,
However, if you do not exit the critical section for other reasons, the semaphore will never be released,
At this point, the system uses sem_undo to perform the restoration operation, and the semaphore is restored to the status before the process operation */
If (semop (sem_id, & sem_ B, 1) =-1) {// P operation error,-1 is returned, condition is true; otherwise the condition is not true
Fprintf (stderr, "semaphore_p failed ");
Return (0); // if the preceding condition is true, an error occurs. 0 is returned to the called function.
}
} // Luojiazhen corrected it December 20
Static int semaphore_v (void ){
Struct sembuf sem_ B;
Sem_ B .sem_num = 0;
Sem_ B .sem_op = 1;/* It is a positive number, which is equivalent to a V operation. Add the sem_op value (1) to the semaphore ),
This means that the process returns from the critical zone and releases critical resources */
Sem_ B .sem_flg = sem_undo;
If (semop (sem_id, & sem_ B, 1) =-1) {// v operation error, return-1, condition is true; otherwise the condition is not true
Fprintf (stderr, "semaphore_v failed ");
Return (0 );
}
Return (1 );
}