semaphore concurrency - c

In the following code, wouldn't a mutex be created, in the child, as a copy of its parent's? Hence there're two copies of mutexs now -- one in child, and one in parent. How can it be synchronized? As far as I can remember, you need one copy that are shared by multiple processes in order to make it synchronize.
#include <semaphore.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
int main(int argc, char **argv)
{
int fd, i,count=0,nloop=10,zero=0,*ptr;
sem_t mutex;
//open a file and map it into memory
fd = open("log.txt",O_RDWR|O_CREAT,S_IRWXU);
write(fd,&zero,sizeof(int));
ptr = mmap(NULL,sizeof(int), PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
close(fd);
/* create, initialize semaphore */
if( sem_init(&mutex,1,1) < 0)
{
perror("semaphore initilization");
exit(0);
}
if (fork() == 0) { /* child process*/
for (i = 0; i < nloop; i++) {
sem_wait(&mutex);
printf("child: %d\n", (*ptr)++);
sem_post(&mutex);
}
exit(0);
}
/* back to parent process */
for (i = 0; i < nloop; i++) {
sem_wait(&mutex);
printf("parent: %d\n", (*ptr)++);
sem_post(&mutex);
}
exit(0);
}

You must not confuse a mutex with a semaphore. A semaphore might allow several threads/processes to access a resource, a mutex allows only ONE concurrent access to a resource.
As stated here you would need to create a named semaphore to make cross-process-synchronisation possible.
You must create a semaphore in your parent process and access is using sem_open in the child process to achieve synchronisation.

Related

POSIX Semaphores parent semaphore value is unaffected

I am learning POSIX Semaphores.
Wrote a basic code which allows share POSIX Semaphores between parent and child. Why is the semaphore value not changed in parent after child updates it.
#include <stdio.h>
#include <fcntl.h> /* For O_* constants */
#include <sys/stat.h> /* For mode constants */
#include <semaphore.h>
#include <stdlib.h>
void print_sem_value(sem_t *sem)
{
int sem_value;
if (sem_getvalue(sem, &sem_value) != 0) {
perror("sem_getvalue");
} else {
printf("%d:Semaphore value:%d\n", getpid(), sem_value);
}
}
int main(int argc, char *argv[])
{
pid_t pid;
sem_t sem;
sem_init(&sem, 1, 3);
pid = fork();
if (pid == 0) {
print_sem_value(&sem);
sem_wait(&sem);
print_sem_value(&sem);
sem_wait(&sem);
print_sem_value(&sem);
} else if (pid > 0) {
wait(NULL);
print_sem_value(&sem);
sem_post(&sem);
print_sem_value(&sem);
}
sem_destroy(&sem);
return 0;
}
Why is the semaphore value not changed in parent after child updates it.
You create an unnamed, process-shared semaphore, which is appropriate for your purpose, but you have not caused it actually to be shared. As the sem_init manual page documents:
If pshared is nonzero, then the semaphore is shared between
processes, and should be located in a region of shared memory (see
shm_open(3), mmap(2), and shmget(2)).
If you don't adhere to that then the child gets its own copy of the semaphore, which does not interact with the parent's, process-shared status notwithstanding.
Once you fix that, do note also that only one process should sem_destroy() the semaphore, whereas in your current code, both processes (attempt to) do.

Using semaphores between processes [duplicate]

Let's say I create a semaphore. If I fork a bunch of child processes, will they all still use that same semaphore?
Also, suppose I create a struct with semaphores inside and forked. Do all the child processes still use that same semaphore? If not, would storing that struct+semaphores in shared memory allow the child processes to use the same semaphores?
I'm really confused about how my forked child processes can use the same semaphores.
Let's say I create a semaphore. If I fork a bunch of child processes, will they all still use that same semaphore?
If you are using a SysV IPC semaphore (semctl), then yes. If you are using POSIX semaphores (sem_init), then yes, but only if you pass a true value for the pshared argument on creation and place it in shared memory.
Also, suppose I create a struct with semaphores inside and forked. Do all the child processes still use that same semaphore? If not, would storing that struct+semaphores in shared memory allow the child processes to use the same semaphores?
What do you mean be 'semaphores inside'? References to SysV IPC semaphores will be shared, because the semaphores don't belong to any process. If you're using POSIX semaphores, or constructing something out of pthreads mutexes and condvars, you will need to use shared memory, and the pshared attribute (pthreads has a pshared attribute for condvars and mutexes as well)
Note that anonymous mmaps created with the MAP_SHARED flag count as (anonymous) shared memory for these purposes, so it's not necessary to actually create a named shared memory segment. Ordinary heap memory will not be shared after a fork.
Let's say I create a semaphore. If I fork a bunch of child processes,
will they all still use that same semaphore?
It depends how you created the semaphore, to do that with an IPC semaphore see semaphore.c: Illustration of simple semaphore passing for an example.
Also, suppose I create a struct with semaphores inside and forked. Do
all the child processes still use that same semaphore? If not, would
storing that struct+semaphores in shared memory allow the child
processes to use the same semaphores?
For that to work your semaphore needs to be stored in an area shared between the parent and the child process like shared memory, and not just created on the stack or on the heap because it will be copied when the process forks.
I'm really confused about how my forked child processes can use the
same semaphores.
The semaphore can be shared across threads or processes. Cross-process sharing is implemented on the operating system level. Two or more different processes can share the same semaphore even if those processes were not created by forking a single parent process.
See this example for sharing an unnamed UNIX semaphore between a parent process and its child (to compile with gcc you'll need the -pthread flag):
#include <semaphore.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
int main(void)
{
/* place semaphore in shared memory */
sem_t *sema = mmap(NULL, sizeof(*sema),
PROT_READ |PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,
-1, 0);
if (sema == MAP_FAILED) {
perror("mmap");
exit(EXIT_FAILURE);
}
/* create/initialize semaphore */
if ( sem_init(sema, 1, 0) < 0) {
perror("sem_init");
exit(EXIT_FAILURE);
}
int nloop=10;
int pid = fork();
if (pid < 0) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid == 0) {
/* child process*/
for (int i = 0; i < nloop; i++) {
printf("child unlocks semaphore: %d\n", i);
if (sem_post(sema) < 0) {
perror("sem_post");
}
sleep(1);
}
if (munmap(sema, sizeof(sema)) < 0) {
perror("munmap");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
if (pid > 0) {
/* back to parent process */
for (int i = 0; i < nloop; i++) {
printf("parent starts waiting: %d\n", i);
if (sem_wait(sema) < 0) {
perror("sem_wait");
}
printf("parent finished waiting: %d\n", i);
}
if (sem_destroy(sema) < 0) {
perror("sem_destroy failed");
exit(EXIT_FAILURE);
}
if (munmap(sema, sizeof(sema)) < 0) {
perror("munmap failed");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
}
The output will be:
parent starts waiting: 0
child unlocks semaphore: 0
parent finished waiting: 0
parent starts waiting: 1
child unlocks semaphore: 1
parent finished waiting: 1
...
You may want to read Semaphores in Linux as well, but be aware that the example of UNIX semaphores across fork given doesn't work because the author forgot to use the MAP_ANONYMOUS flag in mmap.
Try this
child and parent would increment the shared variable alternatively
#include <semaphore.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
struct test {
sem_t mutex1;
sem_t mutex2;
int temp;
}test1;
int main(int argc, char **argv)
{
int fd, i,count=0,nloop=10,zero=0,*ptr;
struct test *testptr;
//open a file and map it into memory
sem_t mutex;
fd = open("log.txt",O_RDWR|O_CREAT,S_IRWXU);
write(fd,&zero,sizeof(int));
ptr = mmap(NULL, sizeof(struct test),PROT_READ |PROT_WRITE,MAP_SHARED,fd,0);
close(fd);
memcpy(ptr, &test1, sizeof(test1));
testptr = (struct test *)ptr;
// testptr = (struct test *)&test1;
/* create, initialize semaphore */
if( sem_init(&(testptr->mutex1),1,1) < 0)
{
perror("semaphore initilization");
exit(0);
}
/* create, initialize semaphore */
if( sem_init(&(testptr->mutex2),1,0) < 0)
{
perror("semaphore initilization");
exit(0);
}
if (fork() == 0) { /* child process*/
for (i = 0; i < nloop; i++) {
sem_wait(&(testptr->mutex2));
printf("child: %d\n", testptr->temp++);
sem_post(&(testptr->mutex1));
}
exit(0);
/* back to parent process */
for (i = 0; i < nloop; i++) {
sem_wait(&testptr->mutex1);
printf("parent: %d\n", testptr->temp++);
sem_post(&(testptr->mutex2));
}
exit(0);
}

Process Synchronisation in C does not execute the first time

So I am having this issue with a Process Synchronization program in C.
I am supposed to make a code that, using fork(), will produce something like this:
PARENT
PARENT
CHILD
PARENT
CHILD
PARENT
Using a code I found here, I was able to make it work but for some reasons, the first result that comes to screen is messed while all the others work just fine.
To compile, type : gcc test.c display.c -o test -pthread
Anyway, here is the code I am testing (I repeat: it's not my code):
#include <semaphore.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
int main(void)
{
int i;
/* place semaphore in shared memory */
sem_t *sema = mmap(NULL, sizeof(sema), PROT_READ |PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1, 0);
/* create/initialize semaphore */
if ( sem_init(sema, 1, 0) < 0)
{
perror("sem_init");
exit(EXIT_FAILURE);
}
int nloop=10;
int pid = fork();
if (pid == 0)
{
for (i = 0; i < nloop; i++)
{
// child unlocks semaphore
display("CHILD\n");
if (sem_post(sema) < 0)
perror("sem_post");
sleep(1);
}
if (munmap(sema, sizeof(sema)) < 0)
{
perror("munmap");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
else
{
for (i = 0; i < nloop; i++)
{ // parent starts waiting
display("PARENT\n");
if (sem_wait(sema) < 0)
perror("sem_wait");
// parent finished waiting
}
if (sem_destroy(sema) < 0)
{
perror("sem_destroy failed");
exit(EXIT_FAILURE);
}
if (munmap(sema, sizeof(sema)) < 0)
{
perror("munmap failed");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
}
Here is the output:
PACREHNT
ILD
PARENT
CHILD
PARENT
CHILD
PARENT
CHILD
PARENT
CHILD
PARENT
CHILD
PARENT
CHILD
PARENT
CHILD
PARENT
CHILD
PARENT
CHILD
Why does this happen in the beginning?
You can't write a program that alternates between a parent and a child process with a single semaphore (without resorting to some form of busy waiting with flags or something), because both processes will race to acquire the semaphore; there is no way to predict which process will acquire it first. Your code (other than the first iteration) seems to work as expected because the child sleeps for a very long time, but technically it is still a race condition, there is no guarantee that the parent will get a chance to acquire the semaphore before the child wakes up (although it is very unlikely).
So, you need 2 semaphores: one used by the child to notify the parent that it's his turn, and another used by the parent to notify the child. To pick who starts first, initialize the corresponding semaphore to 1 (and the other to 0).
Also, this is wrong:
sem_t *sema = mmap(NULL, sizeof(sema), PROT_READ |PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1, 0);
The 2nd argument should be sizeof(*sema) since you want to allocate memory for the semaphore object, not for the pointer.
You never #include "display.h", you probably should.
Error handling could be improved, but for this toy program I don't think it's a big deal.
Here's a working version using the 2-semaphore approach (this initializes the parent semaphore to 1, so the parent will start first):
#include <semaphore.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
int main(void)
{
int i;
/* place semaphore in shared memory */
sem_t *child_sem = mmap(NULL, sizeof(*child_sem), PROT_READ |PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1, 0);
sem_t *parent_sem = mmap(NULL, sizeof(*parent_sem), PROT_READ |PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1, 0);
/* create/initialize semaphore */
if ( sem_init(child_sem, 1, 0) < 0)
{
perror("sem_init");
exit(EXIT_FAILURE);
}
if (sem_init(parent_sem, 1, 1) < 0) {
perror("sem_init");
exit(EXIT_FAILURE);
}
int nloop=10;
int pid = fork();
if (pid == 0)
{
for (i = 0; i < nloop; i++)
{
if (sem_wait(child_sem) < 0)
perror("sem_wait");
display("CHILD\n");
if (sem_post(parent_sem) < 0)
perror("sem_post");
sleep(1);
}
}
else
{
for (i = 0; i < nloop; i++)
{ // parent starts waiting
if (sem_wait(parent_sem) < 0)
perror("sem_wait");
display("PARENT\n");
if (sem_post(child_sem) < 0)
perror("sem_post");
}
}
}
I removed the munmap(2) and sem_destroy(3) calls for conciseness, and because they are unnecessary since the process is exiting anyway.
Notice that both processes follow the same pattern: wait for their semaphore, do work, notify the other process' semaphore. This is a nice opportunity to do some refactoring and move it all to a function that receives the string to display, the semaphore to wait on, and the semaphore to notify afterwards.
You should also get used to compiling with -Wall.

Adding Semaphore to a program - C in Linux

I am relatively new to programming, especially in the C Language.
I got an assignment to write a simple program in C and executing it in Linux.
I've written the code already as below:
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<stdio.h>
#include<stdlib.h>
#define BUFSZ 4096
int shmid;
int shmkey = 12222;
int main()
{
/* ----- Creating Shared memory ----- */
shmid=shmget(IPC_PRIVATE,BUFSZ,0666);
if(shmid<0)
{
perror("shmget");
exit(EXIT_FAILURE);
}
printf(" Segment Created: %d \n", shmid);
/* ----- Attaching Memory to Shared memory ----- */
char *shmbuf;
if((shmbuf=shmat(shmid,0,0))<0)
{
perror("shmat");
exit(EXIT_FAILURE);
}
printf("Segmet Attached at %p \n", shmbuf);
//system("ipcs -m");
/* ----- Creating Process Using Fork ----- */
int p,i; //i is counter
for (i=1; i<=20; i++) //loop for counter
{
p=fork(); //defining fork
if (p<0)
{
printf("Fork Failed"); //Fork Fails if P<0
exit(-1);
}
else if (p==0) //Child Process
{
printf("Counter: %d\t Process ID: %d\n" ,i,getpid());
//Prints Counter Value and Process ID.
}
else //Parent Process
{
wait(NULL); //Waits Child Process to Complete
exit(0);
}
}
/* ----- Deattaching Memory -----*/
if((shmdt(shmbuf))<0)
{
perror("shmat");
exit(EXIT_FAILURE);
}
printf("Segmet Deattached at %p \n", shmbuf);
//system("ipcs -m");
/* ----- Exiting Program ----- */
exit(0);
puts("\n End\n");
}
I now have to apply the concept of semaphore to this program, using semget(), semop(), and semctl(). Can I please get help on how to use the three functions in my program?
The advantage of semaphores over other synchronization mechanisms is that they can be used to synchronize two related or unrelated processes trying to access the same resource.
Related Process
The processes are said to be related if the new process is created from within an existing process, which ends up in duplicating the resources of the creating process. Such processes are called related processes. The following example shows how the related processes are synchronized.
file prog.c
#include <semaphore.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
int main(int argc, char **argv) { int fd, i,count=0,nloop=10,zero=0,*ptr; sem_t mutex;
//open a file and map it into memory
fd = open("log.txt",O_RDWR|O_CREAT,S_IRWXU); write(fd,&zero,sizeof(int)); ptr = mmap(NULL,sizeof(int),PROT_READ |PROT_WRITE,MAP_SHARED,fd,0); close(fd);
/* create, initialize semaphore */ if( sem_init(&mutex,1,1) < 0)
{
perror("semaphore initilization");
exit(0);
} if (fork() == 0) { /* child process*/
for (i = 0; i < nloop; i++) {
sem_wait(&mutex);
printf("child: %d\n", (*ptr)++);
sem_post(&mutex);
}
exit(0); } /* back to parent process */ for (i = 0; i < nloop; i++) {
sem_wait(&mutex);
printf("parent: %d\n", (*ptr)++);
sem_post(&mutex); } exit(0); }
gcc prog.c -lpthread
In this example, the related process access a common piece of memory, which is synchronized.
Unrelated Process
Processes are said to be unrelated if the two processes are unknown to each other and no relationship exists between them. For example, instances of two different programs are unrelated process. If such programs try to access a shared resource, a semaphore could be used to synchronize their access. The following source code demonstrates this:
file 1: server.c
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define SHMSZ 27
char SEM_NAME[]= "vik";
int main()
{
char ch;
int shmid;
key_t key;
char *shm,*s;
sem_t *mutex;
//name the shared memory segment
key = 1000;
//create & initialize semaphore
mutex = sem_open(SEM_NAME,O_CREAT,0644,1);
if(mutex == SEM_FAILED)
{
perror("unable to create semaphore");
sem_unlink(SEM_NAME);
exit(-1);
}
//create the shared memory segment with this key
shmid = shmget(key,SHMSZ,IPC_CREAT|0666);
if(shmid<0)
{
perror("failure in shmget");
exit(-1);
}
//attach this segment to virtual memory
shm = shmat(shmid,NULL,0);
//start writing into memory
s = shm;
for(ch='A';ch<='Z';ch++)
{
sem_wait(mutex);
*s++ = ch;
sem_post(mutex);
}
//the below loop could be replaced by binary semaphore
while(*shm != '*')
{
sleep(1);
}
sem_close(mutex);
sem_unlink(SEM_NAME);
shmctl(shmid, IPC_RMID, 0);
_exit(0);
}
gcc server.c -lpthread -o server
File 2: client.c
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <semaphore.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define SHMSZ 27
char SEM_NAME[]= "vik";
int main()
{
char ch;
int shmid;
key_t key;
char *shm,*s;
sem_t *mutex;
//name the shared memory segment
key = 1000;
//create & initialize existing semaphore
mutex = sem_open(SEM_NAME,0,0644,0);
if(mutex == SEM_FAILED)
{
perror("reader:unable to execute semaphore");
sem_close(mutex);
exit(-1);
}
//create the shared memory segment with this key
shmid = shmget(key,SHMSZ,0666);
if(shmid<0)
{
perror("reader:failure in shmget");
exit(-1);
}
//attach this segment to virtual memory
shm = shmat(shmid,NULL,0);
//start reading
s = shm;
for(s=shm;*s!=NULL;s++)
{
sem_wait(mutex);
putchar(*s);
sem_post(mutex);
}
//once done signal exiting of reader:This can be replaced by another semaphore
*shm = '*';
sem_close(mutex);
shmctl(shmid, IPC_RMID, 0);
exit(0);
}
gcc client.c -lpthread -o client
The above executables (client and server) demonstrate how semaphore could be used between completely different processes.
In addition to the applications shown above, semaphores can be used cooperatively to access a resource. Please note that a semaphore is not a Mutex. A Mutex allows serial access to a resource, whereas semaphores, in addition to allowing serial access, could also be used to access resources in parallel. For example, consider resource R being accessed by n number of users. When using a Mutex, we would need a Mutex "m" to lock and unlock the resource, thus allowing only one user at a time to use the resource R. In contrast, semaphores can allow n number of users to synchronously access the resource R.

Do forked child processes use the same semaphore?

Let's say I create a semaphore. If I fork a bunch of child processes, will they all still use that same semaphore?
Also, suppose I create a struct with semaphores inside and forked. Do all the child processes still use that same semaphore? If not, would storing that struct+semaphores in shared memory allow the child processes to use the same semaphores?
I'm really confused about how my forked child processes can use the same semaphores.
Let's say I create a semaphore. If I fork a bunch of child processes, will they all still use that same semaphore?
If you are using a SysV IPC semaphore (semctl), then yes. If you are using POSIX semaphores (sem_init), then yes, but only if you pass a true value for the pshared argument on creation and place it in shared memory.
Also, suppose I create a struct with semaphores inside and forked. Do all the child processes still use that same semaphore? If not, would storing that struct+semaphores in shared memory allow the child processes to use the same semaphores?
What do you mean be 'semaphores inside'? References to SysV IPC semaphores will be shared, because the semaphores don't belong to any process. If you're using POSIX semaphores, or constructing something out of pthreads mutexes and condvars, you will need to use shared memory, and the pshared attribute (pthreads has a pshared attribute for condvars and mutexes as well)
Note that anonymous mmaps created with the MAP_SHARED flag count as (anonymous) shared memory for these purposes, so it's not necessary to actually create a named shared memory segment. Ordinary heap memory will not be shared after a fork.
Let's say I create a semaphore. If I fork a bunch of child processes,
will they all still use that same semaphore?
It depends how you created the semaphore, to do that with an IPC semaphore see semaphore.c: Illustration of simple semaphore passing for an example.
Also, suppose I create a struct with semaphores inside and forked. Do
all the child processes still use that same semaphore? If not, would
storing that struct+semaphores in shared memory allow the child
processes to use the same semaphores?
For that to work your semaphore needs to be stored in an area shared between the parent and the child process like shared memory, and not just created on the stack or on the heap because it will be copied when the process forks.
I'm really confused about how my forked child processes can use the
same semaphores.
The semaphore can be shared across threads or processes. Cross-process sharing is implemented on the operating system level. Two or more different processes can share the same semaphore even if those processes were not created by forking a single parent process.
See this example for sharing an unnamed UNIX semaphore between a parent process and its child (to compile with gcc you'll need the -pthread flag):
#include <semaphore.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
int main(void)
{
/* place semaphore in shared memory */
sem_t *sema = mmap(NULL, sizeof(*sema),
PROT_READ |PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,
-1, 0);
if (sema == MAP_FAILED) {
perror("mmap");
exit(EXIT_FAILURE);
}
/* create/initialize semaphore */
if ( sem_init(sema, 1, 0) < 0) {
perror("sem_init");
exit(EXIT_FAILURE);
}
int nloop=10;
int pid = fork();
if (pid < 0) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid == 0) {
/* child process*/
for (int i = 0; i < nloop; i++) {
printf("child unlocks semaphore: %d\n", i);
if (sem_post(sema) < 0) {
perror("sem_post");
}
sleep(1);
}
if (munmap(sema, sizeof(sema)) < 0) {
perror("munmap");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
if (pid > 0) {
/* back to parent process */
for (int i = 0; i < nloop; i++) {
printf("parent starts waiting: %d\n", i);
if (sem_wait(sema) < 0) {
perror("sem_wait");
}
printf("parent finished waiting: %d\n", i);
}
if (sem_destroy(sema) < 0) {
perror("sem_destroy failed");
exit(EXIT_FAILURE);
}
if (munmap(sema, sizeof(sema)) < 0) {
perror("munmap failed");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
}
The output will be:
parent starts waiting: 0
child unlocks semaphore: 0
parent finished waiting: 0
parent starts waiting: 1
child unlocks semaphore: 1
parent finished waiting: 1
...
You may want to read Semaphores in Linux as well, but be aware that the example of UNIX semaphores across fork given doesn't work because the author forgot to use the MAP_ANONYMOUS flag in mmap.
Try this
child and parent would increment the shared variable alternatively
#include <semaphore.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
struct test {
sem_t mutex1;
sem_t mutex2;
int temp;
}test1;
int main(int argc, char **argv)
{
int fd, i,count=0,nloop=10,zero=0,*ptr;
struct test *testptr;
//open a file and map it into memory
sem_t mutex;
fd = open("log.txt",O_RDWR|O_CREAT,S_IRWXU);
write(fd,&zero,sizeof(int));
ptr = mmap(NULL, sizeof(struct test),PROT_READ |PROT_WRITE,MAP_SHARED,fd,0);
close(fd);
memcpy(ptr, &test1, sizeof(test1));
testptr = (struct test *)ptr;
// testptr = (struct test *)&test1;
/* create, initialize semaphore */
if( sem_init(&(testptr->mutex1),1,1) < 0)
{
perror("semaphore initilization");
exit(0);
}
/* create, initialize semaphore */
if( sem_init(&(testptr->mutex2),1,0) < 0)
{
perror("semaphore initilization");
exit(0);
}
if (fork() == 0) { /* child process*/
for (i = 0; i < nloop; i++) {
sem_wait(&(testptr->mutex2));
printf("child: %d\n", testptr->temp++);
sem_post(&(testptr->mutex1));
}
exit(0);
/* back to parent process */
for (i = 0; i < nloop; i++) {
sem_wait(&testptr->mutex1);
printf("parent: %d\n", testptr->temp++);
sem_post(&(testptr->mutex2));
}
exit(0);
}

Resources