-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathsys-v-semaphores.tex
169 lines (154 loc) · 6.96 KB
/
sys-v-semaphores.tex
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
include(`macros.m4')
\pdfbookmark[1]{System V Semaphores}{sys-v-semaphores}
\begin{slide}
\sltitle{System V semaphore API }
\texttt{int \funnm{semget}(key\_t \emph{key}, int \emph{\texttt{nsems}},
int \emph{\texttt{semflg}});}
\begin{itemize}
\item returns identifier of an array of \texttt{nsems} semaphores associated
with the \texttt{key} key (\texttt{IPC\_PRIVATE} key \dots{} private semaphores,
each call returns different identifier).
\texttt{semflg} is OR-combination of access rights and constants
\texttt{IPC\_CREAT} (create if does not exist),
\texttt{IPC\_EXCL} (error, if exists).
\end{itemize}
ifdef([[[NOSPELLCHECK]]], [[[
\texttt{int \funnm{semctl}(int \emph{\texttt{semid}},
int \emph{\texttt{semnum}}, int \emph{\texttt{cmd}}, ...);}
]]])
\begin{itemize}
\item controlling function, optional fourth argument \texttt{arg} is of the
\texttt{union~semun} type.
\end{itemize}
ifdef([[[NOSPELLCHECK]]], [[[
\texttt{int \funnm{semop}(int \emph{\texttt{semid}},
struct sembuf *\emph{\texttt{sops}}, size\_t \emph{\texttt{nsops}});}
]]])
\begin{itemize}
\item generic operations P and V.
\end{itemize}
\end{slide}
\hlabel{SYSVSEM}
\begin{itemize}
\item How to get the key for \texttt{semget} is explained on page
\pageref{FTOK}.
\item The most interesting property of System V semaphore implementation is
that given syscall does not operate on one semaphore but on \emsl{semaphore
array}, atomically.
Most of the time you will need just one semaphore, i.e. array of one item.
For such use the System V semaphores are needlessly complex.
\item Access rights are only for reading and writing; the execute bit does not
make sense in this context.
\item Similar API (function for creating, control and operations) is followed by
the other System V IPC mechanism as well.
\item Once the array of semaphores is created by a process, the other processes
can use \texttt{semctl()} and \texttt{semop()}, without calling
\texttt{semget()} beforehand. This is valid also for the semaphores created with
the \texttt{IPC\_PRIVATE} key, for which it is not possible to call
\texttt{semget()}, because it would create new semaphore array. This is done so
that private semaphores can be inherited across \texttt{fork} as well.
\end{itemize}
%%%%%
\begin{slide}
\sltitle{System V semaphore API: \texttt{semctl()}}
\setlength{\baselineskip}{0.9\baselineskip}
\begin{itemize}
\item \texttt{semnum} \dots{} number of semaphore in the array
\item possible values of \texttt{cmd}:
\begin{itemize}
\item \texttt{GETVAL} \dots{} returns semaphore value
\item \emsl{\texttt{SETVAL}} \dots{} \emsl{sets semaphore to value}
\texttt{arg.val}
\item \texttt{GETPID} \dots{} PID of the process that performed the last op.
\item \texttt{GETNCNT} \dots{} number of processes waiting on bigger value
\item \texttt{GETZCNT} \dots{} number of processes waiting for zero value
\item \texttt{GETALL} \dots{} saves the values of all semaphores to
\texttt{arg.array}
\item \texttt{SETALL} \dots{} sets all values according to
\texttt{arg.array}
\item \texttt{IPC\_STAT} \dots{} saves number of semaphores, access rights,
times of the last \texttt{semctl()} and \texttt{semop()} into \texttt{arg.buf}
\item \texttt{IPC\_SET} \dots{} sets access rights
\item \texttt{IPC\_RMID} \dots{} destroys the semaphore array
\end{itemize}
\end{itemize}
\end{slide}
\begin{itemize}
\item The \texttt{semctl(semid, semnum, SETVAL, arg)} call corresponds to
generic semaphore operation \texttt{init(s,~n)}.
\end{itemize}
%%%%%
\begin{slide}
\sltitle{System V semaphore API: \texttt{semop()}}
\begin{itemize}
\item operation is performed atomically (i.e. either it will be done for all
semaphores or none) on \texttt{nsops} semaphores according to the array
\texttt{sops} of structures \texttt{struct~sembuf}, that contains:
\begin{itemize}
\item \texttt{sem\_num} \dots{} semaphore number
\item \texttt{sem\_op} \dots{} operation
\begin{itemize}
\item \texttt{P(sem\_num, abs(sem\_op))} for \texttt{sem\_op < 0}
\item \texttt{V(sem\_num, sem\_op)} for \texttt{sem\_op > 0}
\item waiting on zero semaphore value for \texttt{sem\_op == 0}
\end{itemize}
\item \texttt{sem\_flg} \dots{} OR-combination
\begin{itemize}
\item \texttt{IPC\_NOWAIT} \dots{} when the operation cannot be
performed it does not wait and returns error
\item \texttt{SEM\_UNDO} \dots{} upon process exit undo the semaphore
operations
\end{itemize}
\end{itemize}
\end{itemize}
\end{slide}
\begin{itemize}
\item The atomicity across the array avoids deadlock e.g. in this situation:
two processes $A$ and $B$ will be using two semaphores for synchronization of
access to two system resources. $A$ will lock in the $(0, 1)$ order and process
$B$ will use the $(1, 0)$ order. In the moment when process $A$ locks semaphore
$0$ and $B$ locks $1$, deadlock will happen because neither process can
continue due to cyclical dependency. Using atomic operation of both semaphores
means the operation will be successful only for one process that acquires both
semaphores, the other will wait.
\item \texttt{SEM\_UNDO} ensures that upon process exit the semaphore that were
locked by the process (used as locks) will become unlocked.
\end{itemize}
%%%%%
ifdef([[[NOSPELLCHECK]]], [[[
\pdfbookmark[1]{ftok}{ftok}
]]])
\begin{slide}
\sltitle{Creating System V IPC resources}
\begin{itemize}
\item one process creates the resources, other connect to it.
\item after being done with the resource, it has to be destroyed.
\item \texttt{semget()}, \texttt{shmget()} and
\texttt{msgget()} have the key identifying the resource as a first argument.
Group of processes that want to communicate has to agree on common key.
Different groups of communicating processes should have different keys.
\end{itemize}
\texttt{key\_t \funnm{ftok}(const char *\emph{path}, int \emph{id});}
\begin{itemize}
\item returns key derived from \texttt{path} and \texttt{id} number.
Returns the same key for the same \texttt{id} and arbitrary path referencing the
same file. Returns different keys for different \texttt{id} or different files
on the same volume.
\end{itemize}
\end{slide}
\hlabel{FTOK} \texttt{ftok()} notes:
\begin{itemize}
\item Only the 8 lowest bits are used from the \texttt{id} argument.
\item It is left unspecified whether the same key will be returned across file
deletion. Usually not because the key often reflects inode number.
\item Different keys for different files are not always guaranteed. E.g. on
Linux the key is determined using the combination of 16-bit inode number, 8 bits
of \texttt{id} and 8 bits of minor device number. Same key is returned if the
inode numbers have the same 16 lower bits.
\item If unrelated processes need to use the same semaphore,
\emsl{the file name used for the key needs to be agreed on beforehand.}
\item \hlabel{SEM_FIXED_RACE_C} Example: \example{race/sem-fixed-race.c}
(this is the \example{race/race.c} example from page \pageref{RACE_C} fixed
with semaphores)
\end{itemize}
\endinput