Working with semaphores and shared memory in C - c

The program should create 200000 integers and write 2000 to a shared memory. A forked process should read 2000 from shared memory and the parent should write the next 2000 to shared memory.
if i use the code below without sleep, the parent first creates all 200000 integers and then the child reads the same integers from shared memory.
With sleep everything looks good, but we have to use semaphore.
shm.c (parent):
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/resource.h>
#include <sys/wait.h>
#define N_DATA 200000
#define N_SHARED 2000
#define LOCK -1
#define UNLOCK 1
static struct sembuf semaphore;
char shmidArg[32];
char semidArg[32];
int *shmData;
int i, j;
int status;
char *strsignal(int sig);
pid_t pid;
static int shmid;
static int semid;
char *strsignal(int sig);
/** Semaphore Operation */
static int semaphore_operation (int op) {
semaphore.sem_num = 1;
semaphore.sem_op = op;
semaphore.sem_flg = IPC_NOWAIT;
if( semop (semid, &semaphore, 1) == -1) {
perror(" semop ");
exit (EXIT_FAILURE);
}
return 1;
}
int main(int argc, char **argv) {
/* Ein Shared-Memory-Segment einrichten */
shmid = shmget(IPC_PRIVATE, N_SHARED*sizeof(int), IPC_CREAT | SHM_R | SHM_W);
if (shmid == -1) {
perror("shmid");
exit(1);
}
printf("Shared-Memory-ID: %d\n",shmid);
/* Pointer zu Shared-Memory-Segment erhalten */
shmData = (int *)shmat(shmid,0, 0);
if (shmData == (int *)(-1)) {
perror("shmat");
exit(1);
}
/* Semaphore anlegen */
semid = semget(IPC_PRIVATE, 1, IPC_CREAT | SHM_R | SHM_W);
if (semid < 0) {
perror("semid");
exit(1);
}
printf ("Semaphor-ID : %d\n", semid);
/* Semaphor mit 1 initialisieren */
if (semctl (semid, 0, SETVAL, (int) 1) == -1) {
perror("semctl");
}
snprintf(shmidArg,32, "%d", shmid);
snprintf(semidArg,32, "%d", semid);
/** erstellen des Kindprozesses */
pid = fork();
// Kindprozess
if (pid == 0) {
execlp("./shm_child",shmidArg,semidArg,NULL);
} else if (pid < 0) {
perror("Kindprozess konnte nicht erzeugt werden!");
return 1;
}
// Elternprozess
else {
/** ininitalisieren des Zufallsgenerator durch aktuellen Zeitstempel */
srand48(time(NULL));
for(i=0;i<N_DATA;i=i+N_SHARED) {
semaphore_operation(LOCK);
for (j=0; j<N_SHARED; j++) {
shmData[j] = lrand48();
//MSZ
//printf("SHM-->%d-->%d\n",i+1,shmData[i]);
}
// if(i == 0 || i == 2000) {
printf("Parent-->%d-->0-->%d\n",i,shmData[0]);
printf("Parent-->%d-->1999->%d\n",i,shmData[1999]);
// }
semaphore_operation(UNLOCK);
//sleep(1);
}
}
//MSZ
//sleep(2);
printf("PID: %d\n", pid);
if (waitpid(pid, &status, 0) == -1) {
perror("wait konnte nicht erzeugt werden!");
return 1;
}
if (WIFEXITED(status)) {
printf("Exitcode: %d\n", WEXITSTATUS(status));
semctl (semid, 0, IPC_RMID, 0);
shmctl (shmid, IPC_RMID, NULL);
//If process terminaded by a signal
} else if (WIFSIGNALED(status)) {
printf("Signal: %d %s\n", WTERMSIG(status), strsignal(WTERMSIG(status)));
semctl (semid, 0, IPC_RMID, 0);
shmctl (shmid, IPC_RMID, NULL);
}
}
shm_child.c (Child):
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#define N_DATA 6000
#define N_SHARED 2000
#define LOCK -1
#define UNLOCK 1
int i,j;
int *shmData;
static int shmid;
static int semid;
static struct sembuf semaphore;
/** Semaphore Operation */
static int semaphore_operation (int op) {
semaphore.sem_num = 0;
semaphore.sem_op = op;
semaphore.sem_flg = SEM_UNDO;
if( semop (semid, &semaphore, 1) == -1) {
perror(" semop ");
exit (EXIT_FAILURE);
}
return 1;
}
int main(int argc, char **argv) {
shmid = atoi(argv[0]);
semid = atoi(argv[1]);
printf("\nshm_child shared memoryid:%d\n",shmid);
printf("shm_child Semaphoren-ID:%d\n",semid);
/* Pointer auf Shared-Memory erstellen */
shmData = (int *)shmat(shmid,0,0);
if (shmData == (int *)(-1)) {
perror("shmat");
exit(1);
}
for(i=0;i<N_DATA;i=i+N_SHARED) {
semaphore_operation(LOCK);
for(j=0;j<N_SHARED;j++) {
//printf("%d-->%d --> %d\n",i,j+1,shmData[j]);
}
// if(i == 0 || i == 2000) {
printf("child-->%d-->0-->%d\n",i,shmData[0]);
printf("child-->%d-->1999->%d\n",i,shmData[1999]);
// }
semaphore_operation(UNLOCK);
sleep(1);
}
return 0;
}
Please help us
Thank you guys
Edit: Thank you very much for your answers. I can't mark the right answer because i dont know what its right. But i dont want try anything more. 15 hours are enough

