我正在尝试制作一个简单的外壳,并添加了使用&在后台运行进程的功能。
在我的主要方法中,我基本上有:
int main() {
if (signal(SIGCHLD, handle) == SIG_ERR)
perror("Cannot catch SIGCHLD");
pid_t child = fork();
if (child == 0)
execvp(command, arguments);
else {
if (background == 1) {
printf("1");
backgroundList(command, child);
printf("2"); }
else
waitpid(child, NULL, 0);
}
}
对于我的经理,我有:
void handle(int s) {
printf("a");
if (signal(SIGCHLD, handle) == SIG_ERR)
perror("Cannot catch SIGCHLD");
pid_t pid;
printf("b");
while((pid = waitpid(0, NULL, WNOHANG)) > 0) {
printf("c");
rmBackgroundList(pid);
printf("d");
}
}
我可以让它在前台运行一个进程。运行“ ls”会将内容打印到屏幕上,然后将“ a”和“ b”打印到SIGCHLD处理程序中,但是由于已经等待,因此不会转到“ c”。
但是,在后台运行某些内容(“ ls&”)将显示“ 1”和“ 2”,让父级返回到提示,然后子级将内容打印到屏幕上,然后出现分段错误。它不会打印处理程序中我拥有的任何字母。
我无法弄清楚为什么SIGCHLD对已经等待的孩子有好处,但是会导致分段错误,甚至对于没有等待的进程也永远不会进入处理程序。
最佳答案
您没有遵循信号处理程序的规则。您不能使用printf()
或perror()
。 Read the rules on what is safe to do in a signal handler.
另外,signal()
的行为也会根据BSD或SysV风格的Unix而变化。 Linux会根据_BSD_SOURCE或_GNU_SOURCE的存在来更改其在glibc中的行为,具体取决于您调用gcc -ansi
还是gcc -std=c99
或gcc -std=gnu99
您确实应该使用sigaction()
而不是signal()
。