fork() - 父和子访问的多个文件子进程

时间:2014-08-11 09:19:55

标签: c file process fork spinlock

出于教育目的,我编写了一个程序,用于处理进程和...

  1. 孩子连续读取3个文件,打印内容,睡眠10ms。
  2. 父母为每个文件保留一个计数器。每个文件也有一个与之关联的延迟时间。 每次文件的计时器到期时,计数器都会递增,文件将被替换为
    新的柜台价值。每个延迟值都不同,因此所有3个文件都以不同的速率更新。
  3. 问题是,计数器只会在短时间内增加,几秒钟后一切都会冻结。任何人都可以对这里发生的事情做出很好的解释吗?

    #include <stdio.h>
    #include <stdint.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string.h> 
    #include <sys/time.h>
    
    #define CHAN1WAIT 100000
    #define CHAN2WAIT 750000
    #define CHAN3WAIT 1000000
    #define NCHAN 3
    
    FILE *chanfiles[NCHAN] = {NULL, NULL, NULL};                                      //file pointers for fake 'devices'
    char *filenames[NCHAN] = {"_chan1tmpfile_", "_chan2tmpfile_", "_chan3tmpfile_"}; 
    int chanwait[NCHAN] = {CHAN1WAIT, CHAN2WAIT, CHAN3WAIT};                          //time it takes for each 'device' to be updated with a new value
    int chancount[NCHAN] = {0, 0, 0};  //value for each device    
    int clrcount = NCHAN * 8;
    
    uint8_t chan1;
    
    int read_chan (int chan)
    {
        char buf[4];
        char c;
        int i, ret;
        short count = 0;
        uint8_t set = 0;
        char * retstr;
    
        while (! set)
        {
            if (chanfiles[chan] == NULL) //if file is not in use
            {
                if ((chanfiles[chan] = fopen(filenames[chan], "r")) == NULL)
                {
                    printf("Error opening file %s for reading.\n%s\n", filenames[chan], strerror(errno));
                    exit(-1);
                }
    
                while ((c = fgetc(chanfiles[chan])) != EOF)
                {
                    buf[count] = c;
                    count++;
                }
                fclose(chanfiles[chan]);
                chanfiles[chan] = NULL;
                retstr = malloc(count + 1);
                for (i = 0; i < count; i++) retstr[i] = buf[i];
                ret = atoi(retstr);
                free(retstr);
                set = 1;
            }
        }
        return ret;
    }
    
    void write_chan (int chan)
    {
        uint8_t set = 0;
        while (! set)
        {
            if (chanfiles[chan] == NULL) //if file is not in use
            {
                if ((chanfiles[chan] = fopen(filenames[chan], "w")) == 0)
                {
                    printf("Error opening file %s for writing.\n%s\n", filenames[chan], strerror(errno));
                    exit(-1);
                }
    
                if (fprintf(chanfiles[chan], "%d", chancount[chan]) < 0)
                {
                    printf("Error writing to file %s:\n%s\n", filenames[chan], strerror(errno));
                    exit(-1);
                }
    
                fclose(chanfiles[chan]);
                chanfiles[chan] = NULL;
                set = 1;
            }
        }
    }
    
    time_t get_usecs()
    {
        struct timeval tv;
        gettimeofday(&tv, NULL);
            return tv.tv_sec + tv.tv_usec;
    }
    
    int main (int argc, char * argv[])
    {
        pid_t pid;
        time_t curtime;
        int i;
    
        for (i = 0; i < NCHAN; i++) write_chan(i);
    
        printf("\nChannel:");
        for (i = 0; i < NCHAN; i++) printf("%8d", i);
        printf("\n  Value:");
    
        pid = fork();
    
    // This process reads all 3 files, prints the values,
    // then sleeps for 10ms, in an infinite loop.
        if (pid == 0)
        {
            int j;
            while (1)
            {
                uint8_t set;
                for (j = 0; j < NCHAN; j++)
                {
                    int value;
                    set = 0;
                    value = read_chan(j);
                    printf("%8d", value);
                }
                fflush(stdout);
                usleep(10000);
                for (j = 0; j < clrcount; j++) printf("\b"); fflush(stdout);
            }
        }
    
    // This process updates the values of all 3 files at 
    // different rates, based on the value in chanwait[]
    // for each file.
        else
        {
            time_t timers[NCHAN];
            int i;
            for (i = 0; i < NCHAN; i++) timers[i] = get_usecs();
    
            while (1)
            {
                for (i = 0; i < NCHAN; i++)
                {
                    if ((get_usecs() - timers[i]) >= chanwait[i])
                    {
                        chancount[i]++;
                        write_chan(i);
                        timers[i] = get_usecs();
                    }
                }
            }
        }
    }
    

1 个答案:

答案 0 :(得分:0)

我不确定这是您唯一的问题,但您的get_usecs功能是可疑的。你可能意味着这个

return tv.tv_sec * 1000000 + tv.tv_usec;

而不是

return tv.tv_sec + tv.tv_usec;

虽然,请注意,time_t仅保证足够大,以秒为单位,而不是使用它时的微秒数。