c - 在下一个前台进程中终止后台进程
问题描述
我在循环我的 shell 和终止后台进程时遇到了麻烦。在看了几个小时这样的问题后,我无法弄清楚 waitpid 的正确用法,所以我将描述我的问题。
我需要运行一个 sleep 命令几秒钟,保存那个 pid,运行一个 ls 命令并在 sleep 在后台运行时保持我的 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;
}
}
}
}
但是外壳程序只是运行该过程,挂起并且从未给我一个收获的消息。在那种情况下,当我按下回车键时,它会将父进程重新启动到循环的顶部,但永远不会收获后台进程。我到底做错了什么?我尝试使用 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
(我在这里按回车键或任何输入,否则没有提示)
Freeing input...
backgroundPid - 9886
looping...
shellProg>
解决方案
推荐阅读
- javascript - Angular-如何重复具有不同数据的组件?
- mysql - MySql:如何只获得四个唯一的结果?
- shiny - stat_bin 需要以下缺失的美学:x
- python-3.x - python中的双倍日志消息
- python - (Python) converting a list of integers into tuples/sets changes positions of integers
- javascript - 如何在本地选择文件
- javascript - 如何使用 ant design 自动完成(react js)搜索和查找表详细信息
- c# - SHA1 hash code comparing fails
- java - 如何在 Android 中生成视频预览缩略图
- prismic.io - template forms in prismic