fork:
一个进程,包括代码、数据和分配给进程的资源。fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。
一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。
fork特点:
- 调用一次,返回两次。●调用一次。返回两次。fork函数被父进程调用一次,但是却返回两次一 次是返回到父进程,一次是返回到新创建的子进程。
- .并发执行。父进程和子进程是并发运行的独立进程。内核能够以任意方式交替执行它们的逻辑控制流中的指令。
- **相同但是独立的地址空间。**父进程和子进程是独立的进程,它们对变量的任何改变都是独立的。
- 共享文件。
下面看一个典题:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char* argv[])
{
fork();
fork() && fork() || fork();
fork();
printf("hello\n");
}
运行结果1:
总共20个进程,除去main进程,还有19个进程。
为什么是还有19个进程。
第一个fork和最后一个fork肯定是会执行的。
主要在中间3个fork上,
- 注意&&和||运算符。
A&&B,如果A=0,就没有必要继续执行&&B了;A非0,就需要继续执行&&B。
A| |B,如果A非0,就没有必要继续执行||B了,A=0,就需要继续执行| |B。
- 父进程中fork返回1,子进程返回0.
运行结果2:
程序的唯一的区别就在于一个/n回车符号,为什么结果会相差这么大呢?
这就跟printf的缓冲机制有关了,printf某些内容时,操作系统仅仅是把该内容放到了stdout的缓冲队列里了,并没有实际的写到屏幕上。
但是,只要看到有\n则会立即刷新stdout,因此就马上能够打印了。
运行了printf(“fork!”)后,“fork!”仅仅被放到了缓冲里,程序运行到fork时缓冲里面的“fork!” 被子进程复制过去了。因此在子进程度stdout缓冲里面就也有了fork! 。所以,你最终看到的会是fork! 被printf了2次!!!!
而运行printf(“fork! \n”)后,“fork!”被立即打印到了屏幕上,之后fork到的子进程里的stdout缓冲里不会有fork! 内容。因此你看到的结果会是fork! 被printf了1次!!!!
代码1:
#include <unistd.h>
#include <stdio.h>
int main() {
pid_t fpid;//fpid表示fork函数返回的值
printf("fork!");
fpid = fork();
if (fpid < 0)
printf("error in fork!");
else if (fpid == 0)
printf("I am the child\n");
else
printf("I am the parent\n");
return 0;
}
代码2:
#include <unistd.h>
#include <stdio.h>
int main() {
pid_t fpid;
printf("fork!\n");
fpid = fork();
if (fpid < 0)
printf("error in fork!");
else if (fpid == 0)
printf("I am the child\n");
else
printf("I am the parent\n");
return 0;
}
运行结果: