我正在尝试创建一个简单的shell并添加功能以在后台使用&运行进程。 在我的主要方法中,我基本上有:
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对已经等待但却导致分段错误的孩子有好处,甚至从未进入处理器以处理未等待的进程。
答案 0 :(得分:0)
您没有遵循信号处理程序的规则。您无法使用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()
。