Operating system 在C语言中包含一个库,它放在地址空间的什么位置?
我理解地址空间是如何划分为代码、数据、堆栈和堆的。然而,对于给定的C代码,我很难将什么映射到何处 我知道: 全局变量位于数据部分。静态变量位于数据部分。局部变量位于堆栈部分。动态分配的空间位于堆部分。 我的问题是,当把一个库包含到一个程序中时,它放在地址空间的什么位置Operating system 在C语言中包含一个库,它放在地址空间的什么位置?,operating-system,shared-libraries,address-space,Operating System,Shared Libraries,Address Space,我理解地址空间是如何划分为代码、数据、堆栈和堆的。然而,对于给定的C代码,我很难将什么映射到何处 我知道: 全局变量位于数据部分。静态变量位于数据部分。局部变量位于堆栈部分。动态分配的空间位于堆部分。 我的问题是,当把一个库包含到一个程序中时,它放在地址空间的什么位置 我希望这个问题有意义。实际上,如果您有基于linux的pc,您可以通过以下方式自己检查: 创建一个简单的c应用程序,在main()中使用无限while循环 编撰 $gcc-o main./main.c-g 发射 $gdb./mai
我希望这个问题有意义。实际上,如果您有基于linux的pc,您可以通过以下方式自己检查:
Start Addr End Addr Size Offset objfile
0x400000 0x401000 0x1000 0x0 /tmp/main
0x600000 0x601000 0x1000 0x0 /tmp/main
0x601000 0x602000 0x1000 0x1000 /tmp/main
0x602000 0x623000 0x21000 0x0 [heap]
0x7ffff7a0d000 0x7ffff7bcd000 0x1c0000 0x0 /lib/x86_64-linux-gnu/libc-2.23.so
0x7ffff7bcd000 0x7ffff7dcd000 0x200000 0x1c0000 /lib/x86_64-linux-gnu/libc-2.23.so
0x7ffff7dcd000 0x7ffff7dd1000 0x4000 0x1c0000 /lib/x86_64-linux-gnu/libc-2.23.so
0x7ffff7dd1000 0x7ffff7dd3000 0x2000 0x1c4000 /lib/x86_64-linux-gnu/libc-2.23.so
0x7ffff7dd3000 0x7ffff7dd7000 0x4000 0x0
0x7ffff7dd7000 0x7ffff7dfd000 0x26000 0x0 /lib/x86_64-linux-gnu/ld-2.23.so
0x7ffff7fd4000 0x7ffff7fd7000 0x3000 0x0
0x7ffff7ff6000 0x7ffff7ff8000 0x2000 0x0
0x7ffff7ff8000 0x7ffff7ffa000 0x2000 0x0 [vvar]
0x7ffff7ffa000 0x7ffff7ffc000 0x2000 0x0 [vdso]
0x7ffff7ffc000 0x7ffff7ffd000 0x1000 0x25000 /lib/x86_64-linux-gnu/ld-2.23.so
0x7ffff7ffd000 0x7ffff7ffe000 0x1000 0x26000 /lib/x86_64-linux-gnu/ld-2.23.so
0x7ffff7ffe000 0x7ffff7fff000 0x1000 0x0
0x7ffffffdd000 0x7ffffffff000 0x22000 0x0 [stack]
0x7ffff7bcd000-0x7ffff7dd5000
中。偏移量字段-是ELF文件本身中的偏移量。我们可以使用readelf检查哪些部分对应于哪个偏移:
$ readelf -a /lib/x86_64-linux-gnu/libc-2.23.so | less
例如:
[13] .text PROGBITS 000000000001f8b0 0001f8b0
0000000000153214 0000000000000000 AX 0 0 16
这意味着
.text
部分具有偏移量0x1F800
。从上面的映射中,我们可以得出结论:主应用程序地址空间中.text部分开头的虚拟地址将是0x7ffff7bcd000+0x1f8b0
您是从一个不好的前提开始的:
我理解地址空间是如何划分为代码、数据、堆栈和堆的。然而,对于给定的C代码,我很难将什么映射到何处
地址空间不是以这种方式分区的。地址空间包含内存。用于堆栈的内存与用于堆的内存无法区分。使堆栈成为堆栈的唯一原因是,它是使用堆栈指针在应用程序中分配的。使堆成为堆的唯一原因是应用程序中有一个堆管理器。您可以从堆中分配内存,并将其分配给硬件堆栈指针,您的内存既是堆又是堆栈
这是另一个误解:
我知道:全局变量在数据部分。静态变量位于数据部分。局部变量位于堆栈部分。动态分配的空间位于堆部分
汇编程序、链接器和系统之间的区别。然而,rational汇编器允许用户定义自己的命名部分。在许多汇编程序中,我可以创建Bobs_Data_段、Freds_Data_段和Sams_Data_段,并将全局变量放入其中
对于大多数(但不是所有)编译器,程序员无法控制如何创建节。不能保证编译器会将全局变量放在一个名为“data”的节中。事实上,全局变量和静态局部变量可以放在同一节中
这样的“部分”通常只是链接器的输入。链接器将汇编程序和编译器定义的部分组合到具有公共访问属性的内存区域中。进入链接器的内容,例如,链接器中的“数据”部分,作为可执行文件中的指令,用于创建读/写页面
我的问题是,当把一个库包含到一个程序中时,它放在地址空间的什么位置
因此,现在你遇到了一个问题,即你如何努力学习事物是如何工作的。如果将进程地址空间视为内存,则可以在任何位置加载库。程序加载器读取可执行文件中的指令,并在地址空间中的任何可用位置创建具有正确属性(例如readonly/noexecute、read/write、readonly/execute)的页面
如果将地址空间视为被划分为代码、数据等,则加载库会出现问题。这让我想知道为什么学校和书籍坚持使用这些荒谬的概念进行教学