fork() 系统调用和进程的内存空间 [英] fork() system call and memory space of the process

查看:16
本文介绍了fork() 系统调用和进程的内存空间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我引用当一个进程使用 fork() 调用创建一个新进程时,只有共享内存段在父进程和新分叉的子进程之间共享.堆栈和堆的副本是为新创建的Silberschatz 的操作系统概念"解决方案中的流程".

但是当我尝试这个程序时

#include <stdio.h>#include <sys/types.h>#define MAX_COUNT 200无效子进程(无效);/* 子进程原型 */无效父进程(无效);/* 父进程原型 */无效主要(无效){pid_t pid;char * x=(char *)malloc(10);pid = fork();如果(pid == 0)子进程();别的父进程();printf("地址是%p
",x);}无效子进程(无效){printf(" *** 子进程 ***
");}无效父进程(无效){printf("*** 父级 *****
");}

结果是这样的:

*** 家长*****地址是 0x1370010***子进程***地址是 0x1370010

父母和孩子都打印堆中的相同地址.

谁能解释一下这里的矛盾.请清楚地说明父母和孩子在内存空间中共享的所有东西.

解决方案

从另一个线程引用自己.

  • <块引用>

    当一个 fork() 系统调用被发出时,所有页面的副本对应父进程被创建,加载到单独的操作系统用于子进程的内存位置.但这不是在某些情况下需要.考虑当一个孩子执行一个"exec" 系统调用或在 fork() 之后很快退出.当...的时候child 只需要为父进程执行命令,不需要复制父进程的页面,因为 exec将调用它的进程的地址空间替换为要执行的命令.

    在这种情况下,会使用一种称为写时复制 (COW) 的技术.和这种技术,当发生分叉时,父进程的页面不会为子进程复制.相反,页面在子进程和父进程.每当一个进程(父或子)修改页面,单独制作该特定页面的单独副本对于执行修改的那个进程(父进程或子进程).然后,此过程将使用新复制的页面,而不是在所有未来的参考文献中共享一个.另一个过程(其中一个没有修改共享页面)继续使用原始副本页面(现在不再共享).这种技术被称为写入时复制,因为当某些进程写入时页面被复制.

  • 另外,为了理解为什么这些程序似乎使用相同的内存空间(事实并非如此),我想引用操作系统:原理与实践"一书中的一部分内容.

    <块引用>

    大多数现代处理器都引入了一个间接级别,称为虚拟地址.有了虚拟地址,每个进程的内存从相同"的地方开始,例如,零.每个进程都认为自己拥有整台机器,尽管显然现实中并非如此.

    所以这些虚拟地址是物理地址的转换,并不代表相同的物理内存空间,举个更实际的例子,我们可以做一个测试,如果我们多次编译和运行一个显示方向的程序静态变量,比如这个程序.

    #include <stdio.h>int main() {静态int a = 0;printf("%p
    ", &a);获取字符();返回0;}

    不可能两次获得相同的内存地址如果我们直接处理物理内存,则不同的程序.

    而多次运行程序得到的结果是……

I quote "when a process creates a new process using fork() call, Only the shared memory segments are shared between the parent process and the newly forked child process. Copies of the stack and the heap are made for the newly created process" from "operating system concepts" solutions by Silberschatz.

But when I tried this program out

#include  <stdio.h>
#include  <sys/types.h>

#define   MAX_COUNT  200

void  ChildProcess(void);                /* child process prototype  */
void  ParentProcess(void);               /* parent process prototype */

void  main(void)
{
         pid_t  pid;
         char * x=(char *)malloc(10);

         pid = fork();
         if (pid == 0) 
            ChildProcess();
         else 
            ParentProcess();
        printf("the address is %p
",x);
}

void  ChildProcess(void)
{
          printf("   *** Child process  ***
");
}

void  ParentProcess(void)
{
         printf("*** Parent*****
");
}

the result is like:

*** Parent*****
the address is 0x1370010
   *** Child process  ***
the address is 0x1370010

both parent and child printing the same address which is in heap.

can someone explain me the contradiction here. please clearly state what are all the things shared by the parent and child in memory space.

解决方案

Quoting myself from another thread.

  • When a fork() system call is issued, a copy of all the pages corresponding to the parent process is created, loaded into a separate memory location by the OS for the child process. But this is not needed in certain cases. Consider the case when a child executes an "exec" system call or exits very soon after the fork(). When the child is needed just to execute a command for the parent process, there is no need for copying the parent process' pages, since exec replaces the address space of the process which invoked it with the command to be executed.

    In such cases, a technique called copy-on-write (COW) is used. With this technique, when a fork occurs, the parent process's pages are not copied for the child process. Instead, the pages are shared between the child and the parent process. Whenever a process (parent or child) modifies a page, a separate copy of that particular page alone is made for that process (parent or child) which performed the modification. This process will then use the newly copied page rather than the shared one in all future references. The other process (the one which did not modify the shared page) continues to use the original copy of the page (which is now no longer shared). This technique is called copy-on-write since the page is copied when some process writes to it.

  • Also, to understand why these programs appear to be using the same space of memory (which is not the case), I would like to quote a part of the book "Operating Systems: Principles and Practice".

    Most modern processors introduce a level of indirection, called virtual addresses. With virtual addresses, every process's memory starts at the "same" place, e.g., zero. Each process thinks that it has the entire machine to itself, although obviously that is not the case in reality.

    So these virtual addresses are translations of physical addresses and doesn't represent the same physical memory space, to leave a more practical example we can do a test, if we compile and run multiple times a program that displays the direction of a static variable, such as this program.

    #include <stdio.h>
    
    int main() {
        static int a = 0;
    
        printf("%p
    ", &a);
    
        getchar();
    
        return 0;
    }
    

    It would be impossible to obtain the same memory address in two different programs if we deal with the physical memory directly.

    And the results obtained from running the program several times are...

这篇关于fork() 系统调用和进程的内存空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