我正在尝试理解C中的进程。我当前想要创建类似shell的结构 - 按下 Ctrl + C 或之后的快捷键 + Z 会杀死它的所有子进程,但会保持活着状态。我的代码如下所示:
#include <ctype.h>
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/wait.h>
#include <termios.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/signal.h>
pid_t pid;
void send_signal(int signum){
kill(pid, signum);
}
void init_signals(){
signal(SIGINT, send_signal);
signal(SIGTSTP, send_signal);
}
int main(){
init_signals();
pid = fork();
if(pid > 0){
//Parent Process
wait(NULL);
} else {
// Child Process
while(1){
usleep(300000);
}
}
return 0;
}
问题在于,当我按下Ctrl + C时,父级会将其重定向到子级并将其杀死,但是当我按下Ctrl + Z时(即使子进程已停止),父级仍会挂起wait(NULL)
。有关如何解决此问题的任何建议吗?
答案 0 :(得分:1)
您可以在此处查看how to use wait in C。长话短说:
wait system-call将进程置于休眠状态并等待子进程结束。然后它使用子进程的退出代码填充参数(如果参数不是NULL)。
wait
在子进程结束之前不会发出信号,因此只需将子进程发送到睡眠状态,主进程就没有理由继续进行。如果你想要任何主要过程仍在工作的设置,而孩子也一样(包括睡觉时),你不能等待孩子。
对于shell来说也没有意义 - 它总是在后台活动。相反,你需要一个更好的主要处理程序 - 比如等待一个条件。这样,当孩子入睡时,你可以发出信号并继续前进。
答案 1 :(得分:0)
除了https://stackoverflow.com/a/49346549/5694959的解决方案之外,我想建议另外一个解决方案来处理仅用于父进程的信号。这样父进程将执行信号处理程序,并且将对子进程执行默认操作。使用waitpid()
获取孩子的状态。
waitpid(pid,NULL,WUNTRACED);
现在,当子进程更改其状态(即终止或停止)时,父进程将恢复执行。
按如下方式更新您的代码:
#include <ctype.h>
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/wait.h>
#include <termios.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/signal.h>
pid_t pid;
void send_signal(int signum){
kill(pid, signum);
}
void init_signals(){
signal(SIGINT, send_signal);
signal(SIGTSTP, send_signal);
}
int main(){
pid = fork();
if(pid > 0){
//Parent Process
init_signals();
waitpid(pid, NULL, WUNTRACED);
printf("I think this is what you are expecting...\n");
} else {
// Child Process
while(1){
usleep(300000);
}
}
return 0;
}
请记住一件事,请确保父流程 在按 ctrl + c 或 ctrl + z 之前处理了信号,否则将执行信号的默认动作对于父母也是如此。