Linux Process Communication-semaphores

Source: Internet
Author: User
Tags tmp file

I. Related Knowledge

Semaphores: an integer;
The number of resource entities that tables can be used by concurrent processes when the value is greater than or equal to 0;
Number of processes waiting for using the critical section in the age of less than 0;
The initial semaphore value used for mutex must be greater than 0;
It can only be changed through P and V primitive operations;
Semaphore element composition:
1. The value of the semaphore element;
2. process ID of the final semaphore Element
3. The number of processes with the semaphore element value + 1;
4. Number of processes whose semaphores element value is 0;
 
Ii. Main Functions
 
1.1 create semaphores
Int semget (
Key_t key, // The Key to identify the semaphore, there are three methods: 1, the use of IPC--PRIVATE for the system to produce,
// 2. Select a random number. 3. Use ftok to generate a random number from the file path.
Int nsemes, // number of elements in the semaphore set
Int flag // ipc_creat; ipc_excl is created only when the semaphore set does not exist
)
Success: return the semaphore handle.
Failed:-1 is returned.
 
1.2 use the ftok function to generate a keyword Based on the file path name
Key_t ftok (const char * pathname, int proj_id );
The path name must have the corresponding Permissions
 
1.3 control semaphores
Int semctl (
Int Semid, // semaphore set handle
Int semnum, // number of elements in the semaphore set
Int cmd, // command
/* Union senum Arg */...//
)
Success: the corresponding value is returned.
Failed:-1 is returned.
 
Command details:
CMD: ipc_rmid: deletes a semaphore.
Ipc_excl is created only when the semaphore set does not exist.
Ipc_set: Set the semaphore permission
Setval: set the value of the element of the specified semaphore to AGC. Val.
Getval obtains the value of a specified semaphore.
Getpid obtains the final process ID that finally controls this element.
Getncnt obtains the number of processes that wait for the element to change to 1.
Getzcnt obtains the number of processes that wait for the element to change to 0.

Union senum is defined as follows:
Union senum {
Int val;
Struct semid_ds * Buf;
Unsigned short * array;
} AGC;

Semid_ds is defined as follows:
Struct semid_ds {
Struct ipc_pem sem_pem; // operation pemission struct
Time_t sem_otime; // last semop () Time
Time_t sem_ctime; // last time changed by semctl ()
Struct SEM * sembase; // PTR to first semaphore in array
Struct sem_queue * sem_pending; // pending operations
Struct sem_queue * sem_pending_last; // last pending operations
Struct sem_undo * undo; // undo requests on this arrary
Unsigned short int sem_nsems; // Number of semaphores in Set
};

1.4 semaphore + 1 or-1 or test whether it is 0
Int semop (
Int Semid,
Struct sembuf * SOPs, // points to the element Operation Array
Unsigned short nsops // Number of element operations in the array
)
 
Structure sembuf Definition
Sembuf {
Short int sem_num; // semaphore number
Short int sem_op; // semaphore operaion
Short int sem_flg // operation flag
};
 
Iii. Example:
2.1 servers

# I nclude <sys/SEM. h>
# I nclude <sys/IPC. h>

# Derefined segsize 1024
# Define readtime 1
Union semun {
Int val;
Struct semid_ds * Buf;
Unsigned short * array;
} ARG;
// Generate a semaphore
Int sem_creat (key_t key)
{
Union semun SEM;
Int Semid;
SEM. Val = 0;
Semid = semget (Key, 1, ipc_creat | 0666 );
If (-1 = Semid ){
Printf ("create semaphore error \ n ");
Exit (-1 );
}
Semctl (Semid, 0, setval, SEM );
Return Semid;
}
// Delete semaphores
Void del_sem (INT Semid)
{
Union semun SEM;
SEM. Val = 0;
Semctl (Semid, 0, ipc_rmid, SEM );
}

// P
Int P (INT Semid)
{
Struct sembuf SOPs = {0, + 1, ipc_nowait };
Return (semop (Semid, & SOPs, 1 ));
}
// V
Int V (INT Semid)
{
Struct sembuf SOPs = {0,-1, ipc_nowait };
Return (semop (Semid, & SOPs, 1 ));
}
Int main ()
{
Key_t key;
Int shmid, Semid;
Char * SHM;
Char MSG [7] = "-data -";
Char I;
Struct semid_ds Buf;
 
Key = ftok ("/", 0 );
Shmid = shmget (Key, segsize, ipc_creat | 0604 );
If (-1 = shmid ){
Printf ("create shared memory error \ n ");
Return-1;
}
SHM = (char *) shmat (shmid, 0, 0 );
If (-1 = (INT) SHM ){
Printf ("Attach shared memory error \ n ");
Return-1;
}
Semid = sem_creat (key );
For (I = 0; I <= 3; I ++ ){
Sleep (1 );
P (Semid );
Sleep (readtime );
MSG [5] = '0' + I;
Memcpy (SHM, MSG, sizeof (MSG ));
Sleep (58 );
V (Semid );
}
Shmdt (SHM );
Shmctl (shmid, ipc_rmid, & BUF );
Del_sem (Semid );
Return 0;
// Gcc-o shm. C-G
}
 
2.2 Client
 
# I nclude <sys/SEM. h>
# I nclude <time. h>
# I nclude <sys/IPC. h>

# Derefined segsize 1024
# Define readtime 1
Union semun {
Int val;
Struct semid_ds * Buf;
Unsigned short * array;
} ARG;

