Как использовать fflush (), когда несколько процессов печатают на одном и том же стандартном выводе - PullRequest
1 голос
/ 14 октября 2019

Я создаю несколько дочерних процессов, и все они печатают в один и тот же файл STDOUT, даже если им приходится ждать мьютекса для печати и даже fflush (stdout), печать все равно перекрывает друг друга.

Я добавил мьютексы для окружения каждого printf, я даже добавил fflush после каждого оператора печати. Я пытался добавить только один fflush и пробовал это различными способами, помещая fflush в разные части кода.

#include <sys/ipc.h>
#include <sys/stat.h>
#include <sys/shm.h>
#include <semaphore.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <errno.h>
#include <time.h>
#include <sys/wait.h>

#include "wrappers.c"
#include "shmSegment.h"
#include "message.h"

/*  
    argv[1] = id, 
    argv[2] = capacity
    argv[3] = duration (ms)
*/
int main(int argc, char *argv[])
{
    int myID = atoi(argv[0]);
    int capacity = atoi(argv[1]);
    int duration = atoi(argv[2]);

    //#iterations=#partsMadeByMe=0;
    int numIterations;
    int numPartsMadeByMe;
    numIterations = numPartsMadeByMe = 0;


    //get shared memory
    int        shmid ;
    key_t      shmkey;
    int        shmflg;
    shmData    *p;

    shmkey = ftok("shmSegment.h" , 1 ) ;
    shmflg = IPC_CREAT | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
    shmid  = shmget( shmkey , SHMEM_SIZE , shmflg ) ;
    p  = (shmData *) Shmat( shmid , NULL , 0 );
    //get message queue
    msgBuf  msgSnd;
    int     queID ;
    int     msgStatus ;
    queID   = Msgget( BASE_MAILBOX_NAME , 0600) ;

    //get mutex
    int semflg, semmode ;
    semflg = O_CREAT;
    semmode = S_IRUSR | S_IWUSR;
    sem_t *mutex;
    mutex = Sem_open2("/mutex", semflg);

    Sem_wait(mutex);
    printf("%d STARTED.\n", myID);
    fflush(stdout);
    Sem_post(mutex);

    int job = 0;
    Sem_wait(&(p->memMutex));
    //while parts still remain
    while(p->numPartsNeeded > 0)
    {
        //determine how many to make and update remain
        if (p->numPartsNeeded >= capacity)
        {
           job = capacity;
        } else 
        {
          job = p->numPartsNeeded;
        }
        p->numPartsNeeded -= job;
        p->numPartsBuilt += job;

        Sem_post(&(p->memMutex));

        //mutex
        Sem_wait(mutex);

        //print “%d: Going to make %d in %d milliSecs” , myID, data ...
        printf("%d: Going to make %d in %d milliSecs\n", myID, job, duration);
        fflush(stdout);

        Sem_post(mutex);

        //sleep(myDuration)
        usleep(1000 * duration);

        //create and send production message
        msgSnd.msgType = TYPE_PRODUCTION;
        msgSnd.body.lineID = myID;
        msgSnd.body.numParts = job;
        msgSnd.body.time = duration;
        msgStatus =  msgsnd( queID , &msgSnd , MSG_INFO_SIZE , 0 );

        //increment #iterations
        numIterations++;

        //update total number of parts made by me
        numPartsMadeByMe += job;

        Sem_wait(&(p->memMutex));
    }

    Sem_post(&(p->memMutex));

    //create and send completion message    
    msgSnd.msgType = TYPE_TERMINATION;
    msgSnd.body.lineID = myID;
    msgSnd.body.numParts = numPartsMadeByMe;
    msgSnd.body.time = numIterations;
    msgStatus =  msgsnd( queID , &msgSnd , MSG_INFO_SIZE , 0 );
    if ( msgStatus < 0 ) 
    {
        printf("Failed to send on queuID %d. Error code=%d\n" 
               , queID , errno ) ;
        perror("Reason");
        exit(-2) ;  
    }

    Sem_wait(mutex);
    printf(">>>> %4d: Terminating after making total of %5d in %4d iterations\n",
        myID, numPartsMadeByMe, numIterations);
    fflush(stdout);
    Sem_post(mutex);

    shmdt( p ) ;
    shmctl( shmid , IPC_RMID , NULL );
    sem_close(mutex); sem_unlink("/mutex");
    exit(1);
}

Если у меня одновременно запущены два процесса, я ожидаю вывод, подобный

1 STARTED
2 STARTED
1: Going to make 15 parts in 734 milliSecs
2: Going to make 10 parts in 528 milliSecs
2: Going to make 10 parts in 528 milliSecs
1: Going to make 15 parts in 734 milliSecs
[...]
>>>> 1: Terminating after making total of 90 parts in 6 iterations
>>>> 2: Terminating after making total of 60 parts in 6 iterations

порядок вывода не имеет значения, но когда я запускаю его с fflush после каждой печати, выходной файл выглядит примерно так:

2 STARTED.
2: Going to make 43 in 763 milliSecs12: Going to make 43 in 763 milliSec1:2: Going to make 43 in 763 milliSe1: 2: Going$>>>>    2: Terminating after making total of   135 in    4 iterations
otal of    15 in    5 iterations

только с одним fflush дает тоже не работает. Типичные выходы только с одним fflush:

1 STARTED.
1: Going to make 18 in 547 milliSecs
2: Going to make 2 in 1176 milliSecs
2: Going to make 2 in 1176 milliSecs
2: Going to make 2 in 1176 milliSecs
>>>>    2: Terminating after making total of     8 in    4 iterations
ecs
1: Going to make 18 in 547 milliSecs
1: Going to make 16 in 547 milliSecs
>>>>    1: Terminating after making total of   142 in    8 iterations
2 STARTED.
2: Going to make 48 in 945 milliSecs
2: Going to make 22 in 945 milliSecs
>>>>    2: Terminating after making total of    70 in    2 iterations
...