线程和进程区别:进程是任务,线程对应着cpu实体,cpu每个小核心都有一个或两个线程,进程是任务,每个进程都可以分配多个线程执行,但进程不能一直占着线程,会轮流执行,一般是按照优先级。每个核心都有独自的缓存和寄存器,通过缓存协议cpu时间轮片保证物理上同一时间段只能一个线程通过数据总线访问内存,但如果是栈区的数据可以读入缓存就能真正意义并发读取来运算,写数据的话看谁抢到权限才能写入,加了读写锁就可以并发读、依次写,写的优先级比读高,意思是cpu无论正在读或写,后面排队的线程如果前面是读,那排在后面的写操作可以插队。
虚拟地址空间:为了减少内存移动,提高利用率,隔离进程保护安全,加入了虚拟的地址,把内存分割成很多页映射存储需要经过转换才能访问实际物理内存。
栈区、全局变量区、堆区是每个进程独享的内存,因为堆区一开始不知道要使用多少内存,需要动态开辟,堆区一开始有默认大小,等到调用malloc函数时查找块从头到尾遍历完了没有空闲块就会移动堆区有效指针break以实现扩容,是内核调用,花费时间。如果用到了新的页面一个页面4k,就要分配物理页。如果指针在同一个页面里面移动就不用。堆区是隐式链表保存着内存块区域大小以及使用状态。而代码区是进程共享的,指使着如何运算,他们之间的逻辑关系,运用哪个数据进行怎样的操作,比如y=x*x+3;全部都是已知指令,但是该数据可以是地址间接引用,具体的内容是变化的,到栈区去找。
函数调用时栈中的内存的变化:先用push指令把参数压栈,然后调用call指令,call指令包含两个操作:把下一条语句的地址压栈,为了保证调用的函数退出时能找到之前函数的地址,接着跳转到函数起始地址处。调用的函数开头的指令:把上一个函数函数的栈基地址压栈,新的函数的栈基寄存器ebp赋值为旧的栈顶,最后新的栈顶减去一个数,这个数在编译时已经确定了即为该函数临时变量的总大小,扩大到足够的栈帧空间。个人感觉只需一个栈顶寄存器就能完成功能。