fork() system call and memory space of the process

2019-02-02 14:49发布

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\n",x);
}

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

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

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.

6条回答
我只想做你的唯一
2楼-- · 2019-02-02 15:11

Yes address in both the case is same. But if you assign different value for x in child process and parent process and then also prints the value of x along with address of x, You will get your answer.

#include  <stdio.h>
#include  <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#define   MAX_COUNT  200

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

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

    pid = fork();
    if (pid == 0) {
            *x = 100;
            ChildProcess();
    }
    else {
            *x = 200;
            ParentProcess();
    }
    printf("the address is %p and value is %d\n", x, *x);
}

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

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

Output of this will be:

*** Parent*****
the address is 0xf70260 and value is 200
*** Child process  ***
the address is 0xf70260 and value is 100

Now, You can see that value is different but address is same. So The address space for both the process is different. These addresses are not actual address but logical address so these could be same for different processes.

查看更多
该账号已被封号
3楼-- · 2019-02-02 15:14

You're probably running your program on an operating system with virtual memory. After the fork() call, the parent and child have separate address spaces, so the address 0x1370010 is not pointing to the same place. If one process wrote to *x, the other process would not see the change. (In fact those may be the same page of memory, or even the same block in a swap-file, until it's changed, but the OS makes sure that the page is copied as soon as either the parent or the child writes to it, so as far as the program can tell it's dealing with its own copy.)

查看更多
等我变得足够好
4楼-- · 2019-02-02 15:15

Yes, both processes are using the same address for this variable, but these addresses are used by different processes, and therefore aren't in the same virtual address space.

This means that the addresses are the same, but they aren't pointing to the same physical memory. You should read more about virtual memory to understand this.

查看更多
小情绪 Triste *
5楼-- · 2019-02-02 15:19

The address is the same, but the address space is not. Each process has its own address space, so parent's 0x1370010 is not the same as child's 0x1370010.

查看更多
Animai°情兽
6楼-- · 2019-02-02 15:24

When the kernel fork()s the process, the copied memory information inherits the same address information since the heap is effectively copied as-is. If addresses were different, how would you update pointers inside of custom structs? The kernel knows nothing about that information so those pointers would then be invalidated. Therefore, the physical address may change (and in fact often will change even during the lifetime of your executable even without fork()ing, but the logical address remains the same.

查看更多
乱世女痞
7楼-- · 2019-02-02 15:32

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\n", &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...

enter image description here

查看更多
登录 后发表回答