c-用于同步的全局信号量-计数器



下面我在两个不同的进程中增加一个计数器1000,并使用全局信号量进行同步。但是iCounter不给我2000?有人能解释一下原因吗?

#include <stdio.h>
#include <semaphore.h>
#include <stdlib.h>
#include <fcntl.h>
#define SEM_NAME "/sync"
#define NUMBER_OF_PROCESSES 2
int main ()
{
int iCounter = 0;
pid_t pid[NUMBER_OF_PROCESSES];
sem_t *sSem = sem_open (SEM_NAME,O_CREAT | O_EXCL, S_IRWXU | S_IRWXG | S_IRWXO, 1);
int i, iStatus;

for (i = 0; i < NUMBER_OF_PROCESSES; i++)
{
pid[i] = fork ();
if (pid[i] < 0)
{
printf ("Could not create processn");
exit (1);
}
else if (pid[i] == 0)
{
int i;
for (i = 0; i < 1000; i++)
{
sem_init(sSem, 0, 1);
sem_wait (sSem);
iCounter++;
sem_post (sSem);
}
exit (0);
}
}
for (i = 0; i < NUMBER_OF_PROCESSES; i++)
waitpid (pid[i], &iStatus, WUNTRACED);
printf ("Value of iCounter = %dn", iCounter);
sem_close (sSem);
sem_unlink (SEM_NAME);
}

您有两个大问题:

  1. 您没有正确使用命名信号量。sem_init()只用于匿名信号,每个信号量只使用一次,在已经初始化的信号量上多次调用它。这是未定义的行为。

  2. 您的iCounter变量不会在您创建的进程之间共享。

以下对程序的重新设计使用POSIX共享内存进行分配(并进行了一些常规清理(:

#include <errno.h>
#include <fcntl.h>
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#define SEM_NAME "/sync"
#define SHM_NAME "/counter"
#define NUMBER_OF_PROCESSES 2
int main() {
int *iCounter = MAP_FAILED;
pid_t pid[NUMBER_OF_PROCESSES];
int iStatus;
int ret = 0;
int memfd = -1;

sem_t *sSem = sem_open(SEM_NAME, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 1);
if (sSem == SEM_FAILED) {
perror("sem_open");
ret = 1;
goto cleanup;
}
memfd = shm_open(SHM_NAME, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
if (memfd < 0) {
perror("shm_open");
ret = 1;    
goto cleanup;
}
if (ftruncate(memfd, sizeof *iCounter) < 0) {
perror("ftruncate");
ret = 1;
goto cleanup;
}
iCounter = mmap(NULL, sizeof *iCounter, PROT_READ | PROT_WRITE, MAP_SHARED,
memfd, 0);
if (iCounter == MAP_FAILED) {
perror("mmap");
ret = 1;
goto cleanup;
}
close(memfd);
*iCounter = 0;
for (int i = 0; i < NUMBER_OF_PROCESSES; i++) {
pid[i] = fork();
if (pid[i] < 0) {
fprintf(stderr, "Could not create process: %sn", strerror(errno));
ret = 1;
goto cleanup;
} else if (pid[i] == 0) {
for (i = 0; i < 1000; i++) {
sem_wait(sSem);
(*iCounter)++;
sem_post(sSem);
}
sem_close(sSem);
return 0;
}
}
for (int i = 0; i < NUMBER_OF_PROCESSES; i++)
waitpid(pid[i], &iStatus, WUNTRACED);
printf("Value of iCounter = %dn", *iCounter);
cleanup:
if (sSem != SEM_FAILED) {
sem_close(sSem);
sem_unlink(SEM_NAME);
}
if (memfd >= 0)
shm_unlink(SHM_NAME);
return ret;
}

示例:

$ gcc -g -O -Wall -Wextra example.c -lrt -lpthread
$ ./a.out
Value of iCounter = 2000

最新更新