The writer process shall give reader a permission to read, and wait for the reading completion. After that the reader shall give writer a permission to proceed, and wait for writing completion.
This goal cannot be achieved with a single semaphore. You need two, along the lines of:
// parent aka writer
writer_barrier = semaphore(UNLOCKED);
reader_barrier = semaphore(LOCKED);
start_reader();
while(...) {
lock(writer_barrier);
write_data();
unlock(reader_barrier);
}
// child aka reader
while(....)
lock(reader_barrier);
read_data();
unlock(writer_barrier);
}

Related

Synchronizing two child processes with semaphores in c

I have to create a program that synchronizes two processes each printing only a single letter so that whenever we observe the output of the program, the difference between the amount of "A" and "B" is no greater than 2.
So this would be accepted:
BAABBAABBABA
this wouldn't be because it prints 4 B's and only 2 A's:
ABBABB
So for starters i decided to use the POSIX semaphores.
I created two semaphores , giving them all the permissions using the sem_open
Then i created two child processes and for each child process i open the semaphores i created as described in the man page for sem_open and manipulate them.
I don't think it's the logic of the sem_post and sem_wait that's at fault here, since the program seems to ignore them.
So my question is. What goes wrong?
Edit: I don't really need the solution to the problem. Some guidance alone would be much appreciated and welcoming as an answer. Thank you in advance!
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <semaphore.h>
int main(void){
sem_t *semA = sem_open("/semA", O_CREAT|O_EXCL, S_IRWXU | S_IRWXG | S_IRWXO, 0); //Initialize semaphore(= 0) for process A
sem_t *semB = sem_open("/semB", O_CREAT|O_EXCL, S_IRWXU | S_IRWXG | S_IRWXO, 0); //Initialize semaphore(= 0) for process B
if (fork()){ // parent process
if(fork()){}
else{
sem_t *childsemA = sem_open("/semA", 0);
sem_t *childsemB = sem_open("/semB", 0);
while(1){
printf("A");
sem_post(childsemB);
sem_wait(childsemA);
}
}
}
else{
sem_t *childsemA = sem_open("/semA", 0);
sem_t *childsemB = sem_open("/semB", 0);
while(1){
printf("B"); // child2 process
sem_post(childsemA);
sem_wait(childsemB);
}
}
return 0;
}
Output:
May i suggest you to use System V semaphores? This is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/sem.h>
#include "Semaphores.h"
#define SEM1_KEY (key_t)888
#define SEM2_KEY (key_t)1234
int sem1, sem2;
int main()
{
pid_t pid;
sem1 = semget(SEM1_KEY, 1, IPC_CREAT | 0666);
if(sem1 < 0)
{
fprintf(stderr, "\nSEMGET Failed\n");
exit(EXIT_FAILURE);
}
sem2 = semget(SEM2_KEY, 1, IPC_CREAT | 0666);
if(sem1 < 0)
{
fprintf(stderr, "\nSEMGET Failed\n");
exit(EXIT_FAILURE);
}
SEM_SET(sem1, 1);
SEM_SET(sem2, 0);
if((pid = fork()) == -1)
{
fprintf(stderr, "\nError in fork()\n");
exit(EXIT_FAILURE);
}
if(pid == 0)
{
while(1)
{
SEM_WAIT(sem2);
printf("%c", 'B');
fflush(stdout);
sleep(1);
SEM_POST(sem1);
}
}
while(1)
{
SEM_WAIT(sem1);
printf("%c", 'A');
fflush(stdout);
sleep(1);
SEM_POST(sem2);
}
wait(0);
SEM_DEL(sem1);
SEM_DEL(sem2);
exit(EXIT_SUCCESS);
}
And this is the header file Semaphores.h which includes the System V semaphores implementation:
#include <sys/sem.h>
union semun
{
int val;
struct semid_ds * buf;
unsigned short * array;
};
int SEM_SET(int sem_id, int sem_val)
{
union semun sem_union;
sem_union.val = sem_val;
return semctl(sem_id, 0, SETVAL, sem_union);
}
int SEM_DEL(int sem_id)
{
return semctl(sem_id, 0, IPC_RMID);
}
int SEM_WAIT(int sem_id)
{
struct sembuf sem_buf;
sem_buf.sem_num = 0;
sem_buf.sem_op = -1;
sem_buf.sem_flg = SEM_UNDO;
return semop(sem_id, &sem_buf, 1);
}
int SEM_POST(int sem_id)
{
struct sembuf sem_buf;
sem_buf.sem_num = 0;
sem_buf.sem_op = 1;
sem_buf.sem_flg = SEM_UNDO;
return semop(sem_id, &sem_buf, 1);
}
The result will be this:
ABABABABABABABABA and so on
fflush() was probably the problem, but your code has some leaks, you need to understand what is a critical section, and you need to check for the return values of fork().

