多进程和输出

Posted

技术标签:

【中文标题】多进程和输出【英文标题】:The multi-process and output 【发布时间】:2020-07-30 12:51:51 【问题描述】:

我正在做关于多处理的作业。

在这个作业中,我们被要求使用 fork() 函数从一个父进程中分叉不同的进程。然后我们对不同的子进程进行相同的模拟。问题与体育比赛有关。该程序应该能够模拟不同团队的分组功能。

现在我专注于测试模式的第一部分,我遇到了一些问题。

我得到了类似的输出

Parent, pid 57361 : 2 children T Mode 
Child 1 , pid 57362 : teams for pot 0 are : Liverpool Arsenal Barcelona ManCity Juventus Bayern Paris Zenit 
Child 1 , pid 57362 : teams for pot 1 are : RealMadrid Atletico Chelsea Dortmund Napoli Shakhtar Tottenham Ajax 
Child 1 , pid 57362 : teams for pot 2 are : Benfica Lyon Leverkusen Salzburg Olympiacos Brugge Valencia Internazionale 
Child 1 , pid 57362 : teams for pot 3 are : Zagreb Lokomotiv Genk Galatasaray Leipzig SlaviaPraha Atalanta Lille 
Child 1 , pid 57362 : Teams for group A are RealMadrid Brugge Galatasaray Paris 
Child 1 , pid 57362 : pots for group A are 2 3 4 1 
Child 1 , pid 57362 : country for group A are Spain Belgium Turkey France 
Child 1 , pid 57362 : Teams for group B are Lille Olympiacos Tottenham Bayern 
Child 1 , pid 57362 : pots for group B are 4 3 2 1 
Child 1 , pid 57362 : country for group B are France Greece England Germany 
Child 1 , pid 57362 : Teams for group C are ManCity Valencia Atalanta Shakhtar 
Child 1 , pid 57362 : pots for group C are 1 3 4 2 
Child 2 , pid 57363 : teams for pot 0 are : Liverpool Arsenal Barcelona ManCity Juventus Bayern Paris Zenit 
Child 1 , pid 57362 : country for group C are England Spain Italy Ukraine 
Child 2 , pid 57363 : teams for pot 1 are : RealMadrid Atletico Chelsea Dortmund Napoli Shakhtar Tottenham Ajax 
Child 2 , pid 57363 : teams for pot 2 are : Benfica Lyon Leverkusen Salzburg Olympiacos Brugge Valencia Internazionale 
Child 2 , pid 57363 : teams for pot 3 are : Zagreb Lokomotiv Genk Galatasaray Leipzig SlaviaPraha Atalanta Lille 
Child 1 , pid 57362 : Teams for group D are Juventus Leverkusen Lokomotiv Atletico 
Child 2 , pid 57363 : Teams for group A are RealMadrid Brugge Galatasaray Paris 
Child 1 , pid 57362 : pots for group D are 1 3 4 2 
Child 2 , pid 57363 : pots for group A are 2 3 4 1 
Child 1 , pid 57362 : country for group D are Italy Germany Russia Spain 
Child 2 , pid 57363 : country for group A are Spain Belgium Turkey France 
Child 1 , pid 57362 : Teams for group E are Genk Napoli Liverpool Salzburg 
Child 1 , pid 57362 : pots for group E are 4 2 1 3 
Child 2 , pid 57363 : Teams for group B are Lille Olympiacos Tottenham Bayern 
Child 1 , pid 57362 : country for group E are Belgium Italy England Austria 
Child 1 , pid 57362 : Teams for group F are Barcelona Internazionale SlaviaPraha Dortmund 
Child 2 , pid 57363 : pots for group B are 4 3 2 1 
Child 1 , pid 57362 : pots for group F are 1 3 4 2 
Child 1 , pid 57362 : country for group F are Spain Italy Czech Germany 
Child 2 , pid 57363 : country for group B are France Greece England Germany 
Child 1 , pid 57362 : Teams for group G are Leipzig Lyon Zenit Chelsea 
Child 2 , pid 57363 : Teams for group C are ManCity Valencia Atalanta Shakhtar 
Child 1 , pid 57362 : pots for group G are 4 3 1 2 
Child 2 , pid 57363 : pots for group C are 1 3 4 2 
Child 1 , pid 57362 : country for group G are Germany France Russia England 
Child 2 , pid 57363 : country for group C are England Spain Italy Ukraine 
Child 1 , pid 57362 : Teams for group H are Arsenal Benfica Zagreb Ajax 
Child 2 , pid 57363 : Teams for group D are Juventus Leverkusen Lokomotiv Atletico 
Child 1 , pid 57362 : pots for group H are 1 3 4 2 
Child 2 , pid 57363 : pots for group D are 1 3 4 2 
Child 1 , pid 57362 : country for group H are England Portugal Croatia Netherlands 
Child 2 , pid 57363 : country for group D are Italy Germany Russia Spain 
Child 1, pid 57362 : Valid GroupiChild 2 , pid 57363 : Teams for group E are Genk Napoli Liverpool Salzburg 
ng
Child 2 , pid 57363 : pots for group E are 4 2 1 3 
Child 2 , pid 57363 : country for group E are Belgium Italy England Austria 
Child 2 , pid 57363 : Teams for group F are Barcelona Internazionale SlaviaPraha Dortmund 
Child 2 , pid 57363 : pots for group F are 1 3 4 2 
Child 2 , pid 57363 : country for group F are Spain Italy Czech Germany 
Child 2 , pid 57363 : Teams for group G are Leipzig Lyon Zenit Chelsea 
Child 2 , pid 57363 : pots for group G are 4 3 1 2 
Child 2 , pid 57363 : country for group G are Germany France Russia England 
Child 2 , pid 57363 : Teams for group H are Arsenal Benfica Zagreb Ajax 
Child 2 , pid 57363 : pots for group H are 1 3 4 2 
Child 2 , pid 57363 : country for group H are England Portugal Croatia Netherlands 
Child 2, pid 57363 : Valid Grouping

