linux 进程内存基础

    一、进程虚拟空间

  linux所有的进程都运行在自己的虚拟地址空间中,每个进程都有自己的内存地址。在32位系统中,4GB的进程地址空间被分为用户空间和内核空间两个部分。用户空间占用0-3GB,内核空间范围是3-4GB。

    每个进程都会占用如下的数据段:

    1. 代码段

        用于保存可执行文件的操作指令和程序定义的常量(const,字符常量等)。为了防止代码在运行时候被其他进程修改,代码段只读。多进程也可以共享代码段。

    2. 数据段

        数据段紧挨着代码段,分为初始化数据段和未初始化数据段(BSS)。此段中存放初始化的全局变量和静态变量,未初始化的全局变量则位于bss段。

    3. 堆栈段

        堆中存放的是malloc或new分配的内存空间。堆的位置与数据段相邻。

    栈中存放的是函数中创建的临时变量,传递给函数的参数也将被保存在栈中。、

    具体分析见下例子:

#include <stdio.h>
#include <malloc.h>
#include <unistd.h>


int bss_var;
int data_var0 = 1;
int no_data_init = 8;

int main( int argc, char** argv )
{
  printf ("below are addresses of types of process's mem\n");
  printf ("Text location\n");
  printf ("\tAddress of main( Code Segment):%p\n", main);
  printf ("--------------------\n");

  int stack_var0 = 3;
  printf ("Stack Location:\n");
  printf ("\tInitial end of stack:%p\n", &stack_var0 );
  
  int stack_var1 = 3;
  printf ("\tnew end of stack:%p\n", &stack_var1 );

  printf ("--------------------\n");
  printf ("Data Location.\n");
  static int data_var1 = 4;
  printf ("\tAddress of data_var( Data Segment ):%p\n", &data_var0 );
  printf ("\tNew end of data_var( Data Segment ):%p\n", &data_var1 );
  printf ("\tAnother global initial data_var( Data Segment ):%p\n", &no_data_init );

  printf ("--------------------\n");
  printf ("BSS Location:\n");
  printf ("\tAddress of bss_var: %p\n", &bss_var );
  printf ("--------------------\n");
  
  char *b = sbrk( ( ptrdiff_t )0 );
  printf ("Heap Location:\n");
  printf ("\tInitial end of heap:%p\n", b );
  
  return 0;
}
below are addresses of types of process's mem
Text location
        Address of main( Code Segment):0x80484ac
--------------------
Stack Location:
        Initial end of stack:0xbfff7de8
        new end of stack:0xbfff7de4
--------------------
Data Location.
        Address of data_var( Data Segment ):0x804a028
        New end of data_var( Data Segment ):0x804a030
        Another global initial data_var( Data Segment ):0x804a02c
--------------------
BSS Location:
        Address of bss_var: 0x804a038
--------------------
Heap Location:
        Initial end of heap:0x89fe000

二、进程生成

进程的产生有两种方式,一个是调用系统函数fork():

 fork的返回值如果小于0,则创建进程失败,如果返回值为0,则为子进程,否则为父进程。

 另外一个为vfork(),返回值同fork。

 ps: fork()和vfork()的区别主要在,fork会复制父进程的所拥有的资源(如进程环境,内存,堆栈等)。vfork函数则不会复制父进程的相关资源,父子进程共享地址空间。子进程对虚拟空间的修改,都是在修改父进程的虚拟空间。

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


int g_var = 0;
int g_var_vfork = 10;


int main()
{
  pid_t pid;
  pid_t pid_vfork;
  int var = 1;
  int var_vfork = 11;

  printf ("--------------------\n");
  printf ("fork process start\n");
  printf ("process id: %ld\n", ( long )getpid() );
  printf ("before execute the fork system call, g_var=%d var=%d\n", g_var, var );
  
  if ( ( pid = fork() ) < 0 )
    {
      perror( "Cannot create a new process.\n" );
      return 1;
    } 
  else if ( pid == 0 )
    {
      g_var++;
      var++;
      printf ("process id : %ld, g_var=%d var=%d\n", ( long )getpid(), g_var, var );
      _exit( 0 );
    }

  printf ("process id :%ld, g_var=%d var=%d\n", ( long )getpid(), g_var, var );
  printf ("fork process stop.\n");
  printf ("--------------------\n");


  printf ("vfork process start\n");
  printf ("process id :%ld\n", ( long )getpid() );
  printf ("before vfork system call, g_var_vfork=%d var_vfork=%d\n", g_var_vfork, var_vfork );

  if ( ( pid_vfork = vfork() ) < 0 )
    {
      perror( "Cannot create a new process.\n" );
      return 1;
    }
  else if ( pid_vfork == 0 )
    {
      g_var_vfork++;
      var_vfork++;
      printf ("process id :%ld, g_var_vfork=%d, var_vfork=%d\n", ( long )getpid(), g_var_vfork, var_vfork );
      _exit( 0 );
    }
  
  printf ("process id :%ld, g_var_vfork=%d, var_vfork=%d\n", ( long )getpid(), g_var_vfork, var_vfork );
  printf ("vfork process stop.\n");

  return 0;
}
--------------------
fork process start
process id: 2496
before execute the fork system call, g_var=0 var=1
process id :2496, g_var=0 var=1
fork process stop.
--------------------
vfork process start
process id :2496
before vfork system call, g_var_vfork=10 var_vfork=11
process id : 2497, g_var=1 var=2
process id :2498, g_var_vfork=11, var_vfork=12
process id :2496, g_var_vfork=11, var_vfork=12
vfork process stop.

 三、exec函数组

  exec函数族用于对新产生进程的数据段,代码段,堆栈段进行替换。进程调用exec函数族中的函数后,其代码段会被替换成新的代码段。同时,获取新程序的数据段和堆栈段,进程的进程号保持不变。

 

 

 

 

posted @ 2013-05-31 22:28  brackenbo  阅读(346)  评论(0编辑  收藏  举报