zoukankan      html  css  js  c++  java
  • 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函数族中的函数后,其代码段会被替换成新的代码段。同时,获取新程序的数据段和堆栈段,进程的进程号保持不变。

  • 相关阅读:
    微博回调接口
    vue获取微博授权URL
    生成微博授权url接口
    微博账号注册
    电脑程式直接打开文件
    关于 transparent rgba display:none; opacity visiblity 关于em
    定位及部分属性
    盒模型以及部分小笔记
    htm基础知识,css的链入以及标签分类。
    JS函数01
  • 原文地址:https://www.cnblogs.com/bracken/p/3111570.html
Copyright © 2011-2022 走看看