fork()如何重复内存

时间:2013-10-16 03:20:09

标签: fork

我对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 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分: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;

}

希望这会有所帮助,叉子有时会让人感到困惑。

答案 2 :(得分: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
}