父子进程
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main(){
// 创建子进程
pid_t pid = fork();
//判断是父进程还是子进程
if(pid > 0){
//如果大于0,返回的是创建的子进程的PID号,当前是父进程
printf("pid :%d\n",pid);
printf("i am parent process,pid : %d,ppid :%d\n",getpid(),getppid());
}else if(pid == 0){
// 当前是子进程
printf("i am child process, pid :%d,ppid: %d\n",getpid(),getppid());
}
//for 循环
for(int i=0;i<10000;i++)
{
printf("i : %d,pid : %d\n",i,getpid());
//sleep(1);
}
return 0;
}
代码运行的区域:
关键是fork() 的返回值
Linux 的 fork() 使用是通过写时拷贝实现。写时拷贝是一种可以推迟甚至避免拷贝数据的技术。内核并不复制整个进程的地址空间,而是让父子进程共享同一个地址空间。只有在写入时才会复制地址空间(重新开辟一块内存),从而使各个进程拥有自己的地址空间。即资源的复制只有在写入时才会进行,在此之前,只有以只读的方式进行。
fork() 之后的父子进程共享文件,此时的 fork() 产生的子进程与父进程相同的文件描述符指向相同的文件表,引用计数增加,共享文件偏移指针
总结
首先父进程执行到fork时会创建子进程,fork后会给父子进程分别返回一个pid号(父进程fork后返回的pid号为子进程的pid=10089,而返回给子进程的pid号为0。注意,该代码第二行的pid是由fork创建后返回的pid,并不是该进程本身的pid,这点容易搞混,最好改一下命名如r_pid好一些),此时系统会将父进程的用户去数据和内核区拷贝过来生成一段新的虚拟地址空间供子进程使用,然后父进程开始继续执行if()判断,此时子进程是在父进程fork()后创造出来的,因此子进程只会执行fork()之后的语句,即也进行if()判断。但不同的是父进程是通过栈空间返回的pid号为大于0的值,而子进程通过栈空间返回的pid号为等于0的值。因此父子进程执行的if条件语句并不相同。
(实际更精准的说,Linux的fork()函数是通过写时拷贝来实现的,即fork后内核实际并不复制整个父进程的地址空间,而是让父子进程以只读的方式共享一个地址空间,只有在写入操作时才会进行资源的复制操作)