使用C

时间:2017-10-26 23:03:25

标签: c fork semaphore shared-memory race-condition

我正在开发一个程序,它将变量Bank存储在共享内存中并导致竞争条件。我的代码编译但它只打印初始余额报表而不是结果余额。基本上,程序应该打印除了竞争条件200以外的余额,当使用信号量修复条件时,它应该使用不同的数字来始终打印200的余额。我错过了什么可能导致我的程序被捕获在第一次打印之后?

    #include <unistd.h> 
    #include <stdio.h> 
    #include <stdlib.h>  
    #include <sys/mman.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <sys/shm.h>
    #include <sys/ipc.h>
    #include <semaphore.h>
    #include <string.h>

    //sem_t mutex; // semaphore global variable

    struct {
        int balance[2];
    }

    Bank = {{100, 100}};

    //struct Bank *bank;

    // routine for thread execution
    void* MakeTransactions() { 
        key_t shmkey;
        int shmid, seqid;
        int seqnum = 5858;
        int i, j, tmp1, tmp2, rint;
        int *shmint1, *shmint2;
        double dummy;

        if ((shmkey=ftok(getenv("HOME"), seqnum))==(key_t)-1) {
            perror("ERROR: ftok"); 
            }
        else if ((shmid=shmget(shmkey,sizeof(int)*2,0600|IPC_CREAT))==-1) {
            perror("ERROR: shmget");
            }
        if ((shmint1=(int *)shmat(shmid,NULL,0600))==(int*)-1) {
            perror("ERROR: shmalloc");
            }
        shmint2 = shmint1 + 1;

        // wait on semaphore
        //sem_wait(&mutex);

        for (i=0; i < 100; i++) {  
            rint = (rand()%30)-15; 
            if (((tmp1= *shmint1)+rint) >=0 &&
                    ((tmp2= *shmint2)-rint)>=0) { 
                //sem_wait(&mutex);
                //bank->balance[0] = tmp1 + rint;
                *shmint1 = tmp1 + rint;
                //sem_post(&mutex); 

                usleep(5000);

                for (j=0; j < rint*100; j++) {
                    dummy=2.345*8.765/1.234; // spend time on purpose
                }
                //sem_wait(&mutex);
                //bank->balance[1] = tmp2 - rint;
                *shmint2 = tmp2 - rint;
                //sem_post(&mutex); 
            }  
        } 
        Bank.balance[0]= *shmint1;
        Bank.balance[1]= *shmint2;

        // increment value of semaphore
        //sem_post(&mutex);
        return NULL;
    } 
    vint main(int argc, char **argv) { 

        key_t shmkey;
        int shmid, seqid, seqnum;
        int *shmint1, *shmint2;
        int i;

        // initialize semaphore
        //sem_init(&mutex, 0, 1);

        // shared memory
        //bank = mmap(NULL, sizeof(struct Bank), PROT_READ | PROT_WRITE,                         MAP_SHARED | MAP_ANONYMOUS, -1, 0);
        if ((shmkey=ftok(getenv("HOME"), seqnum))==(key_t)-1) {
            perror("ERROR: ftok"); 
            }
        else if ((shmid=shmget(shmkey,sizeof(int)*2,0600|IPC_CREAT))==-1) {
            perror("ERROR: shmget");
            }
        if ((shmint1=(int *)shmat(shmid,NULL,0600))==(int*)-1) {
            perror("ERROR: shmalloc");
            }

        shmint2 = shmint1 + 1;

        memset((int*)shmint1,0,sizeof(int));
        memset((int*)shmint2,0,sizeof(int));

        /*//check if bank is not NULL
        Bank.balance[0] = 100;
        Bank.balance[1] = 100;
        */

        *shmint1 = Bank.balance[0];
        *shmint2 = Bank.balance[1];

        pid_t pid;
        srand(getpid()); 

        printf("\nInit balances A:%d + B:%d ==> %d!\n",*shmint1,*shmint2,*shmint1 + *shmint2); 

        pid=fork();
        if (pid < 0) {
            fprintf(stderr, "Fork failed");
            return 1;
        }
        if (pid == 0) {
            MakeTransactions();
            return 0;
        }
        else {
            MakeTransactions();
            wait(NULL);
            return 0;
        }
        printf("Let's check the balances A:%d + B:%d ==> %d ?= 200\n\n",*shmint1,*shmint2,*shmint1 + *shmint2);

        //sem_destroy(&mutex);

        // deattach shared memory pointer
        shmdt(shmint1);
        shmctl(shmid, IPC_RMID, NULL); 

        // memory unmap struct
        //munmap(bank, sizeof(struct Bank));

        return 0; 
    }

1 个答案:

答案 0 :(得分:1)

您正在使用的wait()方法,因为它是described here,在解析NULL时可能会导致未定义的行为;它使用整数指针作为进程完成的指示符。