进程篇(2: C程序的存储空间布局)--请参照本博客“操作系统”专栏

1.  C程序的存储空间布局:

C 程序由下面几个部分组成:

  • 正文段(即是代码段):
    这是由CPU执行的机器指令部分。通常,正文段是可以共享的,并常常是可读的,以防止程序因为意外原因而修改自身的代码!

  • 初始化数据段(即数据段): 它包含了程序中需要明确的赋初值的变量。

  • 非初始化数据段(bss段):在程序开始执行之前,内核将此段中的数据初始化为0或空指针。

  • 栈。自动变量以及每次函数调用时所需保存的信息都存放在此段中。每次调用函数时,返回地址以及调用者的环境信息(如某些寄存器的值)都存放在栈中。然后,最近被调用的函数在栈上为其自动和临时变量分配存储空间。这样可以实现函数的递归调用!

  • 堆。通常在堆中进行动态存储分配!

我们现在来做个实验来验证上述说法是否正确:

我们现在来编写一个Base程序,这个程序的main函数中没有自动变量,main函数的外部也没有非初始化数据;


1 #include <stdio.h>

3 int main(void)
4 {
5     return 0;
6 }

我们编译上述程序的到Base的可执行程序,然后用size命令观察各个程序段的大小:


size Base
   text       data        bss        dec        hex    filename
   1115        552          8       1675        68b    Base

下面我们在Base程序的main函数中增加一些初始化的变量:

1 #include <stdio.h>
2 int arr[1000] = {1};

3 int main(void)
4 {
7     return 0;
8 }

size Drive1

text  
data  
 bss  
 dec  
 hex filename

1115  
4568      8
  5691   163b Derive1

可见在mian函数之外增加了int
arr[1000] = {1}; 语句之后data段增加4016byte!


1 #include <stdio.h>


3 int arr[1000];

5 int main(void)
6 {
7     return 0;
8 }

结果是:


text       data        bss        dec        hex    filename
   1115        552       4032       5699       1643    Derive1

bss段增加了4024!

2. 存储器的分配:

函数原型:


NAME
       malloc, free, calloc, realloc - allocate and free dynamic memory
SYNOPSIS
       #include <stdlib.h>

       void *malloc(size_t size);
       void free(void *ptr);
       void *calloc(size_t nmemb, size_t size);
       void *realloc(void *ptr, size_t size);

函数说明:


The  malloc() function allocates size bytes and returns a pointer to the allocated memory.  The memory is not initial‐
       ized(malloc分配出来的空间并未被初始化).  If size is 0, then malloc() returns either NULL, or a unique pointer  value  that  can  later
     
 be  successfully passed to free().

       The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to mal‐
       loc(), calloc() or realloc().(free函数只能释放动态分配的空间)
 Otherwise, or if free(ptr) has already been called before, undefined
       
 behavior  occurs. If ptr is NULL, no operation is performed.

       The  calloc() function allocates memory for an array of nmemb elements of size bytes each and returns a pointer to the
       allocated memory.  The memory is set to zero.(callo函数分配出来的空间会被初始化)
 If nmemb or size is 0, then calloc() returns either
     
 NULL, or  a  unique pointer value that can later be successfully passed to free().

       The  realloc()  function  changes  the size of the memory block pointed to by ptr to size bytes.  The contents will be
       unchanged in the range from the start of the region up to the minimum of the old and new sizes.  If the  new  size  is
       larger  than  the  old size, the added memory will not be initialized.  If ptr is NULL, then the call is equivalent to
       malloc(size), for all values of size; if size is equal to zero, and ptr is not NULL, then the call  is  equivalent  to
       free(ptr).   Unless ptr is NULL, it must have been returned by an earlier call to malloc(), calloc() or realloc().  If
       the area pointed to was moved, a free(ptr) is done.

下面是《The C Programming Language》中关于内存分配管理的一个实例:

进程篇(2: C程序的存储空间布局)--请参照本博客“操作系统”专栏

时间: 2024-10-05 21:54:34

进程篇(2: C程序的存储空间布局)--请参照本博客“操作系统”专栏的相关文章

进程篇(1: 进程运行环境)--请参照本博客“操作系统”专栏

2014年5月30日  下午1:40:59 1. Unix 进程执行环境: 1.1 终止处理程序: ISO C 规定,一个程序可以登记多达32个函数,这些函数将由exit自动调用.我们称这些函数为终止处理程序(exit handler),并调用atexit函数来登记这些函数.该函数的原型如下: 1 #include <stdlib.h>2 3 int atexit(void (*function)(void)); exit调用这些终止程序的顺序与他们登记时的顺序相反(先登记后调用).同一个函数

进程篇(4: 基本进程控制:其他相关控制)--请参照本博客“操作系统”专栏

