进程概述和内存分配

本文介绍了进程的内存布局,包括文本段、初始化数据段、未初始化数据段、栈段和堆段。详细讲解了如何获取进程的内存段结束位置、虚拟内存页面大小、命令行参数和程序名。此外,探讨了volatile关键字的作用,强调其防止编译器优化的特性。还讨论了内存分配,如brk和sbrk的作用,以及malloc的调试工具和内存对齐的重要性。最后,提到了在栈上分配内存的alloca函数。
摘要由CSDN通过智能技术生成

进程概述和内存分配

本文是作者阅读TLPI(The Linux Programer Interface的总结),为了突出重点,避免一刀砍,我不会过多的去介绍基本的概念和用法,我重点会去介绍原理和细节。因此对于本文的读者,至少要求读过APUE,或者是实际有写过相关代码的程序员,因为知识有点零散,所以我会尽可能以FAQ的形式呈现给读者。

进程

一个进程的内存布局是什么样的?

每个进程所所分配的内存由很多部分组成,通常我们称之为段,一般会有如下段:

  • 文本段 包含了进程执行的程序机器语言指令,文本段具有只读属性,以防止进程通过错误指针意外修改自身的指令。
  • 初始化数据段包含了显示初始化的全局变量和静态变量,当程序加载到内存时,从可执行文件中读取这些变量的值
  • 未初始化数据段包含了未进行显式初始化的全局变量和静态变量,程序启动之前,系统将本段内所有的内存初始化为0。
  • 栈段是一个动态增长和收缩的段,由栈帧组成,系统会为每个当前调用的函数分配一个栈帧,栈帧中存储了函数的具备变量,实参,和返回值。
  • 堆段是可在运行时动态进程内存分配的一块区域,堆顶端称作program break
    这里写图片描述

注: 为什么要区分初始化数据段,和未初始化数据段呢?,未初始化数据段简称为BSS段,有何含义BSS全称为Block Started by Symbol,其主要原因在于程序在磁盘上存储时,没有必要为未经初始化的变量分配存储空间,相反,可执行文件只需要记录未初始化数据段的位置和所需大小即可。直到运行时才分配内存空间。通过size命令可以显示可执行文件的文本段,初始化数据段,未初始化数据段的段大小信息。

如何知道进程的文本段,初始化数据段和非初始化数据段的结束位置?

​   大多数UNIX实现中C语言编程环境提供了三个全局符号:etext,edata,end,可在程序内使用这些符号获取文本段,初始化数据段,未初始化数据段结尾处下一字节的地址。代码如下:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
extern char etext,edata,end;
int main()
{
    printf("%p\n",&etext);
    printf("%p\n",&edata);
    printf("%p\n",&end);
}

如何获取虚拟内存的页面大小?

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

int main()
{
    printf("page-size:%d\n",sysconf(_SC_PAGESIZE));
}

如何读取任一进程的命令行参数和程序名?

​   通过读取proc/PID/cmdline可以得到任一进程的命令行参数信息,如果想获取程序本身的命令行参数,可以使用proc/self/cmdline来读取,对于如何获取进程的程序名有如下两种方法:

  • 读取/proc/self/exe的符号链接内容,这个文件会通过符号链接到真正的可执行文件路径,是绝对路径,通过readlink可以读取其中链接的绝对路径名称
#include <stdio.h>
#include <unistd.h>
#include <string.h>
char * get_program_path(char *buf,int count);
char * get_program_name(char *buf,int count);

int main()
{
    //程序测试
    char buf[1024];
    bzero(buf,sizeof(buf));
    //打印路径名称
    printf("%s\n",get_program_path(buf,sizeof(buf)));
    bzero(buf,sizeof(buf));
    //打印程序名称
    printf("%s\n",get_program_name(buf,sizeof(buf)));

}

/*
 * 获取程序的路径名称
 */
char * get_program_path(char *buf,int count)
{
    int i=0;
    int retval = readlink("/proc/self/exe",buf,count-1);
    if((retval < 0 || retval >= count - 1))
    {
        return NULL;
    }
    //添加末尾结束符号
    buf[retval] = '\0';
    char *end = strrchr(buf,'/');
    if(NULL == end)
        buf[0] = '\0';
    else
        *end = '\0';
    return buf;
}

/*
 * 获取这个程序的文件名,其实这有点多余,argv[0] 
 * 就代表这个执行的程序文件名
 */
char * get_program_name(char *buf,int count)
{
    int retval = readlink("/proc/self/exe",buf,count-
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值