我可以使用wait(&status)清除具有相同父项的多个子进程并在C中循环吗?

问题描述 投票:0回答:2

我正在编写一个程序,该程序可以从文件中读取linux命令,并使用fork()execvp()并行运行它们,并且运行良好。

 while((current = GetNextCommand(current)) != NULL){
            char currentCommand[WIDTH - 1];
            current->active = true;
            strcpy(currentCommand, current->command);
            int j=0;
            int ctr=0;
            char newString[LENGTH][WIDTH];
            for(int i = 0; i <= strlen(currentCommand); i++){
                // if space or NULL found, assign NULL into newString[ctr]
                if(currentCommand[i]==' '|| currentCommand[i]=='\0')
                {
                    newString[ctr][j]='\0';
                    ctr++;  //for next word
                    j=0;    //for next word, init index to 0
                }
                else
                {
                    newString[ctr][j] = currentCommand[i];
                    j++;
                }
            }
            char *exe[ctr + 1];
            for(int i = 0; i < ctr; i++){
                exe[i] = strdup(newString[i]);
            }
            exe[ctr] = NULL;
            t = clock();
            clock_gettime(CLOCK_MONOTONIC, &start);
            current->starttime = start.tv_sec;
            current->PID = (pid = fork());
            if(pid < 0){
                fprintf(stderr, "fork Failed\n"); //output in stderr if fork fails and return
                exit(1);
            }
            else if(pid == 0){
                execvp(exe[0], exe);
                //fails
                exit(2);
            }
        }

我的文件是

sleep 3
ls -latr
sleep 1
pwd
sleep 1
wc /etc/passwd
sleep 10

在父进程中,如果命令的运行时间大于2秒,我需要获取每个子进程的运行时间并重新运行该命令。如果命令的运行时间大于2,我将继续运行该命令,直到用户使用kill -sig pidpkill sleep终止该进程为止。我使用for循环并设置了相应的wait(&status)数。在我的文件中,sleep 3sleep 10将大于2秒。 sleep 3的进程完成工作后,它将返回到父级,并且sleep 10仍在运行。现在使用pkill sleep会很好,因为sleep 10将继续在父进程中运行。但是,当它们都从子进程中退出并且我使用kill -sig pid时,整个程序都退出了。因此,在这种情况下如何同时运行它们(sleep 3sleep 10)?

for(int i = 0; i < nodeIndex - 1; i++){
    int status;
    int pid = wait(&status);
    clock_gettime(CLOCK_MONOTONIC, &finish);
    CommandNode* cNode;
    cNode = FindCommand(head->nextCommandPtr, pid);
    elapsed = finish.tv_sec - cNode->starttime;
    printf("%ld\n", elapsed);
    if(elapsed < 2){
        cNode->active = false;
    }
    else{
        char rerunCommand[WIDTH - 1];
        strcpy(rerunCommand, cNode->command);
        int j=0;
        int ctr=0;
        char newString[LENGTH][WIDTH];
        for(int i = 0; i <= strlen(rerunCommand); i++){
            // if space or NULL found, assign NULL into newString[ctr]
            if(rerunCommand[i]==' '|| rerunCommand[i]=='\0')
            {
                newString[ctr][j]='\0';
                ctr++;  //for next word
                j=0;    //for next word, init index to 0
            }
            else
            {
                newString[ctr][j] = rerunCommand[i];
                j++;
            }
        }
        char *exe[ctr + 1];
        for(int i = 0; i < ctr; i++){
            exe[i] = strdup(newString[i]);
        }
        exe[ctr] = NULL;
        while(elapsed > 2){
            int pid2;
            t = clock();
            clock_gettime(CLOCK_MONOTONIC, &start);
            cNode->starttime = start.tv_sec;
            cNode->PID = (pid2 = fork());
            if(pid2 < 0){
                fprintf(stderr, "fork Failed"); //output in stderr if fork fails and return
                exit(1);
            }
            else if(pid2 == 0){
                printf("What happened here.\n");
                execvp(exe[0], exe);
                exit(2);
            }
            else{
                wait(&status);
                clock_gettime(CLOCK_MONOTONIC, &finish);
                elapsed = finish.tv_sec - cNode->starttime;
                if(elapsed > 2) {
                    printf("What is this: %d %d\n", pid2, cNode->PID);
                }
            }
        }
    }
}
c process fork wait system-calls
2个回答
0
投票

关于标题中的问题:

是的,可以循环直到返回值是-1


0
投票

是的,的确,这是确保所有孩子在继续之前都已经完成的正确方法:

pid_t pid;
...
while((pid = wait(NULL)) >= 0)
    printf("child pid=%d ended.\n", pid); /* or whatever you want */

/* no more children active after this point, you don't need 
 * to check the value of errno, except if you allow this
 * process to be interrupted by a signal. */
© www.soinside.com 2019 - 2024. All rights reserved.