У вас есть состояние гонки.
Когда основной процесс выполняет sem_post
, он зацикливается [быстро] и [почти] немедленно выполняет следующий sem_wait
и получает семафордо того, как дочерний процесс сможет его получить.
Простое / наивное решение состоит в добавлении небольшого usleep
внизу каждого цикла:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <semaphore.h>
int
main()
{
sem_t *sem;
setlinebuf(stdout);
sem = sem_open("share", O_CREAT, 0, 1);
sem_unlink("share");
int i;
if (fork()) {
for (i = 0; i < 10; i++) {
sem_wait(sem);
printf("Hello world\n");
sem_post(sem);
usleep(10);
}
wait(NULL);
}
else {
for (i = 0; i < 10; i++) {
sem_wait(sem);
printf("Bonjour monde\n");
sem_post(sem);
usleep(10);
}
}
return 0;
}
теперь вывод:
Hello world
Bonjour monde
Hello world
Bonjour monde
Hello world
Bonjour monde
Hello world
Bonjour monde
Hello world
Bonjour monde
Hello world
Bonjour monde
Hello world
Bonjour monde
Hello world
Bonjour monde
Hello world
Bonjour monde
Hello world
Bonjour monde
ОБНОВЛЕНИЕ:
Как упоминалось ниже, решение семафоров two лучше, поскольку оно гарантируетчередование:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <semaphore.h>
int
main()
{
sem_t *sempar;
sem_t *semcld;
setlinebuf(stdout);
sem_unlink("parent");
sempar = sem_open("parent", O_CREAT, 0, 1);
// by blocking child semaphore, this guarantees parent starts first
sem_unlink("child");
semcld = sem_open("child", O_CREAT, 0, 0);
int i;
if (fork()) {
for (i = 0; i < 10; i++) {
sem_wait(sempar);
printf("Hello world (%d)\n",i);
sem_post(semcld);
}
wait(NULL);
}
else {
for (i = 0; i < 10; i++) {
sem_wait(semcld);
printf("Bonjour monde (%d)\n",i);
sem_post(sempar);
}
}
return 0;
}
ОБНОВЛЕНИЕ № 2:
Но результат не случайный, он печатает HelloWorld, а затем Bonjour и повтор.
Хорошо, тогда решение с одним семафором лучше, с некоторыми модификациями:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <sys/wait.h>
#include <semaphore.h>
sem_t *sem;
void
doloop(time_t seed,const char *msg)
{
int i;
int rval;
srand(seed);
for (i = 0; i < 30; i++) {
rval = rand() % 100000;
sem_wait(sem);
printf("%s i=%d rval=%d\n",msg,i,rval);
sem_post(sem);
usleep(rval);
}
}
int
main()
{
time_t seed;
setlinebuf(stdout);
sem_unlink("share");
sem = sem_open("share", O_CREAT, 0, 1);
seed = time(NULL);
if (fork()) {
doloop(seed,"Hello World");
wait(NULL);
}
else {
doloop(seed ^ ~0,"Bonjour monde");
}
return 0;
}