Producer consumer semaphore value is not correct

I'm trying to implement producer-consumer problem in C using processes and System V IPC and I'm stuck on one thing. This is early version of my code (without implementing queue operations or even producer and consumer executing in loop) that I was using to learn and test how semaphores work:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>
#include <time.h>
#include "sem.h"
#include "shm.h"
#define BUFFER_SIZE 9
int full;
int empty;
int mutex;
struct buff {
int queue[BUFFER_SIZE];
} *buffer;
void producer();
void consumer();
int main() {
int parent_pid, pid, i;
parent_pid = getpid();
int shmid = allocate_shared_memory(sizeof(*buffer));
buffer = (struct buff *) attach_shared_memory(shmid);
for (i = 0; i < BUFFER_SIZE; i++) {
buffer->queue[i] = 0;
}
full = sem_allocate();
empty = sem_allocate();
mutex = sem_allocate();
printf("Full %d\n", full);
printf("Empty %d\n", empty);
printf("Mutex %d\n", mutex);
sem_init(full, 0);
sem_init(empty, BUFFER_SIZE);
sem_init(mutex, 1);
printf("Full value %d\n", sem_get_val(full));
printf("Empty value %d\n", sem_get_val(empty));
printf("Mutex value %d\n", sem_get_val(mutex));
srand(time(0));
pid = fork();
if (!pid) {
printf("Producer here: %d\n", getpid());
producer();
printf("Full value after prod() %d\n", sem_get_val(full));
return 0;
} else printf("Created new producent: %d\n", pid);
sleep(1);
pid = fork();
if (!pid) {
printf("Consumer here: %d\n", getpid());
printf("Full value before cons() %d\n", sem_get_val(full)); //here I always get 0
consumer();
return 0;
} else printf("Created new consumer: %d\n", pid);
while (1)
{
int status;
pid_t done = wait(&status);
if (done == -1)
{
if (errno == ECHILD) break; // no more child processes
}
else
{
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
exit(1);
}
}
}
if (getpid() == parent_pid) {
sem_deallocate(full);
sem_deallocate(empty);
sem_deallocate(mutex);
}
}
void producer() {
sem_wait(empty);
sem_wait(mutex);
printf("Producer is producing!\n");
buffer->queue[0]=0;
sem_post(mutex);
sem_post(full);
}
void consumer() {
sem_wait(full);
sem_wait(mutex);
printf("Consumer is consuming!\n");
sem_post(mutex);
sem_post(empty);
}
int sem_allocate() {
return semget(IPC_PRIVATE, 1, IPC_CREAT | 0666);
}
void sem_deallocate(int semid) {
if (semctl(semid, 0, IPC_RMID, NULL) == -1)
{
perror("Error releasing semaphore!\n");
exit(EXIT_FAILURE);
}
}
int sem_init(int semid, int value) {
union semun arg;
arg.val = value;
if (semctl(semid, 0, SETVAL, arg) == -1) {
perror("semctl");
return -1;
}else return 1;
}
int sem_wait(int semid) {
printf("Someone is waiting %d\n", semid);
struct sembuf sem = { 0, -1, SEM_UNDO };
return semop(semid, &sem, 1);
}
int sem_post(int semid) {
printf("Someone is posting %d\n", semid);
struct sembuf sem = { 0, 1, SEM_UNDO };
return semop(semid, &sem, 1);
}
int sem_get_val(int semid) {
return semctl(semid, 0, GETVAL, 0);
}
int allocate_shared_memory(int size) {
return shmget(IPC_PRIVATE, size, IPC_CREAT | SHM_W | SHM_R);
}
void deallocate_shared_memory(const void* addr, int shmid) {
shmctl(shmid, IPC_RMID, 0);
}
void* attach_shared_memory(int shmid) {
return shmat(shmid, NULL, 0);
}
sem.h:
#include <sys/types.h>
#include <errno.h>
union semun {
int val;
struct semid_ds *buf;
ushort* array;
};
int sem_post(int);
int sem_wait(int);
int sem_allocate();
void sem_deallocate(int);
int sem_init(int, int);
int sem_get_val(int);
shm.h:
#include <stdio.h>
#include <sys/shm.h>
#include <sys/stat.h>
int allocate_shared_memory(int size);
void deallocate_shared_memory(const void* addr, int shmid);
void* attach_shared_memory(int shmid);
Why before executing consumer function value of full semaphore is 0? Even if right after producer finishes his job the value is 1...
I'm new to this kind of topics so maybe there is an obvious explenation of the situation, but I have no idea what can I do and hope you can help me.
You initialize the "full" semaphore to zero. Your "child" producer, prior to exiting calls your sem_post() function, which calls semop() with a SEM_UNDO argument.
int sem_post(int semid) {
printf("Someone is posting %d\n", semid);
struct sembuf sem = { 0, 1, SEM_UNDO };
return semop(semid, &sem, 1);
}
The Ubuntu Linux man page for semop says the following about SEM_UNDO:
... If an operation specifies SEM_UNDO, it will be automatically
undone when the process terminates.
This means, "producer" increments "full" prior to exiting, then after it exits the system "undoes" the increment (i.e. it decrements "full") setting it back to zero.
So,for the purposes of the "full" semaphore, you should NOT specify SEM_UNDO.

