Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我是否可以在C中使用wait(&;status)和loop清理具有相同父进程的多个子进程?_C_Process_Fork_Wait_System Calls - Fatal编程技术网

我是否可以在C中使用wait(&;status)和loop清理具有相同父进程的多个子进程?

我是否可以在C中使用wait(&;status)和loop清理具有相同父进程的多个子进程?,c,process,fork,wait,system-calls,C,Process,Fork,Wait,System Calls,我正在编写一个程序,可以从文件中读取linux命令,并使用fork()和execvp()并行运行这些命令,并且运行良好 while((current = GetNextCommand(current)) != NULL){ char currentCommand[WIDTH - 1]; current->active = true; strcpy(currentCommand, current->command

我正在编写一个程序,可以从文件中读取
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);
            }
        }
在父进程中,我需要获取每个子进程的运行时间,如果命令的运行时间大于2秒,则重新运行该命令。如果命令的运行时间大于2,我将继续运行它,直到用户使用
kill-sig pid
pkill sleep
终止进程。我使用for循环并设置相应的等待次数(&status)。在我的文件中,
sleep 3
sleep 10
将大于2秒。当
sleep 3
进程完成其工作后,它将返回到父进程,并且
sleep 10
仍在运行。当我现在使用
pkillsleep
时,它会很好,因为
sleep 10
将继续在父进程中运行。但是,当它们都从子进程退出并且我使用
kill-sigpid
时,整个程序退出。因此,在这种情况下,我如何同时运行它们(
sleep3
sleep10

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);
                }
            }
        }
    }
}
for(int i=0;inextCommandPtr,pid);
运行时间=finish.tv_sec-cNode->starttime;
printf(“%ld\n”,已过);
如果(经过时间<2){
cNode->active=false;
}
否则{
字符重新取消命令[WIDTH-1];
strcpy(重新取消命令,cNode->command);
int j=0;
int ctr=0;
char newString[长度][宽度];
对于(int i=0;i 2){
int-pid2;
t=时钟();
时钟获取时间(时钟单调和开始);
cNode->starttime=start.tv\u秒;
cNode->PID=(pid2=fork());
if(pid2<0){
fprintf(stderr,“fork Failed”);//如果fork失败,则在stderr中输出并返回
出口(1);
}
else if(pid2==0){
printf(“这里发生了什么事。\n”);
execvp(exe[0],exe);
出口(2);
}
否则{
等待(&状态);
时钟获取时间(时钟单调,完成);
运行时间=finish.tv_sec-cNode->starttime;
如果(经过时间>2){
printf(“这是什么:%d%d\n”,pid2,cNode->PID);
}
}
}
}
}

关于标题中的问题:


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

是,这确实是一种正确的方法,可以确保您的所有孩子在继续之前都已完成:

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. */
这是僵尸进程的老传统(就像行尸走肉电影的标题):僵尸进程是一个已退出(2)ed且父进程未等待(2)ed的进程。它释放了所有资源,除了进程表条目(存储其退出代码和记帐记录)之外。这样,当父进程执行
wait(2)
系统调用时,内核可以导航其子进程表,并检查是否必须返回错误(如果列表为空),或者是否有某个子进程已结束并可以将其
exit(2)
代码返回父进程。如果您之前已经创建了
fork(2)
,则只能正确使用
wait(2)
wait(2)
,如果您没有创建子进程,则发出错误信号

要获取子系统的运行时间,您需要使用一个备用系统调用来
wait(2)
wait3(2)
wait4(2)
,根据FreeBSD手册页,在linux上有类似的系统调用)

试试这个简单的例子:

#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>

#define N                    7
#define PARENT_SLEEP        30
#define CHILD_MAXSLEEP      60

