《嵌入式C语言的自我修养》学习笔记
前言
对于在Linux下运行的程序,我们知道的是,在编译链接是的起始地址是相同的,并且是一个虚拟的地址,通过页表和mmu,完成虚拟地址到物理地址之间的转换,内存读写权限管理等功能,每一个进程都有页表,用来记录这些映射关系。具体是怎么搞得,可以看其他的文章。
可执行文件在运行时,加载器将其不同的section加载到对应的地方。
图1
图一就比较清晰的显示了内核空间与用户空间。32位的处理器,地址空间可达4G,每一个进程都有4G的虚拟地址空间。0-3G被用户占着,3-4G被内核占着。应用程序内有权限访问内核空间,只能通过中断或者系统调用来访问。,下图描绘的很清楚。
stack 栈是什么?在数据结构中,我们接触到了栈,FILO,先入后出。就和我经常喝的泡腾片一样,在生产装瓶的新进去的我最后喝。在了解程序的运行时,之前的初始化,其中就有包含栈的初始化。这里必须要提到的一点是栈指针sp,出栈栈的时候,先让元素蹦出来,然后在移动栈指针指向当前的栈顶,入栈则相反。
每个进程栈的大小可以通过ulimt -s 来查看大小。linux 默认是8M。这块可以看看线程大小和进程的关系。接下来,主要看下在不同情况下栈的使用。
1.函数调用可以知道的是,arm 的栈是从高地址向低地址生长的。一个函数中定义的局部变量,以及传递的实参都是保存在栈空间中的,每一个函数都有一个栈帧,,作为栈空间。每一个栈帧有两个寄存器FP和SP,FP指向栈底,sp则是栈顶。
函数的调用
2.参数传递参数传递时,arm一般时从右往左压栈,且当参数大于4个时,前四个放到R0 -R3,后面的依次压入栈中保存。
3.实参形参形参只是在函数调用时在函数栈帧中申请存储单元,用来接收传进来的实参数值,实参和形参存储在栈的不同内存单元上,因此,在函数内部,改变形参的值不会影响实参。
4.栈与作用域当了解参数传递和实参形参后,这个问题比较明确,局部变量作用域就是这个函数,这函数完成后,栈帧也完成。
5.栈溢出攻击原理如数组越界。



