腾讯——面经3
虚拟内存怎么到物理内存的?
当每个进程创建的时候,内核会为进程分配4G的虚拟内存,当进程还没有开始运行时,这只是一个内存布局。实际上并不立即就把虚拟内存对应位置的程序数据和代码(比如.text .data段)拷贝到物理内存中,只是建立好虚拟内存和磁盘文件之间的映射就好(叫做存储器映射)。这个时候数据和代码还是在磁盘上的。当运行到对应的程序时,进程去寻找页表,发现页表中地址没有存放在物理内存上,而是在磁盘上,于是发生缺页异常,于是将磁盘上的数据拷贝到物理内存中。可以认为虚拟空间都被映射到了磁盘空间中(事实上也是按需要映射到磁盘空间上,通过mmap,mmap是用来建立虚拟空间和磁盘空间的映射关系的)
juc的常见同步工具类?
semaphore:信号量,通常用来限制线程可以同时访问的资源数量
CountDownLatch:主要是在完成一组正在其他线程中执行的操作之前,允许一个或多个线程一直阻塞,不支持重用
CyclicBarrier:允许一组线程互相等待,直到到达某个公共的屏障点。并且支持重用
mysql长事务?
长事务是运行时间比较长,长时间未提交的事务,这种事务往往会造成大量的阻塞和锁超时,容易造成主从延迟,应该尽量避免
解决办法:尽量避免一次处理太多数据,对长事务进行拆分,这样当事务发生错误时,只需要回滚一部分数据就行了
查看tcp连接数的命令?
netstat -nat | grep 8080 | wc -l
Linux中的"|"?
管道,把前一个命令原本要输入到屏幕的数据当做后一个命令的标准输入
如何定位内存泄漏?
先用jmap生成堆转储快照(dump文件),然后用mat等分析工具来找出占用超出预期的嫌疑对象,再去分析嫌疑对象和其他对象的引用关系,这时候可以去分析对应的源代码找出原因了。
jvm调优的方向?
1.系统出现异常后去看看是否是堆内存溢出,栈内存溢出,方法区内存溢出等
2.去看下GC日志,查看gc的频率,时间
3.查看线程快照(jstack),看下是否出现了死循环,死锁
4.当内存溢出时,用jmap分析内存使用情况
运输层和网络层的职能?
运输层的作用:一方面为上层应用层提供进程的端到端的通信服务一方面屏蔽了下面网络层的细节,在逻辑上好像两个进程实体之间存在一条端到端的逻辑通信通道。功能:复用和分用
网络层:处理跨越多个网络的机器之间的路由问题,同时也管理网络名称和地址,以便于解决路由问题。它处理从发送方到接收方的数据移动,必要时还能把数据重新打包到较小的数据容器中,处理和识别发送方和接收方的位置问题。功能:mtu分片,寻址,路由
多态的实现机制?
父类或者接口的引用变量可以指向子类或具体实现类的实例对象,由于程序调用方法是在运行期才动态绑定的,所以引用变量所指向的具体实例对象在运行期才确定。
dns的域名解析过程?
1.首先在浏览器中查询是否缓存了dns的记录
2.如果浏览器中没有的话会去操作系统中查找
3.操作系统中也没有的话就回去路由缓存中查找
4.还是没有的话就去isp的dns服务器中查询请求,如果还是找不到,就会像根服务器发出请求,进行递归查询
jmm内存模型?
主内存存储共享变量,然后每个线程都有自己的本地内存,当要对共享变量进行操作时,就会将主内存中的共享变量复制一份副本到自己的本地内存中,然后对本地内存中的变量操作完成再刷新到主内存中
线程间通信的步骤:首先线程A将本地内存中的共享变量刷新到主内存中去,然后线程B到主内存中去读取已经更新过的那个共享变量
主内存:方法区+堆
工作内存:虚拟机栈+本地方法栈+程序计数器
sed,grep命令?
sed是一个管道命令,主要用来对数据行进行替换,删除,新增和选取等操作
grep主要是用来进行搜索的
mysql的体系结构?
自顶向下分别是:网络连接层,服务层,存储引擎层,系统文件层
网络连接层:负责连接管理,授权认证,安全,服务器上维护了一个线程池
服务层:进行查询解析,sql执行计划分析与优化,还有查询缓存等
存储引擎层:负责数据的存储与提取,服务器中的查询执行引擎通过api与存储引擎进行通信,通过接口屏蔽了不同存储引擎之间的差异
系统文件层:主要是将数据库的数据存储在文件系统智商,并完成与存储引擎的交互
jvm调优参数设置:
-Xms:设置jvm启动时堆内存的初始化大小
-Xmx:设置堆内存的最大值
-Xmn:设置年轻代的空间大小
-XX:NewRatio:设置老年代和年轻代的比例大小
-XX:+UseSerialGC:年轻代用串行垃圾收集器
ping命令的基本原理?
icmp协议,发送主机发送echo请求,接受主机回复echo报文
死锁的解决方案?
预防死锁:
1.资源一次性分配,这样可以破坏请求条件
2.如果某个进程获得了部分资源,但是得不到其他资源,则释放已经占有的资源(破坏不可剥夺条件)
3.系统给没类资源赋予一个编号,每一个进程按编号递增的顺序请求资源(破坏循环等待条件)
代码层面的解决:按照顺序获得锁,获取锁的时间超时则放弃获取锁
避免死锁:
银行家算法:当进程请求一组资源时,假设同意该请求,从而改变了系统的状态,然后确定其结果是否还处于安全状态,如果是则同意该请求,不是的话则阻塞该进程直到同意该请求后系统状态仍是安全状态
死锁检测:用jstack命令来追踪堆栈,生成java虚拟机当前时刻的线程快照,然后去查看是否出现了死锁,死循环
红黑树和b+树?
红黑树其实就是不那么平衡的AVL树,虽然红黑树舍弃了一定的平衡性,导致读取效率没AVL树高,但是更有利于维护,每次插入和删除的平均旋转次数远小于AVL树
红黑树一般用在内存中进行排序,b+树多用于磁盘上进行排序
b+树的磁盘io代价更低:它的非叶子结点没有数据,索引比较小,避免了树形结构不断的向下查找,可以降低io次数
并且b+树的查询效率更加稳定,每次查询都是到达叶子节点,所以效率稳定
而且b+树只要遍历叶子结点就能实现整棵树的遍历,而红黑树需要中序遍历,所以b+树遍历更方便
多进程和多线程的区别?
多进程的数据共享复杂,同步简单,占用内存多,切换复杂,cpu利用率低,进程间不会互相影响
多线程共享数据简单,同步复杂,占用内存少,cpu利用率高,一个线程挂掉会导致整个进程挂掉
为什么进程切换的开销比线程大?
每个进程都有自己的内存空间,所以进程间切换是内存空间的切换,而多个线程共享的是进程的内存空间,是在一个内存空间里进行切换的。
进程切换时需要切换页表,而且经常伴随着页调度,而线程只需要保存线程上下文信息就行了
大量close_wait?
被动关闭连接的一方在已经接收到主动方发送的fin后,但是自己还没发送fin给对方,这个时候连接处于close_wait状态,如果close_wait时间长或者有大量的clost_wait,可能是某种情况下对方关闭了socket连接,但是我方并没有关闭连接,也就是没有发送ack信号,于是这个资源就一直被程序占用
linux怎么创建进程和线程的?
可以通过fork和vfork来创建进程,fork多一次内存拷贝,vfork比较麻烦还有风险。目前内核对fork做了写时拷贝优化,也就是说对于fork只有当你需要改变的时候才从父进程中拷贝到子进程中
线程的创建:进程之间共享代码段,文件描述符,信号处理,全局变量的话就称为线程,如果不共享就是进程,线程创建是通过clone或者pthread_create来创建的
进程的管道通信方式的管道种类?
匿名管道:在内核中申请一块固定大小的缓冲区,程序拥有写入和读取的权利,一般使用fork函数实现父子进程的通信
命名管道:在内河中申请一块固定大小的缓冲区,程序拥有写入和读取的权利,没有血缘关系的进程也可以进程间通信
特点:面向字节流,生命周期和内核相同,自带同步互斥机制,半双工,单向通信
Linux文件权限有哪些?
r:可读 4
w:可写 2
x:可执行 1
777:用户组,用户,其他都能够读,写和执行
文件权限的修改使用chmod
http的格式?
1.请求行:请求方法 ur l协议/版本
2.请求头
3.状态行:协议版本,状态代码,状态描述
4.响应正文:服务器返回的资源的内容
5.响应头
ip地址是多少位的?为什么?
ip地址是32位的,首先必须是8的倍数,这样方便计算机处理,32的话能够表示40亿台主机,当时认为就够用了,但是现在发现其实是不够用的,所以ipv6才使用的128位