Linux Network Programming-System V semaphores (2): Examples of process mutex using semaphores and solutions to Dining Philosophers

Source: Internet
Author: User

1. We mentioned the concept of process mutex when talking about inter-process communication. Below we will write a program to simulate the process, for example:


That is, the parent process prints the character o, the child process prints the character X, and sleep each time it prints a character. The effect shown here is that there is a PV operation at the boundary of the print program, therefore, even if the sleep time of each process is rotated to another process, no other characters will be output due to resource unavailability, that is, O or X characters will appear in pairs, for example, ooxxooxxxxxxoo ....

The procedure is as follows:

C ++ code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# Include <sys/types. h>
# Include <unistd. h>
# Include <errno. h>
# Include <sys/IPC. h>
# Include <sys/SEM. h>
# Include <sys/Wait. H>

# Define err_exit (m )\
Do {\
Perror (m );\
Exit (exit_failure );\
} While (0)

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 (Linux-specific )*/
};

Int Semid;
/* The critical section between PV operations. The printed characters must appear in pairs */
Void print (char op_char)
{
Int pause_time;
Srand (getpid ());
Int I;
For (I = 0; I <10; I ++)
{
Sem_p (Semid );
Printf ("% C", op_char );
Fflush (stdout );
Pause_time = rand () % 3;
Sleep (pause_time );
Printf ("% C", op_char );
Fflush (stdout );
Sem_v (Semid );
Pause_time = rand () % 2;
Sleep (pause_time );
}

}

Int main (void)
{

Semid = sem_create (ipc_private );
Sem_setval (Semid, 1 );
Pid_t PID;
PID = fork ();
If (pid =-1)
Err_exit ("fork ");

If (pid> 0)
{

Print ('O ');
Wait (null );
Sem_d (Semid );

}

Else
{

Print ('x ');

}

Return 0;
}

Sem_create and other functions are referenced in the tool set. When semget is called, Specify Key = ipc_private, which indicates that the private signal set is created, but the process with kinship is visible, such as the parent and child processes. The output is as follows:

Simba @ Ubuntu :~ /Documents/code/linux_programming/UNP/system_v $./print
Ooxxooxxooxxooxxooooxxooxxooxxooxxooxxxxxx

The output is a pair of characters.

Analysis: semval = 1. Assume that the parent process is scheduled for execution first, and the parent process is P. At this time, semval = 0. When the parent process is scheduled for sleep, try p, semval =-1, then the sub-process is blocked. After the parent process finishes printing V, semval = 0, wake up the sub-process, and the P operation of the sub-process returns, print the character V after sleep, semval = 1. Of course, when the child process is sleeping, the parent process may also be trying P, so it will continue to loop.


2. The description of the dining problem of philosophers can be referred here. The following solution is as follows: a philosopher is allowed to take chopsticks only when both sides of chopsticks are available.


The red number indicates the number of philosophers. A total of five philosophers are represented by five processes. A black number indicates the number of chopsticks. There are five chopsticks in total, it can be defined that a signal set contains five semaphores. The initial value of each semaphores is 1. When a philosopher can get two chopsticks at the same time (P two semaphores return at the same time), he can eat, otherwise, the request is blocked. After a meal, you must have two semaphores at the same time in v1.

The procedure is as follows:

C ++ code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# Include <stdio. h>
# Include <stdlib. h>
# Include <sys/IPC. h>
# Include <sys/msg. h>
# Include <sys/types. h>
# Include <unistd. h>
# Include <errno. h>
# Include <sys/IPC. h>
# Include <sys/SEM. h>
# Include <sys/Wait. H>

# Define err_exit (m )\
Do {\
Perror (m );\
Exit (exit_failure );\
} While (0)

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 (Linux-specific )*/
};

Int Semid;

# Define delay (RAND () % 5 + 1)

Void wait_for_2fork (INT No)
{
Int left = no;
Int right = (NO + 1) % 5;

Struct sembuf Buf [2] =
{
{Left,-1, 0 },
{Right,-1, 0}
};

Semop (Semid, Buf, 2 );
}

Void free_2fork (INT No)
{
Int left = no;
Int right = (NO + 1) % 5;

Struct sembuf Buf [2] =
{
{Left, 1, 0 },
{Right, 1, 0}
};

Semop (Semid, Buf, 2 );
}

Void philosopere (INT No)
{
Srand (getpid ());
For (;;)
{

Printf ("% d is thinking \ n", no );
Sleep (Delay );
Printf ("% d is hungry \ n", no );
Wait_for_2fork (NO );
Printf ("% d is eating \ n", no );
Sleep (Delay );
Free_2fork (NO );
}
}

Int main (void)
{

Semid = semget (ipc_private, 5, ipc_creat | 0666 );
If (Semid =-1)
Err_exit ("semget ");
Union semun Su;
Su. Val = 1;
Int I;
For (I = 0; I <5; I ++)
{
Semctl (Semid, I, setval, su );
}

Int NO = 0;
Pid_t PID;
For (I = 1; I <5; I ++)
{
PID = fork ();
If (pid =-1)
Err_exit ("fork ");

If (pid = 0)
{
No = I;
Break;
}
}

Philosopere (NO );

Return 0;
}

As we mentioned earlier, when we need to operate multiple semaphores in a signal set, either all or all are not executed, that is, an atomic operation. A process needs to wait for two chopsticks, that is, if two semaphores are successfully p at the same time, the number of semaphores is 0 ~ 4. It can be seen as the number of chopsticks. In this case, semop
The function operates on two semaphores, that is, the array of two struct sembuf struct members must be defined, struct sembuf Buf [2];

Simba @ Ubuntu :~ /Documents/code/linux_programming/UNP/system_v $./Dinning
0 is thinking
3 is thinking
2 is thinking
4 is thinking
1 is thinking
4 is hungry
4 is eating
0 is hungry
3 is hungry
1 is hungry
1 is eating
2 is hungry
3 is eating
4 is thinking
1 is thinking
0 is eating
4 is hungry
0 is thinking
1 is hungry
1 is eating
3 is thinking
4 is eating
0 is hungry
1 is thinking
2 is eating
0 is eating
4 is thinking
2 is thinking
1 is hungry
3 is hungry
3 is eating

0 is thinking
2 is hungry
1 is eating
4 is hungry

................

If you find that the program is not running, that is, there is no deadlock, you can also find that at most two philosophers can eat together, there will be no adjacent philosophers eat together.


Refer:

UNP

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.