关于fork的一些基本问题
1.什么是fork?
fork函数通过系统调用创建一个与原进程几乎相同的进程
一个进程,包括代码、数据和分配给进程的资源。fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。
一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己`
调用一次返回两次,一次返回到父进程,一次返回到新创建的子进程。
void fork1()
{
int x = 1;
pid_t pid = fork();
if (pid == 0) {
printf("Child has x = %d\n", ++x);
}
else {
printf("Parent has x = %d\n", --x);
}
printf("Bye from process %d with x = %d\n", getpid(), x);
}
运行结果如图:
两个进程一个父进程,一个子进程,父进程对x加一,子进程对x减一,二者的pid号不同,这也说明了子进程和父进程都有x,但是子进程和父进程并不是共享同一个x的,这也就是线程和进程的最大的区别。
2.关于fork的问题
(1)、
void fork2()
{
printf("L0\n");
fork();
printf("L1\n");
fork();
printf("Bye\n");
}
运行结果
进程图
可以看到各进程的输出情况。这也让我们知道了,fork出的进程是从fork后开始执行的,就像是父进程的孩子,在孩子出生之后继承父进程的数据,但是后面也许会变得和父进程不同。
(2)、
void fork4()
{
printf("L0\n");
if (fork() != 0) {
printf("L1\n");
if (fork() != 0) {
printf("L2\n");
}
}
printf("Bye\n");
}
运行结果:
进程图
刚刚看这道题我还以为两个if语句是并列的,之后看了运行结果和想的不一样,才发现两个语句是嵌套的而不是并列的。
3.什么是僵尸进程?
僵尸进程的含义是:子进程已经死了,但是父进程还没有wait它的一个中间状态,这个时候进程是一个僵尸。僵尸进程不能被杀死,因为竟是进程本来就是死的。。。
void fork11()
{
pid_t pid[N];
int i;
int child_status;
for (i = 0; i < N; i++)
if ((pid[i] = fork()) == 0)
exit(100+i); /* Child */
for (i = N-1; i >= 0; i--) {
pid_t wpid = waitpid(pid[i], &child_status, 0);
if (WIFEXITED(child_status))
printf("Child %d terminated with exit status %d\n",
wpid, WEXITSTATUS(child_status));
else
printf("Child %d terminate abnormally\n", wpid);
}
}
4.什么是waitpid
pid_t waitpid(pid_t pid,int *statusp, int options);
(1)第一个参数:如果pid>0,那么等待集合就是一个单独的子进程,它的进程号是ID等于pid
如果pid=-1那么等待集合就是由父进程所有的子进程组成子进程组成。
(2)options设置为常量WNOHANG、WUNTRACED和WCONTINUED的各种组合来修改默认行为。
(3)如果statusp参数是非空的。那么waitpid就会在status中放上导致返回的子进程的状态信息。