在这个程序中,我 fork 两个进程,输出有一个 Child 1 中断的问题,然后 Child2 打印它的消息。因此,“ing”被Child2的一个输出隔开。

样本输出应该是这样的


Parent, pid 12352: 2 children, test mode
Child 1, pid 12353: teams for pot 1 are Liverpool Arsenal Barcelona ManCity Juventus Bayern Paris
Zenit
Child 1, pid 12353: teams for pot 2 are RealMadrid Atletico Chelsea Dortmund Napoli Shakhtar
Tottenham Ajax
Child 1, pid 12353: teams for pot 3 are Benfica Lyon Leverkusen Salzburg Olympiacos Brugge
Valencia Internazionale
Child 2, pid 12355: teams for pot 1 are Liverpool Arsenal Barcelona ManCity Juventus Bayern Paris
Zenit
Child 2, pid 12355: teams for pot 2 are RealMadrid Atletico Chelsea Dortmund Napoli Shakhtar
Tottenham Ajax
Child 2, pid 12355: teams for pot 3 are Benfica Lyon Leverkusen Salzburg Olympiacos Brugge
Valencia Internazionale
Child 2, pid 12355: teams for pot 4 are Zagreb Lokomotiv Genk Galatasaray Leipzig SlaviaPraha
Atalanta Lille
Child 2, pid 12355: teams for group A are RealMadrid Brugge Galatasaray Paris
Child 1, pid 12353: teams for pot 4 are Zagreb Lokomotiv Genk Galatasaray Leipzig SlaviaPraha
Atalanta Lille
Child 1, pid 12353: teams for group A are RealMadrid Brugge Galatasaray Paris
Child 1, pid 12353: pots for group A are 2 3 4 1
Child 1, pid 12353: countries for group A are Spain Belgium Turkey France
Child 1, pid 12353: teams for group B are Lille Olympiacos Tottenham Bayern
Child 1, pid 12353: pots for group B are 4 3 2 1
Child 1, pid 12353: countries for group B are France Greece England Germany
. . .
Child 2, pid 12355: countries for group F are Spain Italy Czech Germany
Child 2, pid 12355: teams for group G are Leipzig Lyon Zenit Chelsea
Child 2, pid 12355: pots for group G are 4 3 1 2
Child 1, pid 12353: pots for group H are 1 3 4 2
Child 1, pid 12353: countries for group H are Austria Portugal Croatia Netherlands
Child 1, pid 12353: Valid grouping
Child 2, pid 12355: countries for group G are Germany France Russia England
Child 2, pid 12355: teams for group H are Arsenal Benfica Zagreb Ajax
Child 2, pid 12355: pots for group H are 1 3 4 2
Child 2, pid 12355: countries for group H are Austria Portugal Croatia Netherlands
Child 2, pid 12355: Valid grouping