Confusion with forked process?

I am trying to do first child function, for example, printing out a string : hello!, and go back to parent process. Then, I forked anothrer n processes for the second child function, which will count the shared memory number. I suppose there only shows one "all done" in the end, but it shows two? thanks for your help!
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/shm.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/wait.h>
#include <fcntl.h>
#define NUM_LINES 5
char * shm;
void child_func(char *shm)
{
while (atoi(shm) != NUM_LINES)
{
// P(sem);
printf("now reading word:%d\n", atoi(shm) );
*shm+=1;
// V(sem);
}
exit(0);
}
void parent_func(pid_t pid)
{
int status;
pid_t pid_wait;
do
{
pid_wait = waitpid(pid, &status, WNOHANG);
}while (pid_wait != pid);
// printf("Process %d done\n", getppid());
}
int main(int argc, char const *argv[])
{
/* declarations */
pid_t pid[8];
int ret, shmid, status,corpse, i, ave, n;
char fn[20];
key_t key = 123;
char *string_back;
/* create share memory */
if ((shmid = shmget(key, SHMSIZE, IPC_CREAT|666)) <0)
{
perror("shmget");
exit(1);
}
/* attach shm */
if ((shm = shmat(shmid, NULL, 0)) == (char*)-1)
{
perror("shmat");
exit(1);
}
/* init shm value */
*shm = '0';
/* input */
printf("please enter n:\n");
scanf("%d", &n);
/* section 1 */
pid[0] = fork();
if (pid[0] == 0) // child processes
{
printf("hello !\n");
}
else if (pid[0] >0)
{
parent_func(pid[0]);
}
/* section 2 */
for (i=0;i<n;i++)
{
pid[i] = fork();
if (pid[i] == 0) // child processes
{
child_func(shm);
}
else if (pid[i] >0)
{
parent_func(pid[i]);
}
}
printf("all done\n");
/* detach shm */
shmdt(shm);
/* destroy shm */
int retval = shmctl(shmid, IPC_RMID, NULL);
if (retval < 0) perror("remove shm");
return 0;
}
After adding exit(0) in first section, I only get one "all done" in the last, which is the answer I want.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/shm.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/wait.h>
#include <fcntl.h>
#define NUM_LINES 5
char * shm;
void child_func(char *shm)
{
while (atoi(shm) != NUM_LINES)
{
// P(sem);
printf("now reading word:%d\n", atoi(shm) );
*shm+=1;
// V(sem);
}
exit(0);
}
void parent_func(pid_t pid)
{
int status;
pid_t pid_wait;
do
{
pid_wait = waitpid(pid, &status, WNOHANG);
}while (pid_wait != pid);
// printf("Process %d done\n", getppid());
}
int main(int argc, char const *argv[])
{
/* declarations */
pid_t pid[8];
int ret, shmid, status,corpse, i, ave, n;
char fn[20];
key_t key = 123;
char *string_back;
/* create share memory */
if ((shmid = shmget(key, SHMSIZE, IPC_CREAT|666)) <0)
{
perror("shmget");
exit(1);
}
/* attach shm */
if ((shm = shmat(shmid, NULL, 0)) == (char*)-1)
{
perror("shmat");
exit(1);
}
/* init shm value */
*shm = '0';
/* input */
printf("please enter n:\n");
scanf("%d", &n);
/* section 1 */
pid[0] = fork();
if (pid[0] == 0) // child processes
{
printf("hello !\n");
/* problem solved here */
exit(0);
}
else if (pid[0] >0)
{
parent_func(pid[0]);
}
/* section 2 */
for (i=0;i<n;i++)
{
pid[i] = fork();
if (pid[i] == 0) // child processes
{
child_func(shm);
}
else if (pid[i] >0)
{
parent_func(pid[i]);
}
}
printf("all done\n");
/* detach shm */
shmdt(shm);
/* destroy shm */
int retval = shmctl(shmid, IPC_RMID, NULL);
if (retval < 0) perror("remove shm");
return 0;
}

