This shows you the differences between two versions of the page.
Both sides previous revision Previous revision | |||
os_cp:shmem_semaphores [2024/06/05 22:21] jkonczak [What is a semaphore] |
os_cp:shmem_semaphores [2025/06/04 19:47] (current) jkonczak |
||
---|---|---|---|
Line 23: | Line 23: | ||
be associated with the address range. | be associated with the address range. | ||
\\ | \\ | ||
- | This is done using the ''**[[https://pubs.opengroup.org/onlinepubs/9699919799/functions/mmap.html|mmap(…)]]**'' | + | This is done using the ''**[[https://pubs.opengroup.org/onlinepubs/9799919799/functions/mmap.html|mmap(…)]]**'' |
<html><span style="float:right"><small>Needs header: <code>sys/mman.h</code></small></span></html> | <html><span style="float:right"><small>Needs header: <code>sys/mman.h</code></small></span></html> | ||
function with ''**MAP_SHARED**'' flag. | function with ''**MAP_SHARED**'' flag. | ||
Line 36: | Line 36: | ||
processes, and is done by adding the ''**MAP_ANONYMOUS**'' flag, passing the | processes, and is done by adding the ''**MAP_ANONYMOUS**'' flag, passing the | ||
file descriptor of ''-1'' and passing the offset of ''0''. | file descriptor of ''-1'' and passing the offset of ''0''. | ||
- | \\ | ||
- | <small> | ||
- | ''MAP_ANONYMOUS'' is not part of the POSIX standard. However, virtually any | ||
- | UNIX-like system supports it. | ||
- | </small> | ||
When the file descriptor passed to ''mmap'' refers to an ordinary file, the | When the file descriptor passed to ''mmap'' refers to an ordinary file, the | ||
Line 46: | Line 41: | ||
<small>(a memory page is fetched upon first access within the page)</small>. | <small>(a memory page is fetched upon first access within the page)</small>. | ||
Writing the changes back to the file must be done manually by calling the | Writing the changes back to the file must be done manually by calling the | ||
- | ''**[[https://pubs.opengroup.org/onlinepubs/9699919799/functions/msync.html|msync]]**'' | + | ''**[[https://pubs.opengroup.org/onlinepubs/9799919799/functions/msync.html|msync]]**'' |
function. | function. | ||
The file descriptor passed to ''mmap'' can also refer to a shared memory object. | The file descriptor passed to ''mmap'' can also refer to a shared memory object. | ||
- | Such descriptors are returned by the ''**[[https://pubs.opengroup.org/onlinepubs/9699919799/functions/shm_open.html|shm_open]]**'' | + | Such descriptors are returned by the ''**[[https://pubs.opengroup.org/onlinepubs/9799919799/functions/shm_open.html|shm_open]]**'' |
function, which has identical arguments as the ''open'' function, but the | function, which has identical arguments as the ''open'' function, but the | ||
returned descriptor refers to a region of main memory associated with a given | returned descriptor refers to a region of main memory associated with a given | ||
Line 61: | Line 56: | ||
\\ | \\ | ||
To ensure that the file is large enough, one can use the following functions: | To ensure that the file is large enough, one can use the following functions: | ||
- | * ''[[https://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html|ftruncate]]'' <html><span style="float:right"><small>Needs header: <code>unistd.h</code></small></span></html> resizes file to a given size. \\ Whenever the file is larger it is truncated. | + | * ''[[https://pubs.opengroup.org/onlinepubs/9799919799/functions/ftruncate.html|ftruncate]]'' <html><span style="float:right"><small>Needs header: <code>unistd.h</code></small></span></html> resizes file to a given size. \\ Whenever the file is larger it is truncated. |
- | * ''[[https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_fallocate.html|posix_fallocate]]'' <html><span style="float:right"><small>Needs header: <code>fcntl.h</code></small></span></html> ensures that the file at least of a given size. \\ Whenever the file is larger it is left unchanged. \\ <small>Warning: ''posix_fallocate'' is guaranteed to work for ordinary files. The result of using ''posix_fallocate'' on a shared memory object is undefined.</small> | + | * ''[[https://pubs.opengroup.org/onlinepubs/9799919799/functions/posix_fallocate.html|posix_fallocate]]'' <html><span style="float:right"><small>Needs header: <code>fcntl.h</code></small></span></html> ensures that the file at least of a given size. \\ Whenever the file is larger it is left unchanged. \\ <small>Warning: ''posix_fallocate'' is guaranteed to work for ordinary files. The result of using ''posix_fallocate'' on a shared memory object is undefined.</small> |
To clean up the memory mapping, one has to use the | To clean up the memory mapping, one has to use the | ||
- | ''[[https://pubs.opengroup.org/onlinepubs/9699919799/functions/munmap.html|munmap]]'' | + | ''[[https://pubs.opengroup.org/onlinepubs/9799919799/functions/munmap.html|munmap]]'' |
function. (Provided one wishes to flush data to a backing ordinary file, one | function. (Provided one wishes to flush data to a backing ordinary file, one | ||
must call ''msync'' before ''munmap''.) | must call ''msync'' before ''munmap''.) | ||
Line 232: | Line 227: | ||
POSIX standardizes two implementations of semaphores: | POSIX standardizes two implementations of semaphores: | ||
- | [[https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/semaphore.h.html|POSIX semaphores]] | + | [[https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/semaphore.h.html|POSIX semaphores]] |
- | and <small>[[https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_sem.h.html|System V semaphores]]</small>. | + | and <small>[[https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/sys_sem.h.html|System V semaphores]]</small>. |
While the standard %%C++%% libraries include [[https://en.cppreference.com/w/cpp/header/semaphore|semaphores]], | While the standard %%C++%% libraries include [[https://en.cppreference.com/w/cpp/header/semaphore|semaphores]], | ||
there are no plans to include them in the standard C library (unlike other | there are no plans to include them in the standard C library (unlike other | ||
Line 249: | Line 244: | ||
There are two vital differences between mutexes and semaphores: | There are two vital differences between mutexes and semaphores: | ||
+ | <html><div style="margin-top:-1.4em"></div></html> | ||
- A mutex locked by some thread //belongs// to it and only the thread is allowed to unlock it.\\ A semaphore can be decremented/incremented by distinct threads/processes. | - A mutex locked by some thread //belongs// to it and only the thread is allowed to unlock it.\\ A semaphore can be decremented/incremented by distinct threads/processes. | ||
- A mutex can be configured recursive, and then it can be locked multiple times by the same thread and will be unlocked only after corresponding number of unlocks. | - A mutex can be configured recursive, and then it can be locked multiple times by the same thread and will be unlocked only after corresponding number of unlocks. | ||
Line 254: | Line 250: | ||
There are two ways of creating a POSIX semaphore: | There are two ways of creating a POSIX semaphore: | ||
- | * __Named semaphore:__ create / open a semaphore associated with an identifier using: \\ <html><span style="float:right"><small>Needs headers:<br><code>semaphore.h</code> and <code>fcntl.h</code></small></span><a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_open.html"></html>''sem_t %%*%%**sem_open**(const char *//name//, int //oflag//)'' \\ ''sem_t %%*%%**sem_open**(const char *//name//, int //oflag//, mode_t //mode//, unsigned int //value//)''<html></a></html> \\ These functions work just like opening a file / opening a shared memory object. \\ The extra **//''value''//** argument is the initial value of the semaphore. | + | * __Named semaphore:__ create / open a semaphore associated with an identifier using: \\ <html><span style="float:right"><small>Needs headers:<br><code>semaphore.h</code> and <code>fcntl.h</code></small></span><a href="https://pubs.opengroup.org/onlinepubs/9799919799/functions/sem_open.html"></html>''sem_t %%*%%**sem_open**(const char *//name//, int //oflag//)'' \\ ''sem_t %%*%%**sem_open**(const char *//name//, int //oflag//, mode_t //mode//, unsigned int //value//)''<html></a></html> \\ These functions work just like opening a file / opening a shared memory object. \\ The extra **//''value''//** argument is the initial value of the semaphore. |
- | * __Unnamed semaphore:__ create a variable of the ''sem_t'' type in (usually shared) memory and initialize it using: \\ <html><span style="float:right"><small>Needs header: <code>semaphore.h</code></small></span><a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_init.html"></html>''int **sem_init**(sem_t *//sem//, int //pshared//, unsigned //value//);''<html></a></html> \\ If ''//pshared//'' is logically false (and so equal 0), the semaphore is only guaranteed to work among threads of this process. Else, if ''//pshared//'' is logically true (that is, has a nonzero value) the semaphore is guaranteed to work for threads of distinct processes as well. Again, **//''value''//** sets the initial value of the semaphore. | + | * __Unnamed semaphore:__ create a variable of the ''sem_t'' type in (usually shared) memory and initialize it using: \\ <html><span style="float:right"><small>Needs header: <code>semaphore.h</code></small></span><a href="https://pubs.opengroup.org/onlinepubs/9799919799/functions/sem_init.html"></html>''int **sem_init**(sem_t *//sem//, int //pshared//, unsigned //value//);''<html></a></html> \\ If ''//pshared//'' is logically false (and so equal 0), the semaphore is only guaranteed to work among threads of this process. Else, if ''//pshared//'' is logically true (that is, has a nonzero value) the semaphore is guaranteed to work for threads of distinct processes as well. Again, **//''value''//** sets the initial value of the semaphore. |
To decrement a semaphore (possibly waiting thereby), one shall call: \\ | To decrement a semaphore (possibly waiting thereby), one shall call: \\ | ||
<html><span style="float:right"><small>Needs header: <code>semaphore.h</code></small></span> | <html><span style="float:right"><small>Needs header: <code>semaphore.h</code></small></span> | ||
- | <a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_wait.html"></html> | + | <a href="https://pubs.opengroup.org/onlinepubs/9799919799/functions/sem_wait.html"></html> |
''int **sem_wait**(sem_t *//sem//);'' | ''int **sem_wait**(sem_t *//sem//);'' | ||
<html></a></html> \\ | <html></a></html> \\ | ||
Line 267: | Line 263: | ||
To increment a semaphore, one shall call: \\ | To increment a semaphore, one shall call: \\ | ||
<html><span style="float:right"><small>Needs header: <code>semaphore.h</code></small></span> | <html><span style="float:right"><small>Needs header: <code>semaphore.h</code></small></span> | ||
- | <a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_post.html"></html> | + | <a href="https://pubs.opengroup.org/onlinepubs/9799919799/functions/sem_post.html"></html> |
''int **sem_post**(sem_t *//sem//);'' | ''int **sem_post**(sem_t *//sem//);'' | ||
<html></a></html> | <html></a></html> | ||
Line 274: | Line 270: | ||
logging and debugging purposes) using:\\ | logging and debugging purposes) using:\\ | ||
<html><span style="float:right"><small>Needs header: <code>semaphore.h</code></small></span> | <html><span style="float:right"><small>Needs header: <code>semaphore.h</code></small></span> | ||
- | <a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/sem_post.html"></html> | + | <a href="https://pubs.opengroup.org/onlinepubs/9799919799/functions/sem_post.html"></html> |
''int **sem_getvalue**(sem_t *//sem//, int *//sval//);'' | ''int **sem_getvalue**(sem_t *//sem//, int *//sval//);'' | ||
<html></a></html> \\ | <html></a></html> \\ |