这是我的代码。

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <errno.h>

#define LENGTH sizeof(TEAM)/sizeof(TEAM[0])
#define GROUPNUM sizeof(GROUP)/sizeof(GROUP[0])


char *TEAM[] = "Ajax", "Atalanta", "Atletico", "Barcelona", "Bayern",
                "Benfica", "Brugge", "Chelsea", "Crvenazvezda", "Dortmund", "Galatasaray",
                "Genk", "Internazionale", "Juventus", "Leipzig", "Leverkusen", "Liverpool",
                "Lokomotiv", "Lille", "Lyon", "ManCity", "Napoli", "Olympiacos", "Paris",
                "RealMadrid", "Salzburg", "Shakhtar", "SlaviaPraha", "Tottenham", "Valencia",
                "Zagreb", "Zenit", "Arsenal";


char *COUNTRY[] = "Netherlands", "Italy", "Spain", "Spain", "Germany",
                   "Portugal", "Belgium", "England", "Serbia", "Germany", "Turkey", "Belgium",
                   "Italy", "Italy", "Germany", "Germany", "England", "Russia", "France",
                   "France", "England", "Italy", "Greece", "France", "Spain", "Austria",
                   "Ukraine", "Czech", "England", "Spain", "Croatia", "Russia", "England";

char *GROUP[] ="group A", "group B", "group C", "group D", "group E", "group F", "group G", "group H";



const char* getCountry(char * team)
    int i;
    char* str;
    for(i=0;i<LENGTH;i++)
        str = TEAM[i];
        if ( ( strcmp(team, str) ) == 0)
            break;
        
    

    return COUNTRY[i];



int canTheyMeet(char* str1, char* str2)
    str1 = getCountry(str1);
    str2 = getCountry(str2);
    int flag=1;
    if ( (strcmp(str1, str2)) == 0 )
        flag = 0;
    if ( (strcmp(str1, "Ukraine")) == 0 && (strcmp(str2, "Russia")) == 0 )
        flag = 0;

    if ( (strcmp(str2, "Ukraine")) == 0 && (strcmp(str1, "Russia")) == 0 )
        flag = 0;

    return flag;





// Return Country and It cannot be changed

int whichPot(char * team, char *** result)
    int i,j,flag=0;
    for(i=0;i<4;i++)
        for(j=0;j<8;j++)
            char *str = result[i][j];
            if( (strcmp(team, str)) == 0 )
                flag=1;
                break;
            
        
        if(flag==1)
            break;
    

    return i+1;


int isGroupValid(char ** group, char *** result)
    int i,j;
    int flag = 1;
    for(i=0;i<3;i++)
        for(j=i+1;j<4;j++)
            char *str1 = group[i];
            char *str2 = group[j];
            if(!canTheyMeet(str1, str2) || whichPot(str1, result) == whichPot(str2, result))
                flag=0;
                break;
            
        
    
    return flag;





// only for test mode, we generate the Group for each teams
char *** generateGroup(char** argv, int length)
    int m;
    char *** result;
    result = (char ***)malloc(sizeof(char**)*8);
    for(m=0;m<8;m++)
        result[m] = (char**)malloc(sizeof(char*)*4);
    
    int k,j;
    int i=35;
    for(k=0;k<8;k++)
        for(j=0;j<4;j++)
            char* string = argv[i + j];

            result[k][j] = string;
        
        i+=4;
    

    return result;




