两个不同的进程 虚拟地址相同_不求甚解之进程fork()

4bd68cb806d2045ecab97249cc706e19.png

不求甚解之进程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)不一样,这样就对应物理地址是一样了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值