C语言如何获得变量的物理地址以及简单的写时拷贝测试

基本的思路:linux下的/proc/self是对自身进程映射的文件夹,里面的pagemap允许查看到每个虚拟页映射到的物理页。

#include <stdio.h>
#include <unistd.h>
#include <inttypes.h>
intptr_t Mytop(uintptr_t vaddr) 
{
    FILE *pagemap;
    intptr_t paddr = 0;
    int offset = (vaddr / sysconf(_SC_PAGESIZE)) * sizeof(uint64_t);
    uint64_t e;
     // https://www.kernel.org/doc/Documentation/vm/pagemap.txt
    if ((pagemap = fopen("/proc/self/pagemap", "r"))) {
        if (lseek(fileno(pagemap), offset, SEEK_SET) == offset) {
            if (fread(&e, sizeof(uint64_t), 1, pagemap)) {
        if (e & (1ULL << 63)) { // page present ?
                    paddr = e & ((1ULL << 54) - 1); // pfn mask
                    paddr = paddr * sysconf(_SC_PAGESIZE);
            // add offset within page
            paddr = paddr | (vaddr & (sysconf(_SC_PAGESIZE) - 1));
                }   
            }   
        }   
        fclose(pagemap);
    }   
    return paddr;
}  


void TestShow(void *x)
{
  printf("Virtual Address:%u Physical Address:%u\n",x,Mytop((uintptr_t)x));
}

void main()<pre>
{
  int a;
  TestShow(&a);
}

呃。。。。顺便一提吧,本人后来测试了一下vfork的写时拷贝,大名鼎鼎的写时拷贝….
C语言如何获得变量的物理地址以及简单的写时拷贝测试_第1张图片
结果发现
C语言如何获得变量的物理地址以及简单的写时拷贝测试_第2张图片
vfork写时拷贝是完全不存在的。。。。父子进程完全共享虚拟空间,并且经过测试,本人发现了调动vfork后,一定是子进程先结束后父进程才能继续执行!
呃,后来我想了一下,估计原因是这样的: 假设父进程不在子进程调度完成后才能继续玩下跑,那么在父子进程交替着调度往下跑,并且是在同一个堆栈上进行函数调用,栈帧开辟释放,那么结果无疑是一种噩梦般的结果..我有点困扰为什么系统要这么做,于是我去查阅了一下关于vfork的介绍。得到了以下东西:
1. fork要拷贝父进程的数据段;而vfork则不需要完全拷贝父进程的数据段,在子进程没有调用exec和exit之前,子进程与父进程共享数据段
2. fork不对父子进程的执行次序进行任何限制;而在vfork调用中,子进程先运行,父进程挂起,直到子进程调用了exec或exit之后,父子进程的执行次序才不再有限制
顿时有点茅塞顿开的感觉,原来linux内核设计vfork就是和exec配套使用的,写时拷贝更多的是讲一个进程调用vfork确实完全共享进程绝大部分资源,这里是讲共享部分,至于拷贝部分不是说什么蛋疼的程序员,,,比如我。。。无聊的修改了一下局部变量或者是栈上数据,那么系统就要因此给你分配出相应的东西出拷贝一份原有东西再进行你的修改操作,让进程看起来好像是在你(程序员 )写入后系统自动拷贝再去修改。。。。这个是不可能的,内核不可能这么蛋疼专门去检测这些东西,或者说vfork就是为了exec而诞生的,估计内核设计者是这样想的吧,调动vfork的都是极度渴望进行快速exec的程序员同学。所谓的写时拷贝不是说程序员修改栈上数据引发内核专门分配对应资源再进行修改,而是讲的是frok以后调动exec,内核复制相应资源再进行修改!!!
呃。。。。废话有点多,既然测试了vfork发现学习了这么多东西,那么让我们继续进行测试frok吧。。。代码不用贴了吧..
改变点有两个:
1.fork替换了vfork
2.去掉了x = 10;y=20;
结果是发现fork在没有任何修改,父子进程栈上数据就已经是完全不一样了…..这里写图片描述
也就是说:fork以后父子进程拥有的函数调用栈不是同一个的!!而vfork则是同一个!!
呃。。。。然后我觉得有必然去测试一下全部变量或者是其他的……过一段时间再更新吧!!
备注:顺手看到,顺手粘贴的东西
C语言如何获得变量的物理地址以及简单的写时拷贝测试_第3张图片
_exit不清除IO缓存~~也就是说IO缓冲区的东西是不会输出的~

你可能感兴趣的:(linux,fork,vfork,写时拷贝,获得物理地址)