int main()
{
    int i;
    pid_t mypid = getpid();

    for(i = 0; i < N; i++) {

        pid_t chpid = fork();

        switch (chpid) {

        case -1: /* error */
            fprintf(stderr,
                "Parent [pid=%d]: fork: %s\n",
                mypid,
                strerror(errno));
            goto out; /* we want to break the loop */

        case 0: /* child */
            /* reinit mypid to reflect proper value */
            mypid = getpid();

            printf("Child [pid=%d]: start\n", mypid);

            /* we initialize random module after fork, so
             * all children don't get the same random
             * sequence. Probably all of them will take
             * the same value for the time, so we use also
             * the pid for the seed to be different for
             * each child. */
            srandom( mypid ^ time(NULL) );

            /* a random time between 1 and CHILD_MAXSLEEP */
            int myrandom = random() % CHILD_MAXSLEEP + 1;
            printf("Child [pid=%d]: wait for %d secs.\n",
                    mypid, myrandom);
            sleep( myrandom );

            printf("Child [pid=%d]: exiting with code=%d\n",
                mypid, myrandom);
            exit( myrandom );

        default: /* parent */
            printf("Parent[pid=%d]: I have started"
                    " child (pid = %d)\n", mypid, chpid);
            break;
        } /* switch */
    } /* for */

out:
    /* if you put a delay here, before doing wait()s,
     * and you execute a ps(1) command before the parent
     * begins to make waits, and some of the children have
     * already died, you'll see the zombie processes
     * (they are marked with a Z in status) */
    printf("Parent [pid=%d]: sleeping for %ds.\n",
            mypid, PARENT_SLEEP);
    sleep(PARENT_SLEEP);
    printf("Parent [pid=%d]: beginning to wait.\n",
            mypid);

    int status;
    pid_t child;

    while ((child = wait(&status)) >= 0) {
        printf("Parent[pid=%d]: "
                "detected exit(%d) from "
                "child(pid=%d)\n",
                mypid,
                WEXITSTATUS(status),
                child);
    }

    printf("Parent[pid=%d]: exiting\n", mypid);

    exit(0);

} /* main */
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义n7
#定义父母睡眠30
#定义CHILD_maxleep 60
int main()
{
int i;
pid_t mypid=getpid();
对于(i=0;i#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>

#define N                    7
#define PARENT_SLEEP        30
#define CHILD_MAXSLEEP      60

int main()
{
    int i;
    pid_t mypid = getpid();

    for(i = 0; i < N; i++) {

        pid_t chpid = fork();

        switch (chpid) {

        case -1: /* error */
            fprintf(stderr,
                "Parent [pid=%d]: fork: %s\n",
                mypid,
                strerror(errno));
            goto out; /* we want to break the loop */

        case 0: /* child */
            /* reinit mypid to reflect proper value */
            mypid = getpid();

            printf("Child [pid=%d]: start\n", mypid);

            /* we initialize random module after fork, so
             * all children don't get the same random
             * sequence. Probably all of them will take
             * the same value for the time, so we use also
             * the pid for the seed to be different for
             * each child. */
            srandom( mypid ^ time(NULL) );

            /* a random time between 1 and CHILD_MAXSLEEP */
            int myrandom = random() % CHILD_MAXSLEEP + 1;
            printf("Child [pid=%d]: wait for %d secs.\n",
                    mypid, myrandom);
            sleep( myrandom );

            printf("Child [pid=%d]: exiting with code=%d\n",
                mypid, myrandom);
            exit( myrandom );

        default: /* parent */
            printf("Parent[pid=%d]: I have started"
                    " child (pid = %d)\n", mypid, chpid);
            break;
        } /* switch */
    } /* for */

out:
    /* if you put a delay here, before doing wait()s,
     * and you execute a ps(1) command before the parent
     * begins to make waits, and some of the children have
     * already died, you'll see the zombie processes
     * (they are marked with a Z in status) */
    printf("Parent [pid=%d]: sleeping for %ds.\n",
            mypid, PARENT_SLEEP);
    sleep(PARENT_SLEEP);
    printf("Parent [pid=%d]: beginning to wait.\n",
            mypid);

    int status;
    pid_t child;

    while ((child = wait(&status)) >= 0) {
        printf("Parent[pid=%d]: "
                "detected exit(%d) from "
                "child(pid=%d)\n",
                mypid,
                WEXITSTATUS(status),
                child);
    }

    printf("Parent[pid=%d]: exiting\n", mypid);

    exit(0);

} /* main */
$ a.out
Parent[pid=81452]: I have started child (pid = 81453)
Parent[pid=81452]: I have started child (pid = 81454)
Parent[pid=81452]: I have started child (pid = 81455)
Parent[pid=81452]: I have started child (pid = 81456)
Child [pid=81453]: start
Child [pid=81453]: wait for 34 secs.
Child [pid=81455]: start
Child [pid=81455]: wait for 56 secs.
Child [pid=81456]: start
Child [pid=81456]: wait for 42 secs.
Parent[pid=81452]: I have started child (pid = 81457)
Parent[pid=81452]: I have started child (pid = 81458)
Parent[pid=81452]: I have started child (pid = 81459)
Parent [pid=81452]: sleeping for 30s.
Child [pid=81454]: start
Child [pid=81454]: wait for 9 secs.
Child [pid=81457]: start
Child [pid=81457]: wait for 58 secs.
Child [pid=81458]: start
Child [pid=81458]: wait for 30 secs.
Child [pid=81459]: start
Child [pid=81459]: wait for 14 secs.
Child [pid=81454]: exiting with code=9
Child [pid=81459]: exiting with code=14
Child [pid=81458]: exiting with code=30
Parent [pid=81452]: beginning to wait.   <<<<< before this message, you can see Zombie processes.
Parent[pid=81452]: detected exit(14) from child(pid=81459)
Parent[pid=81452]: detected exit(30) from child(pid=81458)
Parent[pid=81452]: detected exit(9) from child(pid=81454)
Child [pid=81453]: exiting with code=34
Parent[pid=81452]: detected exit(34) from child(pid=81453)
Child [pid=81456]: exiting with code=42
Parent[pid=81452]: detected exit(42) from child(pid=81456)
Child [pid=81455]: exiting with code=56
Parent[pid=81452]: detected exit(56) from child(pid=81455)
Child [pid=81457]: exiting with code=58
Parent[pid=81452]: detected exit(58) from child(pid=81457)
Parent[pid=81452]: exiting
$ _