1. 更改进程的用户ID和组ID:为什么我们要更改用户ID和组ID的呢? 在UNIX系统中,特权是基于用户和组ID的.当用户需要增加特权,或要访问某个当前没有能力访问的文件时,我们需要更改自己的权限,以让新的ID具有合适的特权或访问权限.与此类似,当程序需要降低其特权或阻止对某些资源的访问时,也需要跟换用户ID或组ID;一般而言,在设计应用程序时,我们总是试图使用"最小特权"模型.依照此模型,我们的程序应当值具有为完成特定的任务所需要的最小特权. NAME getuid, geteui

进程篇(3: 基本进程控制:进程的退出)--请参照本博客“操作系统”专栏

1. exit函数: 进程的五种正常的结束方式: 在main函数中执行return语句,这等效于exit; 调用exit函数.此函数由ISO C定义,其操作包括运行各终止处理程序,然后关闭所有标准I/O流等. 调用_exit或_Exit函数,ISO C定义了_Exit函数,目的是为了为进程提供一种无需运行终止处理程序和信号处理程序而终止的方法.并不处理标准I/O流! 进程的最后一个线程在其启动例程中执行返回语句,然后该进程以终止状态0返回. 进程的最后一个线程调用pthread_exit函数.

进程篇(3: 基本进程控制)--请参照本博客“操作系统”专栏

1. 进程标识符: 每个进程都有一个非负整型表示的唯一进程ID.但进程ID可以重用,当一个进程终止之后,其进程ID就可以再次被重用了. UNIX系统中常常有一些专用的进程: ID为0的进程通常是调度进程,常常被称为交换进程(swapper),该进程是内核的一部分,它并不执行磁盘上的任何程序,因此也被称为系统进程. ID为1的进程通常是init进程,在自举过程结束后由内核调用,在比较新的版本中是/sbin/init.此进程负责在自举内核后启动一个UNIX系统.init通常读取与系统有关的初始化文件

第十五篇:C程序的存储空间布局

前言 C语言程序的执行必定需要耗费一定的资源,也就是说,程序在计算机内部的映像不可能就单单代码.本文将讲解C语言程序在计算机内部的存在方式. 程序存储空间 1. 正文段:程序的机器指令部分 2. 初始化的数据:已经明确赋值的变量的值 3. 非初始化的数据:为赋值的变量的值 4. 栈:存放自动变量以及每次函数调用时所需保存的信息 5. 堆:用来实现动态分配内存( malloc new 等函数相关 )

Linux环境编程之进程(二):程序的存储空间布局

引言: 一个写好的程序一般要存放在存储器中,那么程序中的代码.数据等各部分,是如何有规律的存放在存储器中的呢? (一) 一个存储的程序可分为五部分:正文段.初始化数据段.非初始化数据段.栈.堆.其典型的存储安排如下图: 正文段:这是由CPU执行的机器指令的部分.通常,正文段是可共享的,所以即使是频繁执行的程序在存储器中也只需要一个副本,另外正文段常常是只读的,以防止程序由于意外而修改其自身的指令. 初始化数据段:通常称为数据段,它包含了程序中需要明确地赋初值的变量. 非初始化数据段:通常称为bs

Linux下C程序的存储空间布局

一个程序本质上都是由 BSS 段.data段.text段三个组成的.可以看到一个可执行程序在存储(没有调入内存)时分为代码段.数据区和未初始化数据区三部分. BSS段(未初始化数据区):在采用段式内存管理的架构中,BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域.BSS是英文Block Started by Symbol的简称.BSS段属于静态内存分配. 数据段:在采用段式内存管理的架构中,数据段(data segment)通常是指用来存放程序中已初始化的

C程序的存储空间布局

历史沿袭至今,C程序一直由下列几部分组成: 1. 正文段.这是由CPU执行的机器指令部分.通常,正文段是可共享的,所以即使是频繁执行的程序(如文本编辑器.C编译器和shell等)在存储器中也只需有一个副本,另外,正文段常常是只读的,心防止程序由于意外而修改其指令. 2. 初始化数据段.通常将此段称为数据段,它包含了程序中需明确地赋初值的变量.例如,C程序中任何函数之外的声明: int maxcount = 99; 使此变量以其初值存放在初始化数据段中. 3. 未初始化数据段.通常将此段称为bss

操作系统之进程篇(1)

1.进程介绍: 1.1 进程模型: 进程是一个程序的实际执行,包含了程序计数器的状态,寄存器和变量等等! 程序可以看成是一个状态的序列,程序在不同时刻呈现出不同的状态,而这种状态的前后交替过程可以看成是程序的执行过程.概念上来说,每个程序有自己的虚拟CPU,但在现实中CPU在不同的进程间来回切换,又称这种切换为伪并行! 进程和程序差别看似微小,实际上却是十分精妙; 可以将计算机执行程序的过程看成一次有趣的烹饪过程.食谱就是程序,厨师就是CPU,而食材是输入,得到的输出是鲜美可口的美食. 当厨师在