Ваша главная проблема заключается в следующем:
if (fork()!=0) //<-- this
fork()
вернет -1 в случае ошибки, родительский pid, ИЛИ НОЛЬ для ребенка.Таким образом, вы на самом деле делаете все в родительском.Измените на (fork () == 0), и оно сделает то, что вы хотите.
Также вам следует подождать со своими детьми и отсоединить разделяемую память.(Я добавил некоторые выходные данные идентификаторов процесса, чтобы сделать его немного понятнее.)
printf("I AM THE PARENT pid = %d\n", getpid());
*buf = 0;
for(i=1; i<=20; ++i)
{
if((pid = fork()) == -1)
{
perror("fork");
exit(1);
}
if (pid == 0)
{
v(semid, 0);
*buf += 1;
p(semid, 0);
printf("I am child %d with pid = %d\n", i, getpid());
shmdt(buf);
exit(0);
}
}
for (i = 1; i <= 20; ++i)
{
pid = wait(&status);
printf("child pid = %d reaped\n", pid);
}
printf("buf: %p\n", buf);
printf("*buf: %d\n", *buf);
shmdt(buf);
return 0;