使用 POSIX 信号量函数在 parent 和 child 进程之间交替的问题
Issue with alternating between parent and child process using POSIX semaphore functions
我正在尝试创建一个 C 程序,其中通过使用 POSIX 信号量函数在 parent 和 child 之间交替递增计数器。到目前为止,考虑到这是我第一次使用信号量函数,我在使用它时遇到了麻烦。如果我的程序有任何问题,一些指针会很好。
到目前为止,child 似乎根本没有增加,我不确定为什么会这样。该程序在开始时也表现得很奇怪,在交替到 parent 之前停留在 child。
目前该计划的结果:
GOT EM - parent: expected 0, got 0
GOT EM - child: expected 1, got 1
child: expected 3, got 1
child: expected 5, got 1
child: expected 7, got 1
child: expected 9, got 1
child: expected 11, got 1
child: expected 13, got 1
child: expected 15, got 1
child: expected 17, got 1
child: expected 19, got 1
child: expected 21, got 1
child: expected 23, got 1
child: expected 25, got 1
child: expected 27, got 2
child: expected 29, got 2
child: expected 31, got 2
child: expected 33, got 2
child: expected 35, got 2
child: expected 37, got 2
GOT EM - parent: expected 2, got 2
child: expected 39, got 2
child: expected 41, got 3
GOT EM - parent: expected 4, got 4
child: expected 43, got 4
GOT EM - parent: expected 6, got 6
child: expected 45, got 6
GOT EM - parent: expected 8, got 8
child: expected 47, got 8
GOT EM - parent: expected 10, got 10
child: expected 49, got 10
我的程序:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.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;
struct shmbuf *shmp;
if ((fd = open("/dev/zero", O_RDWR)) < 0)
perror("open error");
ftruncate(fd, sizeof(struct shmbuf));
if ((shmp = mmap(0, sizeof(struct shmbuf), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED)
perror("mmap error");
close(fd);
sem_init(&shmp->child, 1, 0);
sem_init(&shmp->parent, 1, 1); /* Parent first */
if ((pid = fork()) < 0) {
perror("fork error");
} else if (pid > 0) { /* parent */
for (i = 0; i < NLOOPS; i += 2) {
sem_wait(&shmp->parent);
if ((counter = update((long *)shmp)) != i)
printf(" parent: expected %d, got %d\n", i, counter);
else
printf("GOT EM - parent: expected %d, got %d\n", i, counter);
sem_post(&shmp->child);
}
} else { /* child */
for (i = 1; i < NLOOPS + 1; i += 2) {
sem_wait(&shmp->child);
if ((counter = update((long *)shmp)) != i)
printf(" child: expected %d, got %d\n", i, counter);
else
printf("GOT EM - child: expected %d, got %d\n", i, counter);
sem_post(&shmp->parent);
}
}
exit(0);
}
update((long *)shmp)
这个转换是错误的,没有任何意义,是你问题的根源。您不能只使用属于信号量之一的内存作为您自己的计数器。您需要将自己的计数器字段添加到 struct
并将指针传递给该字段。
以下建议代码:
- 导致编译器发出关于不检查
ftruncate()
. 返回值的警告
- 执行所需的功能,除了不增加
printf()
语句中用于 'got' 值的计数器。我会把它留给你去实施。
- 在出现任何错误后正确处理程序的清理和终止。
- 不使用信号量地址作为 'long' 计数器。
对以下问题实施更正:
关于:
static int update(long *ptr)
{
return((*ptr)++); /* return value before increment */
}
ptr 声明为指向 long,但返回类型为 int。
关于:
if ((pid = fork()) < 0)
perror("fork error");
这是一个 'show stopper' 所以下一条语句应该是:
exit( EXIT_FAILURE );
不继续执行程序,就像对 fork()
的调用成功一样。
关于:
if ((shmp = mmap(0, sizeof(struct shmbuf), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED)
perror("mmap error");
这个错误是 'show stopper' 所以下一条语句应该是:
exit( EXIT_FAILURE );
没有像调用 mmap() 成功一样继续执行程序。
关于:
if ((fd = open("/dev/zero", O_RDWR)) < 0)
perror("open error");
这个错误是'show stopper'所以当这个错误发生时,下一条语句应该是:
exit( EXIT_FAILURE );
没有像调用 open()
成功一样继续执行程序
现在,建议的代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.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( int *ptr)
{
return((*ptr)++); /* return value before increment */
}
int main(void)
{
int fd;
int i;
int counter = 0;
pid_t pid;
struct shmbuf *shmp;
if ((fd = open("/dev/zero", O_RDWR)) < 0)
{
perror("open error");
exit( EXIT_FAILURE );
}
ftruncate(fd, sizeof(struct shmbuf));
if ((shmp = mmap(0, sizeof(struct shmbuf), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED)
{
perror("mmap error");
close(fd);
exit( EXIT_FAILURE );
}
close(fd);
sem_init(&shmp->child, 1, 0);
sem_init(&shmp->parent, 1, 1); /* Parent first */
if ((pid = fork()) < 0)
{
perror("fork error");
munmap( shmp, sizeof( struct shmbuf ) );
exit( EXIT_FAILURE );
}
else if (pid > 0)
{ /* parent */
for (i = 0; i < NLOOPS; i += 2)
{
sem_wait(&shmp->parent);
if ((counter = update( &counter )) != i)
printf(" parent: expected %d, got %d\n", i, counter);
else
printf("GOT EM - parent: expected %d, got %d\n", i, counter);
sem_post(&shmp->child);
}
}
else
{ /* child */
for (i = 1; i < NLOOPS + 1; i += 2)
{
sem_wait(&shmp->child);
if ((counter = update( &counter ) != i))
printf(" child: expected %d, got %d\n", i, counter);
else
printf("GOT EM - child: expected %d, got %d\n", i, counter);
sem_post(&shmp->parent);
}
}
exit(0);
}
我正在尝试创建一个 C 程序,其中通过使用 POSIX 信号量函数在 parent 和 child 之间交替递增计数器。到目前为止,考虑到这是我第一次使用信号量函数,我在使用它时遇到了麻烦。如果我的程序有任何问题,一些指针会很好。
到目前为止,child 似乎根本没有增加,我不确定为什么会这样。该程序在开始时也表现得很奇怪,在交替到 parent 之前停留在 child。
目前该计划的结果:
GOT EM - parent: expected 0, got 0
GOT EM - child: expected 1, got 1
child: expected 3, got 1
child: expected 5, got 1
child: expected 7, got 1
child: expected 9, got 1
child: expected 11, got 1
child: expected 13, got 1
child: expected 15, got 1
child: expected 17, got 1
child: expected 19, got 1
child: expected 21, got 1
child: expected 23, got 1
child: expected 25, got 1
child: expected 27, got 2
child: expected 29, got 2
child: expected 31, got 2
child: expected 33, got 2
child: expected 35, got 2
child: expected 37, got 2
GOT EM - parent: expected 2, got 2
child: expected 39, got 2
child: expected 41, got 3
GOT EM - parent: expected 4, got 4
child: expected 43, got 4
GOT EM - parent: expected 6, got 6
child: expected 45, got 6
GOT EM - parent: expected 8, got 8
child: expected 47, got 8
GOT EM - parent: expected 10, got 10
child: expected 49, got 10
我的程序:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.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;
struct shmbuf *shmp;
if ((fd = open("/dev/zero", O_RDWR)) < 0)
perror("open error");
ftruncate(fd, sizeof(struct shmbuf));
if ((shmp = mmap(0, sizeof(struct shmbuf), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED)
perror("mmap error");
close(fd);
sem_init(&shmp->child, 1, 0);
sem_init(&shmp->parent, 1, 1); /* Parent first */
if ((pid = fork()) < 0) {
perror("fork error");
} else if (pid > 0) { /* parent */
for (i = 0; i < NLOOPS; i += 2) {
sem_wait(&shmp->parent);
if ((counter = update((long *)shmp)) != i)
printf(" parent: expected %d, got %d\n", i, counter);
else
printf("GOT EM - parent: expected %d, got %d\n", i, counter);
sem_post(&shmp->child);
}
} else { /* child */
for (i = 1; i < NLOOPS + 1; i += 2) {
sem_wait(&shmp->child);
if ((counter = update((long *)shmp)) != i)
printf(" child: expected %d, got %d\n", i, counter);
else
printf("GOT EM - child: expected %d, got %d\n", i, counter);
sem_post(&shmp->parent);
}
}
exit(0);
}
update((long *)shmp)
这个转换是错误的,没有任何意义,是你问题的根源。您不能只使用属于信号量之一的内存作为您自己的计数器。您需要将自己的计数器字段添加到 struct
并将指针传递给该字段。
以下建议代码:
- 导致编译器发出关于不检查
ftruncate()
. 返回值的警告
- 执行所需的功能,除了不增加
printf()
语句中用于 'got' 值的计数器。我会把它留给你去实施。 - 在出现任何错误后正确处理程序的清理和终止。
- 不使用信号量地址作为 'long' 计数器。
对以下问题实施更正:
关于:
static int update(long *ptr)
{
return((*ptr)++); /* return value before increment */
}
ptr 声明为指向 long,但返回类型为 int。
关于:
if ((pid = fork()) < 0)
perror("fork error");
这是一个 'show stopper' 所以下一条语句应该是:
exit( EXIT_FAILURE );
不继续执行程序,就像对 fork()
的调用成功一样。
关于:
if ((shmp = mmap(0, sizeof(struct shmbuf), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED)
perror("mmap error");
这个错误是 'show stopper' 所以下一条语句应该是:
exit( EXIT_FAILURE );
没有像调用 mmap() 成功一样继续执行程序。
关于:
if ((fd = open("/dev/zero", O_RDWR)) < 0)
perror("open error");
这个错误是'show stopper'所以当这个错误发生时,下一条语句应该是:
exit( EXIT_FAILURE );
没有像调用 open()
成功一样继续执行程序
现在,建议的代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.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( int *ptr)
{
return((*ptr)++); /* return value before increment */
}
int main(void)
{
int fd;
int i;
int counter = 0;
pid_t pid;
struct shmbuf *shmp;
if ((fd = open("/dev/zero", O_RDWR)) < 0)
{
perror("open error");
exit( EXIT_FAILURE );
}
ftruncate(fd, sizeof(struct shmbuf));
if ((shmp = mmap(0, sizeof(struct shmbuf), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED)
{
perror("mmap error");
close(fd);
exit( EXIT_FAILURE );
}
close(fd);
sem_init(&shmp->child, 1, 0);
sem_init(&shmp->parent, 1, 1); /* Parent first */
if ((pid = fork()) < 0)
{
perror("fork error");
munmap( shmp, sizeof( struct shmbuf ) );
exit( EXIT_FAILURE );
}
else if (pid > 0)
{ /* parent */
for (i = 0; i < NLOOPS; i += 2)
{
sem_wait(&shmp->parent);
if ((counter = update( &counter )) != i)
printf(" parent: expected %d, got %d\n", i, counter);
else
printf("GOT EM - parent: expected %d, got %d\n", i, counter);
sem_post(&shmp->child);
}
}
else
{ /* child */
for (i = 1; i < NLOOPS + 1; i += 2)
{
sem_wait(&shmp->child);
if ((counter = update( &counter ) != i))
printf(" child: expected %d, got %d\n", i, counter);
else
printf("GOT EM - child: expected %d, got %d\n", i, counter);
sem_post(&shmp->parent);
}
}
exit(0);
}