简体   繁体   中英

fork()- multiple files accessed by parent & child processes

For educational purposes, I wrote a program that forks a process and ...

  1. the child continuously reads 3 files, prints the contents, sleeps for 10ms.
  2. the parent keeps a counter for each file. each file also has a delay time associated with it. each time a file's timer expires, the counter is incremented and the file is overwritten with the
    new counter value. Each delay value is different, so all 3 files get updated at different rates.

The problem is, the counters only increment for a short time, and everything freezes after a few seconds. Can anyone give a good explanation of what is happening here?

#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();
                }
            }
        }
    }
}

I am not sure this is your only problem, but your get_usecs function is suspect. You probably meant this

return tv.tv_sec * 1000000 + tv.tv_usec;

Rather than

return tv.tv_sec + tv.tv_usec;

Although, note that time_t is only guaranteed to be large enough for the time in seconds, not the number of microseconds as you have used it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM