【发布时间】:2016-06-02 11:00:24
【问题描述】:
我想创建一个具有共享内存和信号量的 C 程序。应该有两个子进程。两个孩子都有不同的 int 号。然后有一个应该写入共享内存的目标编号。现在两个孩子都应该从目标数字中减去他们的数字,直到目标数字小于或等于 0。我不希望出现竞争条件。这就是为什么我尝试使用信号量。但这对我不起作用。这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <errno.h>
#include <sys/sem.h>
#define SEG_SIZE sizeof(int)
#define NUM_OF_CHILDS 2
int main(int argc, char *argv[]){
int i, shm_id, sem_id, *shar_mem;
int pid[NUM_OF_CHILDS];
long waittime = 100;
unsigned short marker[1];
/* Define the numbers and the goal number */
int numbers[2] = {28, 23};
int goal = (numbers[0] + numbers[1]) * 4;
/* Create semaphor */
if((sem_id = semget(IPC_PRIVATE, 1, IPC_CREAT|0644)) == -1){
perror("semget()");
exit(EXIT_FAILURE);
}
marker[0] = 1;
/* All sem's to 1 */
semctl(sem_id, 1, SETALL, marker);
/* Create shared memory */
if((shm_id = shmget(IPC_PRIVATE, SEG_SIZE, IPC_CREAT|0600)) == -1){
perror("shmget()");
exit(EXIT_FAILURE);
}
if((shar_mem = (int *)shmat(shm_id, 0, 0)) == (int *) -1){
perror("shmat()");
exit(EXIT_FAILURE);
}
*shar_mem = goal;
/* Create child processes */
for(i = 0; i < NUM_OF_CHILDS; i++){
pid[i] = fork();
if(pid[i] < 0){
printf("Error!\n");
exit(1);
}
if(pid[i] == 0){
int count = 0;
/* Child processes */
/* Structs for semaphor */
struct sembuf enter, leave;
enter.sem_num = leave.sem_num = 0;
enter.sem_flg = leave.sem_flg = SEM_UNDO;
enter.sem_op = -1; /* DOWN-Operation */
leave.sem_op = 1; /* UP-Operation */
/* Join critical area */
semop(sem_id, &enter, 1);
while(*shar_mem > 0){
usleep(waittime);
*shar_mem -= numbers[i];
count++;
}
printf("%i\n", count);
/* Leave critical area */
semop(sem_id, &leave, 1);
exit(0);
}
}
/* Wait for childs. */
for(i = 0; i < NUM_OF_CHILDS; i++){
waitpid(pid[i], NULL, 0);
}
/* Is goal equal 0 or lower? */
int returnv;
if(*shar_mem == 0){
/* No race conditions */
returnv = 0;
}
else {
/* Race conditions */
returnv = 1;
}
/* Close shared memory and semaphores */
shmdt(shar_mem);
shmctl(shm_id, IPC_RMID, 0);
semctl(sem_id, 0, IPC_RMID);
return returnv;
}
当共享内存值最后为 0 时,应该没有竞态条件。如果它低于 0,则存在竞争条件。而且我总是低于0。最重要的是,我计算每个孩子减去他的数字的次数。结果:第一个孩子 8 次,第二个孩子 0 次。谁能帮帮我?
【问题讨论】:
-
您的
while(*shar_mem)循环在semop(enter) .. semop(leave)部分内。您可能只希望一个孩子同时处理这个数字,而且只需要一次,所以应该颠倒这个顺序。那时,互斥锁会比信号量更合适。 -
这应该如何工作?第二个子进程永远没有机会减去它的数字,因为第一个子进程在目标小于或等于 0 之前没有离开临界区域。在您的情况下,目标将导致 -24,即 (28+23)* 4 - 8*28。即使调整你的 semop 调用,你也不能保证两个孩子交替减去他们的数字,所以结果代码可能是零,但也可能不是
-
好主意,但我试图将 semop 部分放入循环中。现在第一个孩子有 8 个计数,第二个孩子有 1 个计数。所以变化不大。这是一个学习练习,我必须使用信号量。
-
也许题外话,但您可以尝试sem_init 与非零
pshared来获得进程之间的共享信号量。
标签: c fork semaphore shared-memory race-condition