// Print the program execution time
Void out_time (void)
{
Static long start = 0;
Time_t TM;
If (0 = Start ){
TM = Time (null );
Start = (long) TM;
Printf ("now start... \ n ");
}
Printf ("Second: % LD \ n", (long) (Time (null)-Start );
}

// Create a semaphore
Int new_sem (key_t key)
{
Union semun SEM;
Int Semid;
SEM. Val = 0;
Semid = semget (Key, 0, 0 );
If (-1 = Semid ){
Printf ("create semaphore error \ n ");
Exit (-1 );
}
Return Semid;
}

// Wait until the semaphore is 0
Void wait_v (INT Semid)
{
Struct sembuf SOPs = {0, 0 };
Semop (Semid, & SOPs, 1 );
}

Int main (void)
{
Key_t key;
Int shmid, Semid;
Char * SHM;
Char MSG [100];
Char I;
 
Key = ftok ("/", 0 );
Shmid = shmget (Key, segsize, 0 );
 
If (-1 = shmid ){
Printf ("create shared memory error \ n ");
Return-1;
}
SHM = (char *) shmat (shmid, 0, 0 );
If (-1 = (INT) SHM ){
Printf ("Attach shared memory error \ n ");
Return-1;
}
Semid = new_sem (key );
For (I = 0; I <3; I ++ ){
Sleep (2 );
Wait_v (Semid );
Printf ("message geted is: % s \ n", SHM + 1 );
Out_time ();
}
Shmdt (SHM );
Return 0;
// Gcc-O shmc. C-G
}

Another example:

The question is: write a program that creates two processes and prints "this is the child process" and "Father say hello to child" respectively, which must be printed alternately, output to "this father is say the hello child to process child". Every time a word is printed, the process is blocked for a period of time. Print the output to the tmp file in the current directory.

A:

 
 
  1. # Include <stdio. h>
  2. # Include <stdlib. h>
  3. # Include <sys/types. h>
  4. # Include <sys/IPC. h>
  5. # Include <sys/SEM. h>
  6. # Include <sys/STAT. h>
  7. # Include <fcntl. h>
  8.  
  9. Union semun
  10. {
  11. Int val;
  12. Struct semid_ds * Buf;
  13. Unsigned short int * array;
  14. Struct seminfo * _ Buf;
  15. };
  16.  
  17. Int main (void)
  18. {
  19. Char * buf_child [] = {"this", "is", "the", "child", "process "};
  20. Char * buf_father [] = {"father", "say", "hello", "to", "child "};
  21. Int I = 0, Semid, FD;
  22. Pid_t PID;
  23. Struct sembuf Sb; // semaphore operation
  24. Union semun SEM;
  25. Semid = semget (1000, 2, 0666 | ipc_creat); // applies for a semaphore Group, which contains 2 semaphores
  26.  
  27. SEM. Val = 0;
  28. Semctl (Semid, 0, setval, SEM); // initialize the semaphore 0 to 0
  29. SEM. Val = 1;
  30. Semctl (Semid, 1, setval, SEM); // initialize semaphores 1 to 1
  31.  
  32. FD = open ("tmp", o_creat | o_trunc | o_wronly, 0666 );
  33.  
  34. PID = fork ();
  35. Switch (PID ){
  36. Case-1:
  37. Perror ("fork fail ");
  38. Break;
  39. Case 0:/* child consume */
  40. Srand (unsigned INT) getpid ());
  41. While (I <5 ){
  42. SB. sem_num = 1; // set the semaphore Number 1
  43. SB. sem_op =-1; // minus 1
  44. SB. sem_flg = sb. sem_flg &~ Ipc_nowait;
  45. Semop (Semid, & SB, 1 );
  46.  
  47. Write (FD, buf_child [I], strlen (buf_child [I]);
  48. Sleep (RAND ());
  49. Write (FD, & "", 1 );
  50. I ++;
  51.  
  52. SB. sem_num = 0; // set the semaphore number 0
  53. SB. sem_op = 1; // Add 1
  54. SB. sem_flg = sb. sem_flg &~ Ipc_nowait;
  55. Semop (Semid, & SB, 1); // operation semaphore
  56. }
  57. Break;
  58. Default:/* parent Production */
  59. Srand (unsigned INT) getpid ());
  60. While (I <5 ){
  61. SB. sem_num = 0; // set the semaphore number 0
  62. SB. sem_op =-1; // minus 1
  63. SB. sem_flg = sb. sem_flg &~ Ipc_nowait;
  64. Semop (Semid, & SB, 1); // operation semaphore
  65.  
  66. Write (FD, buf_father [I], strlen (buf_father [I]);
  67. Sleep (RAND ());
  68. Write (FD, & "", 1 );
  69. I ++;
  70.  
  71. SB. sem_num = 1;
  72. SB. sem_op = 1;
  73. SB. sem_flg = sb. sem_flg &~ Ipc_nowait;
  74. Semop (Semid, & SB, 1 );
  75. }
  76. Break;
  77. }
  78. Return 0;
  79. }

POSIX semaphores:

1. POSIX unknown semaphores if you have studied the operating system, you must be familiar with PV operations. PV operations are atomic operations. that is, the operation cannot be interrupted. within a certain period of time, only one process code can be executed on the CPU. in the system, sometimes in order to smoothly use and protect shared resources, we put forward the concept of signal. suppose we want to use a printer. If two processes are output to the printer at the same time, what is the final result. to deal with this situation, the POSIX standard puts forward the concepts of the famous semaphores and the unknown semaphores. Since Linux only implements the unknown semaphores, we will only introduce the unknown semaphores here. the use of semaphores is mainly used to protect shared resources, so that resources are owned by only one process at a time. therefore, we can use a signal lamp. when the traffic signal value is a certain value, it indicates that the resource cannot be used at this time. no
The following functions are provided to provide efficiency:
The functions of POSIX's unknown semaphores include the following:

# Include

Int sem_init (sem_t * SEM, int pshared, unsigned int value );
Int sem_destroy (sem_t * SEM );
Int sem_wait (sem_t * SEM );
Int sem_trywait (sem_t * SEM );
Int sem_post (sem_t * SEM );
Int sem_getvalue (sem_t * SEM );

Sem_init creates a signal lamp and initializes the value as value. pshared determines whether the semaphore can be shared among several processes. currently, Linux does not implement shared traffic signals between processes, so this value can only be 0. sem_destroy is used to delete traffic signals. the sem_wait call will block the process until the traffic signal value is greater than 0. when this function returns, it will automatically set the value of the signal. the opposite of sem_post and sem_wait is to add the content of the signal lamp and send a signal to wake up the waiting process .. sem_trywait is the same as sem_wait, but it is not blocked. If the signal light value is 0, eagain is returned, indicating that the system will retry later. sem_getvalue to get the signal light value.

Because Linux does not support it, we cannot use the source program to explain it.
These functions are quite simple to use. for example, we have a program to print two pages to a system printer. first, we create a signal lamp and set its initial value to 1, which indicates that a resource is available. then a process calls sem_wait because the signal light value is 1 at this time, so this function returns, the printer starts printing, and the signal light value is 0. if the second process is to be printed, when sem_wait is called, the traffic signal is blocked because the value of the signal lamp is 0 and the resource is unavailable. when the printing of the first process is complete, the value of the sem_post signal is 1. At this time, the system notifies the second process, so the sem_wait of the second process is returned. the second process is printed.

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.