#define _XOPEN_SOURCE 700
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
void run_command(void)
{
char *cmd = NULL, *arg;
size_t n, l;
bool background;
pid_t child;
l = getline(&cmd, &n, stdin);
cmd[l-1] = 0;
l--;
if (cmd[l-1] == '&') {
background = true;
cmd[l-1] = 0;
l--;
}
else
background = false;
arg = strchr(cmd, ' ');
if (arg) {
*arg = 0;
arg++;
}
child = fork();
if (child) {
if (!background)
waitpid(child, NULL, 0);
}
else {
execlp(cmd, cmd, arg, NULL);
exit(-1);
}
free(cmd);
}
int main(void)
{
sigset_t set;
struct sigaction sig;
sigemptyset(&set);
sig.sa_handler = SIG_DFL;
sig.sa_mask = set;
sig.sa_flags = SA_NOCLDWAIT;
sigaction(SIGCHLD, &sig, NULL);
while(!feof(stdin)) run_command();
}
这按预期工作:
hdante@aielwaste:~/code$ ./shell
pwd
/home/hdante/code
ls /home
hdante
sleep 5
ls /
bin dev initrd.img lib32 lost+found opt run srv usr vmlinuz.old
boot etc initrd.img.old lib64 media proc sbin sys var
cdrom home lib libnss3.so mnt root selinux tmp vmlinuz
sleep 5&
xedit&
ls /
bin dev initrd.img lib32 lost+found opt run srv usr vmlinuz.old
boot etc initrd.img.old lib64 media proc sbin sys var
cdrom home lib libnss3.so mnt root selinux tmp vmlinuz
在上面的示例中, sleep 5 正确阻塞,而 sleep 5& 和 xedit& 不会。
如果不查看您的代码,就不可能知道问题出在哪里。但是请注意我处理僵尸进程的方式:我在 sa_flags 中使用 SA_NOCLDWAIT,这样我就不需要跟踪 pid。另外,我使用waitpid() 等待前台子进程。这就是我认为问题所在。您的代码可能正在调用 wait() 而不是 waitpid()。不同之处在于 wait() 等待所有孩子。