首页 文章

fork()如何重复内存

提问于
浏览
0

我对fork()如何从父进程复制内存感到困惑 . 我试着通过写一个例子找到它:

int global_var = 0;


int main(int argc, char* argv[]){

    int local_var = 1;

    pid_t child;

    child = fork();


    if (child < 0){
        cout << "Fork error: " << strerror(errno) << endl;
        return 1;
    }



    if (child != 0 ){ // parent


        cout << "Parent: global address: " << &global_var << endl;
        cout << "Parent: local address: " << &local_var << endl;

        ++global_var;
        ++local_var;

        cout << "Parent: global: " << global_var << endl;
        cout << "Parent: local: " << local_var << endl;



    }else{

        cout << "Child: global address: " << &global_var << endl;
        cout << "Child: local address: " << &local_var << endl;

        sleep(1);

        cout << "Child: global: " << global_var << endl;
        cout << "Child: local: " << local_var << endl;
    }

    return 0;

}

我看到了结果:

父级:全局地址:0x6021a0父级:本地地址:0x7fff942dd99c父级:全局:1父级:本地:2子级:全局地址:0x6021a0子级:本地地址:0x7fff942dd99c子级:全局:0子级:本地:1

为什么孩子没有看到变量的变化,即使孩子的变量与父母的变量在同一地址 . 请有人帮我解释一下 .

提前致谢 .

3 回答

  • 1

    孩子和父母不共享记忆 . 地址具有相同的值,但它们位于不同的堆栈中,如两个不同城市的"123 Main Street";它们指的是记忆中的两个不同位置 . 孩子看不到父母做出的改变,因为这些改变没有发生在孩子的堆叠中 .

  • 0

    当你分叉一个进程时,它就变成了自己的程序,即父进程的副本 .

    在您的示例代码中,您只需在父进程中增加global_var和local_var .

    试试这个看 .

    int global_var = 0;
    
    int main(int argc, char* argv[]){
    int local_var = 1;
    
    pid_t child;
    
    child = fork();
    
    
    if (child < 0){
        cout << "Fork error: " << strerror(errno) << endl;
        return 1;
    }
    
    
    
    if (getpid() != 0 ){ // parent
        cout << "Parent: global address: " << &global_var << endl;
        cout << "Parent: local address: " << &local_var << endl;
    
        ++global_var;
        ++local_var;
    
        cout << "Parent: global: " << global_var << endl;
        cout << "Parent: local: " << local_var << endl;
    
    
    
    }else if(getpid() == 0){ // child
    
        cout << "Child: global address: " << &global_var << endl;
        cout << "Child: local address: " << &local_var << endl;
    
        ++global_var;
        ++local_var;
    
        cout << "Child: global: " << global_var << endl;
        cout << "Child: local: " << local_var << endl;
    }
    
    return 0;
    
    }
    

    希望这会有所帮助,叉子有时会令人困惑 .

  • 0

    进程有两种类型的虚拟内存:内核和用户 . fork()时,创建一个具有单独虚拟内存的克隆子进程,该进程几乎与父进程相同 . fork()调用在父级中进行,但返回两次,一次在父级中,一次在子级中 . 案例由返回码区分:

    int x = fork();
    if(x == 0) 
    {
        // we are in the child
    }
    else
    {
        // we are in the parent
    }
    

    除了此返回代码之外,用户存储器将是相同的 . 内核内存有一些区别:计时器在孩子中休息,pid和ppid是不同的等等 . 通常调用execve()来跟进子进程,这将覆盖用户区域并允许子进程执行与父母完全不同的代码 . execve()被调用一次并且永远不会返回,因为代码是过时的,例如,

    int x = fork();
    if(x == 0) 
    {
        // we are in the child
        execve("myprog", argv, envp);  // overwrites the code with that from myprog
        // never get here because execve never returns
    }
    else
    {
        // we are in the parent
    }
    

相关问题