目录
一、简述堆栈溢出
堆栈溢出就是不顾堆栈中分配的局部数据块大小,向该数据块中写入了过多的数据,导致数据越界。常指调用堆栈溢出,本质上是一种数据结构的满溢情况。堆栈溢出可以理解为两个方面:堆溢出和栈溢出。
1、堆溢出
比如不断的new一个对象,一直创建新的对象,而不进行释放,最终导致内存不足。将会报错:OutOfMemory Error。
2、栈溢出
一次函数调用中,栈中将被依次压入:参数、返回地址等,而方法如果递归比较深或进去死循环,就会导致栈溢出。将会报错:StackOverflow Error。
二、简述操作系统中malloc的实现原理
malloc底层实现原理:当开辟的空间小于128KB是,调用brk()函数;当开辟的空间大于128KB时,调用mmap()。malloc采用的是内存池的管理方式,以减少内存碎片。先申请大块内存作为堆区,然后将堆区分为多个内存块,当用户申请内存时,直接从堆区分配一块合适的空闲块。采用隐式链表将所有空闲块,每一个空闲块记录了一个未分配的、连续的内存地址。
三、简述进程空间从高位到低位都有哪些
如下图,从高地址到低地址,一个程序由命令行参数和环境变量、栈、文件映射区、堆、BSS段、数据段、代码段组成。
1、命令行参数和环境变量;
2、栈区:存储局部变量、函数参数值。栈从高地址向低地址增长,是一块连续的空间。
3、文件映射区:位于堆和栈之间。
4、堆区:动态申请内存用,对从低地址向高地址增长。
5、BSS段:存放程序中未初始化的全局变量和静态变量的一块内存区域。
6、数据段:存放程序中已经初始化的全局变量和静态变量的一块内存区域。
7、代码段:存放程序执行代码的一块内存区域。只读,代码段的头部还会包含一些只读的常数变量。
四、32位系统能访问4GB以上的内存吗
正常情况下不可以。
原因:计算机使用二进制,每位数只有0或1两个状态,32位正好是2的32次方,刚好是4GB。所以大于4GB的就没有办法表示了,而在32位系统中,因为其它原因还需要占用一部分空间,所以内存只能识别3GB多,要使用4GB以上就只能换64位的操作系统了。
但是使用PAE技术可以实现32位系统访问4GB以上的内存。
PAE(Physical Address Extension)技术最初是为了弥补32位地址在PC服务器应用上的不足而推出的。我们知道,传统的IA32架构只有32位地址总线,只能让系统容纳不超过4GB的内存,这么大的内存,对于普通的桌面应用应该说是足够用的。但是,对于服务器来说,还是不足,因为服务器可能要承载很多同时运行的应用。PAE技术将地址扩展到了36位,这样,系统就能够容纳2^36=64GB的内存。
五、简述并发和并行
1、并发:对于单个CPU,在一个时刻只有一个进程在运行,但是线程的切换时间则减少到纳秒数量级,多个任务不停来回快速切换。
2、并行:对于多个CPU,多个进程同时运行。
3、两者区别:通俗来说,它们虽然都说是“多个进程同时运行”,但是它们的“同时”不是一个概念。并行的“同时”是同一时刻可以多个任务在运行(处于running),并发的“同时”是经过不同线程快速切换,使得看上去是多个任务同时都在运行的现象。
六、简述进程、线程、协程及三者的区别
1、进程:程序是指令、数据及其组织形式的描述,而进程则是程序的运行实例,包括程序计数器、寄存器和变量的当前值。
2、线程:微进程,一个进程里更小粒度的执行单元。一个进程里包含多个线程并发执行任务。
3、协程:微线程,在子程序内部执行,可在子程序内部中断,转而执行别的子程序,在适当的时候再返回来接着执行。
4、线程与进程的区别:
①一个线程从属于一个进程,一个进程可以包含多个线程;
②一个线程挂掉,对应的进程挂掉。一个进程挂掉,不会影响其它进程;
③进程是系统资源调度的最小单位,线程是CPU调度的最小单位;
④进程系统开销显著大于线程开销,线程需要的系统资源更少;
⑤进程在执行时拥有独立的内存单元,多个线程共享进程的内存,如代码段、数据段、扩展段,但每个线程拥有自己的栈段和寄存器组;
⑥进程切换时需要刷新TLB并获取新的地址空间,然后切换硬件上下文和内核栈,线程切换时只需要切换硬件上下文和内核栈;
⑦通信方式不一样;
⑧进程适用于多核、多机分布,线程适用于多核。
5、线程与协程的区别:
①协程执行效率极高。协程直接操作栈基本没有内核切换的开销,所以上下文的切换非常快,切换开销比线程更小;
②协程不需要多线程的锁机制,因为多个协程从属于一个线程,不存在同时写变量冲突,效率不线程高;
③一个线程可以有多个协程。