获取进程段的开始和结束 C/C++

6 c unix linux memory-management system

我需要获取以下流程段的开始和结束地址:代码、数据、堆栈、环境。我了解它如何位于内存中,但不知道如何使用 api 调用或其他方式获取它。我找到了如何使用此代码开始某些段

#include <stdio.h>

int temp_data = 100;
static int temp_bss;

void print_addr ( void )
{
        int local_var = 100;
        int *code_segment_address = ( int* ) &print_addr;
        int *data_segment_address = &temp_data;
        int *bss_address = &temp_bss;
        int *stack_segment_address = &local_var;

        printf ( "\nAddress of various segments:" );
        printf ( "\n\tCode Segment : %p" , code_segment_address );
        printf ( "\n\tData Segment : %p" , data_segment_address );
        printf ( "\n\tBSS : %p" , bss_address );
        printf ( "\n\tStack Segment : %p\n" , stack_segment_address );

}

int main ( )
{
        print_addr ();
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

但我不知道如何找到每个段的结尾。我唯一的想法是一段的结束是另一段的开始。请解释我如何使用 C 和 linux API 来做到这一点。

Bas*_*tch 7

我不确定数据或堆段是否定义明确且唯一(特别是在多线程应用程序中,或者只是在使用动态库的应用程序中,包括libc.so)。换句话说,不再有任何明确定义的文本、数据或堆段的开始和结束,因为今天一个进程有许多这样的段。所以你的问题在一般情况下甚至没有意义。

大多数malloc实现使用mmap(2)并且munmap远不止于此sbrk

您应该阅读更多关于proc(5) 的信息。特别是,您的应用程序可以读取/proc/self/maps(或/proc/1234/mapspid 1234 的进程)或/proc/self/smaps;尝试cat /proc/self/maps考虑使用fopen(3) on "/proc/self/maps"(然后在fgetsor上循环readline,最后和快速fclose)。也许dladdr(3)可能是相关的。

您还可以读取程序的ELF头文件,例如/proc/self/exe. 另见readelf(1)objdump(1) & execve(2) & elf(5) & ld.so(8) & libelf。另请阅读Levine 的Linkers & Loaders一书和Drepper 的论文:如何编写共享库

另请参阅相关问题的答案(以及该问题)。请注意,最近的 Linux 系统具有ASLR,因此在同一环境中运行同一程序的两个相似进程的地址布局会有所不同。

还尝试strace(1)一些简单的命令或您的程序。您将更多地了解相关的syscalls(2)。另请阅读高级 Linux 编程

  • @ketazafor 在现代 Linux 系统上不再有文本和数据段这样的东西。tex 分布在多个共享库中,数据分散在来自多个 `mmap()` 调用的地址空间中。你想要的根本就不存在了。 (4认同)
  • 不再有单个代码段。在终端中运行 `cat /proc/self/maps` 并尝试理解其输出。 (3认同)
  • @ketazafor:所有相关信息都在这个答案中。细节有待你去发现和了解。 (2认同)