[techtalk] (no subject)

Laurel Fan lf25+ at andrew.cmu.edu
Fri Oct 20 11:52:31 EST 2000


Excerpts from linuxchix: 20-Oct-100 [techtalk] (no subject) by Arindam
Chatterjee at yahoo 
> i get the following output:
>  
> child process
>  addr of x = bffffb00 addr of y = bffffafc
> parent process
>  addr of x = bffffb00 addr of y = bffffafc
>           
> so far i know parent and child process should have
> separate address space. but here the addresses are
> same in both the processes. r they sharing the same
> address space? then any change in parent will be
> reflected in child. so why do i need pipe or fifo for
> IPC? 
> can anybody explain this?

You are correct, the processes have a separate address space.
Variables in both have the same addresses because these are
virtual addresses, not the actual physical address.

Most modern OSes don't allow user level processes to access arbitrary
physical addresses.  When you access a memory address, what really
happens is that it gets the virtual page number of the address (a page
is basically a fixed size chunk of memory, usually about 4k-ish.
pages are used because you don't want to have to translate every
virtual address to a physical address; with pages you can do a chunk
at a time), looks it up the the process's page table (a table that
maps virtual pages to physical pages), and then goes to the physical
page.

This gets you a lot of good things:

1. Memory protection.  If you don't have a page table entry for
a piece of memory, you can't access it.

2. Demand paging/swapping.  The page table can also point to disk, so
you can use more 'memory' than you have memory (so you can run
netscape :)).

3. Non-continuous physical addresses.  Your program can be in pieces
spread all over physical memory, and it'll still look like you have
a continuous address space.

(One thing to notice is that those addresses probably point to more
memory than you have. bffffb0 is somewhere in the 3G range.)

You can test this by actually assigning to the variable and seeing
if it affects the other process, by using code like [1].

Running that, I get:

child process
 addr of x = bffffbd4 addr of y = bffffbd0, x=10, y=15
parent process
 addr of x = bffffbd4 addr of y = bffffbd0, x=5, y=9

They have the same virtual address, but the values of the variable,
and therefore the memory that the address actually points to, are
different.

If you actually want the 'processes' to be able to mess with each
others' variables, you probably want to use threads.  [2] is similar
to your code, except it uses threads.  When running that, I get:

parent process (pid 5124) before pthread_create
 addr of x = 8049828 addr of y = 804982c, x=5, y=9
child thread (pid 5126)
 addr of x = 8049828 addr of y = 804982c, x=15, y=10
parent process (pid 5124) after pthread_create
 addr of x = 8049828 addr of y = 804982c, x=15, y=10

What the child thread did affected the variables in the parent process.

However, you don't get this for free.  There are a lot of new things
you have to worry about when you share variables between threads.
For example, suppose you have this code:

x = 2;
y = x;
x++;

You'd always expect this to end up with x=3, y=2, right? Not if you have
multiple threads.  It could do this:

A does    x = 2;   
B         x = 2;
B         y = x;   // x=2, y=2
A         y = x;   // x=2, y=2
B         x++;     // x=3, y=2
A         x++;     // x=4, y=2

Or it could do this:

A does    x = 2;   
B         x = 2;
B         y = x;   // x=2, y=2
B         x++;     // x=3, y=2
A         y = x;   // x=3, y=3
A         x++;     // x=4, y=3

To prevent the above from happening, you have to use mutex locks
(MUTual EXclusion locks prevent two processes from running the same
code at the same time).  If you do use threads, you should probably
get a good book on thread programming.

[1] looking at values of variables changed after a fork
---------
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

main()
{
  pid_t pid;
  int x = 5, y = 9;
  pid = fork();
  if(pid == 0)
  {
    x = 10, y = 15;
    printf("child process\n addr of x = %x addr of y = %x, x=%d, y=%d\n",
           &x, &y, x, y);
    fflush(stdout);
  }
  else
  {
    wait(0);
    printf("parent process\n addr of x = %x addr of y = %x, x=%d, y=%d\n",
           &x, &y, x, y);
    fflush(stdout);
  }
  exit(0);
}
-----

[2] looking at values of variables changed after a pthread_create (must
    be compiled with -lpthread)

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

int x = 5;
int y = 9;

int change_variables(void *v)
{
  x = 15;
  y = 10;
  printf("child thread (pid %d)\n addr of x = %x addr of y = %x, x=%d, y=%d\n",
         getpid(), &x, &y, x, y);
  pthread_exit(NULL);
}

main()
{
  int pid;
  pthread_t thr;


  printf("parent process (pid %d) before pthread_create\n addr of x = %x
addr of
 y = %x, x=%d, y=%d\n",
         getpid(), &x, &y, x, y);

  /* this will create a new thread that starts by calling the function
     change_variables */
  pthread_create(&thr, NULL, &change_variables, NULL);

  /* this is like wait, it waits for the thread created above to finish. */
  pthread_join(thr, NULL);

  printf("parent process (pid %d) after pthread_create\n addr of x = %x
addr of 
y = %x, x=%d, y=%d\n",
         getpid(), &x, &y, x, y);
  fflush(stdout);
} 




More information about the Techtalk mailing list