Use semaphores to synchronize shared memory

I have the following code which works fine with the sleep time. But I want to remove sleep and use semaphores to synchronize the threads ( so that the reader waits till data is available in shmptr.) How do I do that? What do I use:
sem_t mutex or
pthread_mutex_t mutex?
P.S : I tried using both above options separately (not shown in above code though) but didn't get desired result.Most of the times I was getting error in shmget in reader - "shmget in reader: No such file or directory".
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <semaphore.h>
#include <errno.h>
void *write(void *t)
{ char str[100] = "\0";
char str1[50];
key_t key;
char *shmptr;
int shmid;
if( (key = ftok("shmSemphore.c",'B')) == -1)
{
perror("ftok in writer");
pthread_exit(NULL);
}
if( (shmid = shmget(key, 1024, 0666 | IPC_CREAT)) == -1)
{
perror("shmget in writer");
pthread_exit(NULL);
}
shmptr = shmat(shmid,0,0);
if( (shmptr == (char *)(-1)))
{
perror("shmget in writer");
pthread_exit(NULL);
}
printf("ENter your text :- ");
//scanf("%s",str);
fgets(str,sizeof(str),stdin);
strcpy(shmptr,str);
sleep(2);
shmdt(shmptr);
if( shmctl(shmid, IPC_RMID, NULL) == -1 )
{
perror("shmctl");
exit(-1);
}
pthread_exit(NULL);
}
void *read(void *t)
{ sleep(2);
key_t key;
char *shmptr;
int shmid;
if( (key = ftok("shmSemphore.c",'B')) == -1)
{
perror("ftok in writer");
pthread_exit(NULL);
}
if( (shmid = shmget(key, 1024, 0)) == -1)
{
perror("shmget in reader");
pthread_exit(NULL);
}
shmptr = shmat(shmid,0,0);
if( (shmptr == (char *)-1))
{
perror("shmget in writer");
pthread_exit(NULL);
}
printf("your text:- %s \n",shmptr);
pthread_exit(NULL);
}
int main()
{
pthread_t reader,writer;
int rt;
long t = 0;
rt = pthread_create(&writer,NULL,write,(void *)t);
/*if(rt == -1)
{ perror("writer thread");
pthread_exit(NULL);
}*/
rt = pthread_create(&reader,NULL,read,(void *)t);
/*if(rt == -1)
{ perror("writer thread");
pthread_exit(NULL);
}*/
pthread_join(writer,NULL);
pthread_join(reader,NULL);
return 0;
}

