不求甚解之进程fork()
代码
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
int main(void)
{
int count = 0;
// pid_t 在 sys/types.h 中定义,代码追踪可以发现 等价于 int (typedef int pid_t)
pid_t pid;
// man fork 用于产生子进程,在 unistd.h定义
pid = fork();
if (pid < 0)
{
printf("error crate forkn");
exit(0);
}
else if (pid == 0)
{
count++;
printf("I am child process; The count=%d; The count adress=%p; The my process id=%d,My parent proccess id=%dn", count,&count,getpid(),getppid());
}
else if (pid > 0)
{
count = 6;
printf("I am parent process; The count=%d; The count address =%p; The my process id=%d; The my child process=%dn", count,&count, getpid(), pid);
sleep(1);
printf("I am parent process; The count=%d; The count address =%p; The my process id=%d; The my child process=%dn", count,&count, getpid(), pid);
}
printf("Run end;count=%d,count address=%pnn",count,&count);
return 0;
}
运行结果
I am parent process; The count=6;The count address =0x7ffeea439ad8; The my process id=41145; The my child process=41146
I am child process; The count=1;The count adress=0x7ffeea439ad8; The my process id=41146,My parent proccess id=41145
Run end;count=1,count address=0x7ffeea439ad8
I am parent process; The count=6;The count address =0x7ffeea439ad8; The my process id=41145; The my child process=41146
Run end;count=6,count address=0x7ffeea439ad8
代码解读
- 在 pid=fork()之前,只有一个进程在执行代码,但在这条语句执行后,就变成两个进行在执行了;这两个代码执行的代码完成相同。
- 在父进程执行时 fork()返回值为 子进程的ID // 就是linux操作系统中
ps aux
查看的那个进程id - 在子进程执行时 fork()返回值为 0
- 如果fork()失败 fork()返回值为 -1
- fork()后要复制了复制了父进进程的数据段。所以父子进程间的count变量是不可见的,独立的。
本例中fork()后,父进行选执行,count赋值于6,打印出来。
I am parent process; The count=6;The count address =0x7ffeea439ad8; The my process id=41145; The my child process=41146
接着主进程sleep(1);子进程已经执行,执行到return 0;子进程结束
I am child process; The count=1;The count adress=0x7ffeea439ad8; The my process id=41146,My parent proccess id=41145
Run end;count=1,count address=0x7ffeea439ad8
主进程sleep(1)后,继续执行,打印出
I am parent process; The count=6;The count address =0x7ffeea439ad8; The my process id=41145; The my child process=41146
Run end;count=6,count address=0x7ffeea439ad8
注 fork()出错的可能性还小,一般出错,是由于进程数达到了系统规定的上限(EAGAIN),二是内存不足(ENOMEM)。
物理地址和逻辑地址
细心的读者可能会,观察到了上面例子是count变量,内存地址变量都相都是address=0x7ffeea439ad8
,址一样,但是值却各异。是不是很奇怪。其实这是物理地址和逻辑地址(虚拟地址)关系。 逻辑地址: CPU所生成的地址。CPU产生的逻辑地址被分为 :p (页号) 它包含每个页在物理内存中的基址(R), 用来作为页表的索引;d (页偏移),同基址相结合,用来确定送入内存设备的物理内存地址。
物理地址: 内存单元所看到的地址。用户程序看不见真正的物理地址。用户只生成逻辑地址,且认为进程的地址空间为0到max。物理地址范围从R+0到R+max,
R为基地址,地址映射-将程序地址空间中使用的逻辑地址变换成内存中的物理地址的过程。由内存管理单元(MMU)来完成。
fork()操作时,子进程获得父进程数据空间、堆和栈的复制,所以变量的地址(当然是虚拟地址)也是一样的。关键点是基地址(R)不一样,这样就对应物理地址是一样了。