I'm attempting to create a C program where the counter is incremented by alternating between the parent and child using the POSIX semaphore functions. So far I'm having trouble using it considering this is the first time I am using semaphore functions so if there is anything wrong with my program some pointers would be great as well.
So far my current issue is using the dereferencing void *
pointer and I'm unsure how to go on since the mmap
is a void pointer according to the Linux programmer's manual.
gcc -ansi -I -Wl -Wall -DLINUX -D_GNU_SOURCE devzeroMyEdit.c -L /lib -pthread -lrt -o devzeroMyEdit
devzeroMyEdit.c: In function ‘main’:
devzeroMyEdit.c:37:16: warning: dereferencing ‘void *’ pointer
sem_init(&shmp->parent, 1, 0);
^~
devzeroMyEdit.c:37:16: error: request for member ‘parent’ in something not a structure or union
devzeroMyEdit.c:38:16: warning: dereferencing ‘void *’ pointer
sem_init(&shmp->child, 1, 1); /* Child first */
^~
devzeroMyEdit.c:38:16: error: request for member ‘child’ in something not a structure or union
devzeroMyEdit.c:40:13: warning: implicit declaration of function ‘fork’ [-Wimplicit-function-declaration]
if ((pid = fork()) < 0) {
^~~~
devzeroMyEdit.c:45:18: warning: dereferencing ‘void *’ pointer
sem_wait(&shmp->child);
^~
devzeroMyEdit.c:45:18: error: request for member ‘child’ in something not a structure or union
devzeroMyEdit.c:50:18: warning: dereferencing ‘void *’ pointer
sem_post(&shmp->parent);
^~
devzeroMyEdit.c:50:18: error: request for member ‘parent’ in something not a structure or union
devzeroMyEdit.c:56:18: warning: dereferencing ‘void *’ pointer
sem_wait(&shmp->parent);
^~
devzeroMyEdit.c:56:18: error: request for member ‘parent’ in something not a structure or union
devzeroMyEdit.c:61:18: warning: dereferencing ‘void *’ pointer
sem_post(&shmp->child);
^~
devzeroMyEdit.c:61:18: error: request for member ‘child’ in something not a structure or union
<builtin>: recipe for target 'devzeroMyEdit' failed
make: *** [devzeroMyEdit] Error 1
My program:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <semaphore.h>
#define NLOOPS 1000
#define SIZE sizeof(long) /* size of shared memory area */
struct shmbuf{
sem_t child;
sem_t parent;
};
static int update(long *ptr)
{
return((*ptr)++); /* return value before increment */
}
int main(void)
{
int fd, i, counter;
pid_t pid;
void *shmp;
if ((fd = shm_open("/dev/zero", O_RDWR, ALLPERMS)) < 0)
perror("open error");
if ((shmp = mmap(0, sizeof(struct shmbuf), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED)
perror("mmap error");
sem_init(&shmp->parent, 1, 0);
sem_init(&shmp->child, 1, 1); /* Child first */
if ((pid = fork()) < 0) {
perror("fork error");
} else if (pid > 0) { /* Parent */
for (i = 0; i < NLOOPS; i += 2) {
sem_wait(&shmp->child);
if ((counter = update((long *)shmp)) != i)
printf("parent: expected %d, got %d", i, counter);
sem_post(&shmp->parent);
}
} else { /* Child */
for (i = 1; i < NLOOPS + 1; i += 2) {
sem_wait(&shmp->parent);
if ((counter = update((long *)shmp)) != i)
printf("child: expected %d, got %d", i, counter);
sem_post(&shmp->child);
}
}
return(0);
}
The type of shmp
should obviously be struct shmbuf*
and not void*
. Dereferencing a void pointer doesn't make sense.
shmp = mmap(0, ...)
is legal, even if the type of shmp
is not void*
, because void pointers are safely promoted to any other pointer type.
So just change void *shmp
to struct shmbuf *shmp
.
Bonus: you also forgot #include <unistd.h>
.