Working with semaphores and shared memory under Linux

I need to write a program that is creating a N amount of sub processes and every single one of them adds one to a shared memory variable. My idea is to use semaphores and shared memory, but the processes are not waiting for each other and the shared memory variable is also not working as I want it.
mydefs.h
#ifndef __MYDEFS__H__
#define __MYDEFS__H__
// Includes
#include <stdio.h>
#include <unistd.h>
#include <semaphore.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <memory.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <sys/shm.h>
#endif // __MYDEFS__H__
main.c
#include "mydefs.h"
#define PROC_COUNT 3
#define INITAL_MARKER_VALUE 0
#define PID_LEN 32
char mypid[PID_LEN];
int main()
{
int i, shm_id;
sem_t mutex;
if(sem_init(&mutex,1,1) < 0)
{
perror("semaphore initilization");
exit(0);
}
shm_id = shmget(IPC_PRIVATE, 4*sizeof(int), IPC_CREAT | 0666);
if (shm_id < 0) {
printf("shmget error\n");
}
int *shmpointer = shmat(shm_id,0,0);
memset(mypid, 0, sizeof(mypid));
sprintf(mypid, "%06d", getpid());
for(i = 0; i < PROC_COUNT; i++)
{
if (fork() == 0)
{
while(sem_wait(&mutex)!=0);
execl("slaveproc", "slaveproc", mypid, (char *)0);
shmpointer += 1;
sem_post(&mutex);
perror("\n Can't exec slave program. Cause ");
exit(1);
}
}
sleep(1);
printf("%d\n", *shmpointer);
return 0;
}
slaveproc.c
#include "mydefs.h"
int marker; // Marker value
int main(int argc, char *argv[])
{
master_pid = atoi(argv[1]);
printf("\n --------------------------------------");
printf("\n I'm the slave proc!");
printf("\n My pid: %d", getpid());
printf("\n My master's pid: %d", master_pid);
printf("\n --------------------------------------");
for(;;) pause();
return 0;
}
The problem (or at least "a problem") is that mutex is not in shared memory: it's allocated on the stack. When you fork(), the new process will have a completely separate copy from the old process, so calling sem_wait(&mutex) on one process will not affect the other process's mutex at all.
You should put mutex in the shared memory:
int main()
{
int i, shm_id;
shm_id = shmget(IPC_PRIVATE, sizeof(sem_t) + 4*sizeof(int), IPC_CREAT | 0666);
if (shm_id < 0) {
printf("shmget error\n");
}
int *shmpointer = shmat(shm_id,0,0);
sem_t *mutex = shmpointer;
shmpointer = (void*)shmpointer + sizeof(sem_t);
if(sem_init(mutex,1,1) < 0)
{
perror("semaphore initilization");
exit(0);
}
memset(mypid, 0, sizeof(mypid));
sprintf(mypid, "%06d", getpid());
for(i = 0; i < PROC_COUNT; i++)
{
if (fork() == 0)
{
while(sem_wait(mutex)!=0);
execl("slaveproc", "slaveproc", mypid, (char *)0);
shmpointer += 1;
sem_post(mutex);
perror("\n Can't exec slave program. Cause ");
exit(1);
}
}
sleep(1);
printf("%d\n", *shmpointer);
return 0;
}
You're also never writing to the memory in shmpointer (perhaps you meant (*shmpointer) += 1?), but I'll let you figure that out on your own.

Resources