// set Teams to different pots
// The pots are three dimensional Array
char *** getTeams(char** argv, int length)
    int m;
    char *** result;
    result = (char ***)malloc(sizeof(char**)*4);
    for (m=0;m<4;m++)
        result[m] = (char**)malloc(sizeof(char*)*8);
    


    int i=3;
    int j=0;
    int k=0;
     //Iterative get all the information of setmode
    for(; k<4; k++) 
        // four pots

            for (; j < 8; j ++) 
                // get string
                char *string = argv[i + j];
                result[k][j] = string;
            
            i+=8;
            j=0;
    
    return result;




void TestMode(char ** argv, int length, int id)
    char *** teamPot = getTeams(argv, length);
    char *** groups = generateGroup(argv, length);
    int i,j,validBit=1;
    for(i=0;i<4;i++)
        printf("Child %d , pid %d : teams for pot %d are : ", id, getpid(), i);
        for(j=0;j<8;j++)
            printf("%s ", teamPot[i][j]);
        
        printf("\n");
    

    for(i=0;i<8;i++)
        printf("Child %d , pid %d : Teams for %s are ", id, getpid(), GROUP[i]);
        for(j=0;j<4;j++)
            printf("%s ", groups[i][j]);
        
        printf("\n");

        printf("Child %d , pid %d : pots for %s are ", id, getpid() ,GROUP[i]);
        for(j=0;j<4;j++)
            printf("%d ", whichPot(groups[i][j], teamPot));
        
        printf("\n");

        printf("Child %d , pid %d : country for %s are ", id, getpid() ,GROUP[i]);
        for(j=0;j<4;j++)
            printf("%s ", getCountry(groups[i][j]));
        
        printf("\n");
        char ** group = groups[i];
        if(!isGroupValid(group, teamPot))
            printf("Child %d, pid %d : InValid Grouping\n" , id, getpid());
            validBit=0;
            break;
        
    
    if(validBit)
        printf("Child %d, pid %d : Valid Grouping\n", id, getpid());
    free(teamPot);
    free(groups);





void GenerateMode()




int main(int argc, char **argv) 
    printf("Hello, World! %d\n", GROUPNUM);





    int k=0;
    int status=0;




    // get number of child process
    int numOfChild = 2;
    // The parent Id
    pid_t ppid = getpid();

    printf("Parent, pid %d : %d children %s Mode \n", ppid, numOfChild, argv[2]);
    pid_t pid;

    for(k=0;k<numOfChild;k++)
        if(fork() == 0)
            if ((strcmp(argv[2], "T") == 0))
                TestMode(argv, argc, k+1);
                exit(0);
            else if ((strcmp(argv[2], "G")) == 0)
                GenerateMode();
            

        
    
    for(k=0;k<numOfChild;k++)
        wait(NULL);
    


    return 0;








我需要用 Lock 做一些工作吗? 谢谢!!!

【问题讨论】:

【参考方案1】:

所有forked 进程都在异步写入stdout。没有关于订单的保证。在程序开始时调用setlinebuf(相当于setvbuf(stream, NULL, _IOLBF, 0))并在每个printf 之后调用fflush 应该帮助,但不一定在所有情况下都能解决您的问题。

在调用setvbuf 时指定大于预期最长行的缓冲区大小也会有所帮助:

char buffer[16000]; // 16000 is the buffer size in bytes
...
int main(int argc, char **argv)

    setvbuf(stdout, buffer, _IOLBF, sizeof buffer);
...

【讨论】:

以上是关于多进程和输出的主要内容,如果未能解决你的问题,请参考以下文章

python多进程和多线程---(自学中,坚持更新)

在将输出写入文件时使用多处理显示来自子进程的实时输出

在多线程 C++ 中捕获进程的输出

python多进程报错load_eof

多处理进程不运行

Python 多进程内存占用问题