在下一个前台进程上终止后台进程

时间:2018-10-07 01:43:29

标签: c fork background-process

我在遍历外壳程序和终止后台进程时遇到麻烦。在看了几个小时的此类问题后,我无法弄清楚waitpid的正确用法,因此我将描述问题。

我需要运行sleep命令几秒钟,保存该pid,运行ls命令并在休眠在后台运行时保持我的shell运行。接下来执行的下一个前台进程(ls)之后将在执行后清除后台进程。所以我写了这样的东西

while(1) {
 //Prompt user input
 //Get input from user
 //Parse & tokenize
    //Determine if this process is to run in the background
                if((strcmp(symbols[0], "&") == 0) || (strcmp(symbols[0], "&\n") == 0)) {
                    backgroundFlag = true;
                } else {
                    backgroundFlag = false;
                    foregroundFlag = true;
                }

            pid_t childPid = fork();
            if(backgroundFlag == true && childPid != 0) {
                backgroundPid = childPid;
            }


            //Determine the process
            if(childPid == 0) {
                //Run in the background
                if(backgroundFlag == true) {
                    printf(">>>IN CHILD(background): backgroundPid = %d\n", getpid());
                    backgroundPid = getpid();
                } else {
                    foregroundFlag = true;
                    //debug
                    printf("\n>>>IN CHILD: pid = %d\n", getpid());
                }

                //Save this for child pid
                childPid = getpid();

                //Execute the command
                execvp(command1[0], args1-1);
            } else {
                printf("\n>>>In Parent: pid = %d\n", getpid());

                //this is the parent
                if(backgroundFlag == false && backgroundPid == 0) {
                    wait(NULL);
                    foregroundFlag = false;
                    printf("\n...Child reaped: pid = %d\n", childPid);
                } else if (backgroundFlag == true && backgroundPid > 0) {
                    pid_t return_pid = waitpid(backgroundPid, 0, WNOHANG);
                    if(return_pid == backgroundPid) {
                        printf("\n...background child reaped: pid = %d\n", backgroundPid);
                        backgroundPid = 0;
                    }
                }
            }
}

但是shell只是运行进程,挂起并且从不给我任何消息。在这种情况下,当我按Enter键时,它将重新启动父级,直到循环的顶部,但绝不会收获后台进程。我到底在做什么错?我尝试使用backgroundPid和-1,WNOHANG和其他一些标志进行循环,但是我一直在获取相同的内容-它会运行并挂起,直到再次按Enter才再次提示输入,否则它将首先运行并且不允许任何输入其他需要处理的前景。

无论哪种方式,它都不会收获背景。

这是我通过执行sleep(3)和(这是回显的自定义睡眠)而得到的结果,然后在完成前显示ls,然后再次显示ls

progShell> ./customecho testing &

COMMAND #1: ./customecho

...The above command will be executed in background

>>>In Parent: pid = 7774

Freeing input...
backgroundPid - 7793
looping...
>>>IN CHILD(background): backgroundPid = 7793
progShell> ls

COMMAND #1: ls

>>>In Parent: pid = 7774

Freeing input...
backgroundPid - 7793
looping...
progShell>
>>>IN CHILD: pid = 7794
Makefile  progShell  progShell.c  customecho.c  customecho
customecho PID=7793: testing

然后只有在按ENTER键后我才能得到此信息... 没有终止...

Freeing input...
backgroundPid - 7793
looping...

编辑:播放了一段时间,并设法修复了一些代码-

while(1) {
    //Determine if this process is to run in the background
            if((strcmp(symbols[0], "&") == 0) || (strcmp(symbols[0], "&\n") == 0)) {
                backgroundFlag = true;
                backgroundFinishedFlag = false;
            } else {
                backgroundFlag = false;
                foregroundFlag = true;
            }

            printf("Background finished: %d\n", backgroundFinishedFlag);
            printf("Background flag: %d\n", backgroundFlag);

            //Create a new process
            pid_t childPid = fork();

            //Determine if this process is to run in the background, and assign appropriately per process.
            if(backgroundFlag == true && childPid == 0) {
                backgroundPid = getpid();
                printf("Background process (PID=%d)\n", backgroundPid);
            } else if(backgroundFlag == true) {
                backgroundPid = childPid;
            }

            //Determine the process we are in - this is child
            if(childPid == 0) {
                //debug
                //Run in the background
                if(backgroundFlag == true) {
                    printf(">>>IN CHILD(background): backgroundPid = %d\n", getpid());
                } else {
                    //Run in the foreground
                    printf("\n>>>IN CHILD: pid = %d\n", getpid());
                }

                //Save this for child pid
                childPid = getpid();

                //Execute the command
                execvp(command1[0], args1-1);
            } else {
                //this is the parent
                //debug
                printf("\n>>>In Parent: pid = %d\n", getpid());
                printf("\t this parent's child is - %d and background id is %d\n", childPid, backgroundPid);

                //There is a foreground process - execute it first.
                if(foregroundFlag) {
                    waitpid(childPid, NULL, 0);
                    foregroundFlag = false;
                    printf("\n...Child reaped: pid = %d\n", childPid);
                } 

                //Determine if there is a background process to be reaped
                if(backgroundFinishedFlag == false && backgroundPid > 0 && (waitpid(backgroundPid, NULL, WNOHANG) > 0)) {
                    printf("\nTerminating background process now!\n");

                    backgroundFinishedFlag = true;
                    backgroundPid = 0;
                }
            }

}

它在下一个前台进程完成时在后台终止子进程... 唯一的问题是,后台进程完成后,我希望它再次提示输入-我可以使用任何信号捕获来执行此操作吗?例如...休眠打印后,它将覆盖看起来像输入的“ shellProg>”提示,并留出空白空间供输入。

shellProg> sne PID=9886: testing

(我按Enter或此处的任何输入,否则无提示)

Freeing input...
backgroundPid - 9886
looping...
shellProg> 

0 个答案:

没有答案