在bash中,如果我执行命令(sleep 60) & wait
,那么bash将等待60秒完成,但如果我执行(sleep 60 &); wait
则不会发生等待。这两种情况(幕后)的根本区别是什么?
答案 0 :(得分:0)
if I execute (sleep 60 &); wait then no waiting occurs.
这是因为sleep 60 &
在分叉子进程的后台运行而不是在当前进程中运行。当wait
在当前进程中运行时,它没有任何等待的工作。
对于前。当你跑:
(sleep 60) &
child sleep process
仅进入当前shell的作业,因此wait
可以正常工作。
要测试此功能,您可以运行:
jobs -l </ p>
并查看后台作业中的睡眠过程:
[2]+ 74103 Running ( sleep 60 ) &
答案 1 :(得分:0)
我将借助于打印进程'pid及其父级pid的程序来说明这一点。
$ cat getpids.c
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
main()
{
printf("%d %d\n", (int)getpid(), (int)getppid());
exit(10);
}
$ echo $$
2002
我们的shell是2002年的过程。
$ ./getpids
2651 2002
这表明getpids是在shell的子进程中运行的。
$ (./getpids)& wait
[1] 2656
2656 2002
[1]+ Exit 10 ( ./getpids )
getpids再次在shell的子进程中运行。 shell等待它并显示其退出状态。
$ (./getpids&); wait
$ 2658 1
这里,getpids是init的一个子进程1.这意味着,当它调用getppid()时,它的父进程已退出。
$ ./getpids
2663 2002
Shell 2002仍然存在。发生的事情是,在这种特殊情况下,shell决定(command&)
值得在shell的fork中运行。那个分叉的shell再次分叉,启动了getpids,然后在getpids开始运行getppid()调用之前退出。
我们可以通过strace
查看系统调用来更仔细地查看。
2002 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb77c5938) = 2657
2002 wait4(-1, <unfinished ...>
2657 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0xb77c5938) = 2658
2657 exit_group(0) = ?
2002 <... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 2657
2658 execve("./getpids", ["./getpids"], [/* 22 vars */]) = 0
Shell 2002 forks并创建shell 2657,它会分叉并创建进程2658然后退出。 Shell 2002等待并看到退出的进程2657。 Shell 2658,现在是“孤儿”,因此拥有父pid 1,执行./getpids。