刚刚学Linux下C程序开发,看的是清华大学出版社出版的《Linxu C 程序基础与实例讲解》,我现在
对父子进程的执行顺序感到很困惑。书上的例子是先子进程后父进程。但在我的电脑上(Ubuntu 10.10)却是先父进程后子进程。
网上说,这是内核进程调度问题,请问一下这是怎么搞得,这样的程序是无法跨平台使用的吧?
附书上的例子:
运行结果:
Parent process with ID : 30394 ,Child process ID : 30395 .
Child process with ID : 30395 .
网上说,这是内核进程调度问题,请问一下这是怎么搞得,这样的程序是无法跨平台使用的吧?
附书上的例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
//fork()
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int
main()
{
pid_t child_pid;
child_pid=fork();
switch
(child_pid)
{
case
-1:
printf
(
"Create process failed!\n"
);
break
;
case
0:
printf
(
"Child process with ID : %d .\n"
,(
int
)getpid());
break
;
default
:
printf
(
"Parent process with ID : %d ,Child process ID : %d .\n"
,(
int
)getpid(),(
int
)child_pid);
break
;
}
return
0;
}
|
运行结果:
Parent process with ID : 30394 ,Child process ID : 30395 .
Child process with ID : 30395 .
这段代码怎么又是先子进程了?
调用了wait()函数的父进程马上阻塞自己,有wait()函数自动分析是否当前进程的某个子进程已经退出,如果找到这样一个一经变成僵进程的子进程,wait()函数就会收集这个子进程的信息,将它彻底终止并返回子进程结束状态值;如果没有找到这样一个子进程,wait()函数就会一直阻塞在这里,直到出现一个变成僵进程的子进程为止。
如果是下面这个程序,它的父进程先执行,父进程执行时就调用wait()函数,那父进程就阻塞了吧(停滞不前了),也就是说父进程在等子进程执行完毕,但子进程还没有执行。按理说这个程序应该不会结束的吧?但事实上不是这样的,这是为什么呢?
运行结果:
Parent process with ID 31371 ,Child process ID 31372 !
Child process finished : PID=31372
Child process exited with code 0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
// zombie.c
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int
main()
{
pid_t pid;
pid=fork();
if
(pid<0)
printf
(
"Error occurred!\n"
);
else
if
(pid==0)
{
printf
(
"ID=%d\n"
,(
int
)getpid());
exit
(NULL);
}
else
{
sleep(5);
wait(NULL);
}
return
0;
|
如果是下面这个程序,它的父进程先执行,父进程执行时就调用wait()函数,那父进程就阻塞了吧(停滞不前了),也就是说父进程在等子进程执行完毕,但子进程还没有执行。按理说这个程序应该不会结束的吧?但事实上不是这样的,这是为什么呢?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
// wait()
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int
main()
{
pid_t child_pid,pid;
int
status;
child_pid=fork();
switch
(child_pid)
{
case
-1:
printf
(
"Create process failed!\n"
);
break
;
case
0:
printf
(
"Child proces with ID %d!\n"
<(
int
)getpid());
break
;
default
:
printf
(
"Parent process with ID %d ,Child process ID %d !\n"
,(
int
)getpid(),(
int
)child_pid);
pid=wait(&status);
printf
(
"Child process finished : PID=%d \n"
,child_pid);
if
(WIFEXITED(status))
printf
(
"Child process exited with code %d \n"
,WEXITSTATUS(status));
else
printf
(
"Child process terminated abnormally!\n"
);
break
;
}
return
0;
}
|
运行结果:
Parent process with ID 31371 ,Child process ID 31372 !
Child process finished : PID=31372
Child process exited with code 0
fork就是这样的,父子进程的执行顺序不确定,谁先执行都有可能。
如果需要确定的执行顺序,就得想别的办法。
如果需要确定的执行顺序,就得想别的办法。
比如用vfork,保证子进程先运行。
父子进程哪个先运行时看内核的调度算法,在我们使用者看来,就是不确定的,LZ不要纠结了。switch 语句相当于并发处理,各个case之间一起运行的,父子进程之间谁运行时不可知的。1楼那个程序最后一个else里如果没有sleep和wait,谁先运行也是不可知的。
如果你很想控制他们谁先运行,可以使用sleep,先让一个睡一会嘛,只要sleep了,就肯定后运行。或者父进程中使用wait,等待子进程,那么很显然就是子进程在运行。
vfork的使用好像并不能控制运行顺序。
建议去看《unix坏境高级编程》,好好体会那里面的代码,会大有收获的