Network
cookie和session
cookie由服务器生成,发送给浏览器,浏览器把cookie以kv形式保存到某个目录下的文本文件内,下一次请求同一网站时会把该cookie发送给服务器。由于cookie是存在客户端上的,所以浏览器加入了一些限制确保cookie不会被恶意使用,同时不会占据太多磁盘空间,所以每个域的cookie数量是有限的。
Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。
Session和Cookie的区别?
1、数据存储位置:cookie数据存放在客户的浏览器上,session数据放在服务器上。
2、安全性:cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑到安全应当使用session。
3、服务器性能:session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie。
4、数据大小:单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
5、信息重要程度:可以考虑将登陆信息等重要信息存放为session,其他信息如果需要保留,可以放在cookie中。
get和post请求的区别
GET POST 后退按钮/刷新 无害 数据会被重新提交(浏览器应该告知用户数据会被重新提交)。 书签 可收藏为书签 不可收藏为书签 缓存 能被缓存 不能缓存 编码类型 application/x-www-form-urlencoded application/x-www-form-urlencoded 或 multipart/form-data。为二进制数据使用多重编码。 历史 参数保留在浏览器历史中。 参数不会保存在浏览器历史中。 对数据长度的限制 是的。当发送数据时,GET 方法向 URL 添加数据;URL 的长度是受限制的(URL 的最大长度是 2048 个字符)。 无限制。 对数据类型的限制 只允许 ASCII 字符。 没有限制。也允许二进制数据。 安全性 与 POST 相比,GET 的安全性较差,因为所发送的数据是 URL 的一部分。
在发送密码或其他敏感信息时绝不要使用 GET !
POST 比 GET 更安全,因为参数不会被保存在浏览器历史或 web 服务器日志中。 可见性 数据在 URL 中对所有人都是可见的。 数据不会显示在 URL 中。 对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);
而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。
TCP/IP分为几层
重定向转发区别
重定向resp,请求转发req
请求转发:request.getRequestDispatcher("/test.jsp").forword(request,response);
重定向:response.sendRedirect("/test.jsp");
1、请求次数:重定向是浏览器向服务器发送一个请求并收到响应后再次向一个新地址发出请求,转发是服务器收到请求后为了完成响应跳转到一个新的地址;重定向至少请求两次,转发请求一次;
2、地址栏不同:重定向地址栏会发生变化,转发地址栏不会发生变化;
3、是否共享数据:重定向两次请求不共享数据,转发一次请求共享数据(在request级别使用信息共享,使用重定向必然出错);
4、跳转限制:重定向可以跳转到任意URL,转发只能跳转本站点资源;
5、发生行为不同:重定向是客户端行为,转发是服务器端行为;
OSI七层模型
路由器、集线器、交换机
http://www.nowamagic.net/academy/detail/72150314
集线器属于OSI的第一层物理层设备,交换机属于OSI的第二层数据链路层设备。路由器一开始就设计工作在OSI模型的网络层(第三层),可以得到更多的协议信息,路由器可以做出更加智能的转发决策。
交换机是利用物理地址或者说MAC地址来确定转发数据的目的地址。路由器是利用不同网络的ID号(即IP地址)来确定数据转发的地址。
状态码:302/301和302的区别,见到这些错误之后的排查思路
https://www.runoob.com/http/http-status-codes.html
- 200 - 请求成功
- 301 - 资源(网页等)被永久转移到其它URL
- 404 - 请求的资源(网页等)不存在
- 500 - 内部服务器错误
304:缓存( https://www.cnblogs.com/weibo806/p/5377275.html) F5 刷新 访问 304
301 Moved Permanently 永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替 302 Found 临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI
TCP和UCP协议
UDP 是否连接 无连接 面向连接 是否可靠 不可靠传输,不使用流量控制和拥塞控制 可靠传输,使用流量控制和拥塞控制 连接对象个数 支持一对一,一对多,多对一和多对多交互通信 只能是一对一通信 传输方式 面向报文 面向字节流 首部开销 首部开销小,仅8字节 首部最小20字节,最大60字节 适用场景 适用于实时应用(IP电话、视频会议、直播等) 适用于要求可靠传输的应用,例如文件传输
TCP是怎么进行流量控制的? 答:滑动窗口追问:滑动窗口是由什么决定的?
https://blog.csdn.net/qq_26896213/article/details/84594060
流量控制就是让发送方的发送速率不要太快,要让接收方来的及接收。
原理是通过确认报文中窗口字段来控制发送方的发送速率,发送方的发送窗口大小不能超过接收方给出窗口大小。
拥塞控制:防止过多的数据注入到网络中,这样可以使网络中的路由器或链路过载。
TCP进行拥塞控制的算法有四种,即慢开始,拥塞避免,快重传,快恢复。
慢开始的“慢”指的是,初始cwnd=1(此时表示的是报文段的个数,而不是真正传输时使用的字节流)
拥塞避免算法的思路是让拥塞窗口cwnd缓慢增大,即每经过一个往返时间RTT就把发送方的拥塞窗口cwnd+1,而不是加倍
快重传
快恢复
发送方让自己的发送窗口等于拥塞窗口,拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化。
为何三次握手?四次挥手2MSL
【问题1】为什么连接的时候是三次握手,关闭的时候却是四次握手?
答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。【问题2】为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
答:虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。
第一次发syn:调用connect方法建立连接
socket是tcp协议之上的接口。jvm提供了与os对应的socket类。socket调用sys_connect来调用tcp_connect方法
http报文结构:https://www.cnblogs.com/ldq2016/p/9055933.html
输入url然后回车发生了什么:https://www.cnblogs.com/jin-zhe/p/11586327.html
URL 解析:首先判断你输入的是一个合法的 URL 还是一个待搜索的关键词,并且根据你输入的内容进行自动完成、字符编码等操作。
DNS 查询
- TCP 连接
- 处理请求
假如服务器配置了 HTTP 重定向,就会返回一个
301
永久重定向响应,浏览器就会根据响应,重新发送 HTTP 请求(重新执行上面的过程)。
- 接受响应
浏览器接收到来自服务器的响应资源后,会对资源进行分析。
首先查看 Response header,根据不同状态码做不同的事(比如上面提到的重定向)。
接下来,根据响应资源里的 MIME[3] 类型去解析响应内容(比如 HTML、Image各有不同的解析方式)。
- 渲染页面
http1.1的请求队列相对于http1.0设计的好处
https://www.cnblogs.com/heluan/p/8620312.html
HTTP1.0最早在网页中使用是在1996年,那个时候只是使用一些较为简单的网页上和网络请求上,而HTTP1.1则在1999年才开始广泛应用于现在的各大浏览器网络请求中,同时HTTP1.1也是当前使用最为广泛的HTTP协议。 主要区别主要体现在:
缓存处理,在HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准,HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。
带宽优化及网络连接的使用,HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。
错误通知的管理,在HTTP1.1中新增了24个错误状态响应码,如409(Conflict)表示请求的资源与资源的当前状态发生冲突;410(Gone)表示服务器上的某个资源被永久性的删除。
Host头处理,在HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递主机名(hostname)。但随着虚拟主机技术的发展,在一台物理服务器上可以存在多个虚拟主机(Multi-homed Web Servers),并且它们共享一个IP地址。HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个错误(400 Bad Request)。
长连接,HTTP 1.1支持长连接(PersistentConnection)和请求的流水线(Pipelining)处理,在一个TCP连接上可以传送多个HTTP请求和响应,减少了建立和关闭连接的消耗和延迟,在HTTP1.1中默认开启Connection: keep-alive,一定程度上弥补了HTTP1.0每次请求都要创建连接的缺点。
http2.0 多路复用(MultiPlexing),即连接共享,即每一个request都是是用作连接共享机制的。一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的 id将request再归属到各自不同的服务端请求里面。
http会被坏人拦截吗
http协议属于明文传输协议,交互过程以及数据传输都没有进行加密,通信双方也没有进行任何认证,通信过程非常容易遭遇劫持、监听、篡改,严重情况下,会造成恶意的流量劫持等问题,甚至造成个人隐私泄露(比如银行卡卡号和密码泄露)等严重的安全问题。
比如常见的,在http通信过程中,“中间人”将广告链接嵌入到服务器发给用户的http报文里,导致用户界面出现很多不良链接; 或者是修改用户的请求头URL,导致用户的请求被劫持到另外一个网站,用户的请求永远到不了真正的服务器。这些都会导致用户得不到正确的服务,甚至是损失惨重。
DNS请求阶段的具体协议:udp
应用层和协议
DNS、HTTP、SMTP、POP3、IMAP、FTP
·SMTP 简单邮件传输协议 用于发邮件
·POP3 邮局协议版本3 用于收邮件
·IMAP 互联网邮件访问协议 类似POP3,功能更多
·FTP:文件传输协议 提供可靠的文件传输服务,具有认证、权限服务
·TFTP:简单文件传输协议 不可靠、不具有认证、权限服务(常用于网络设备的配置文件和系统文件传输)
CSRF攻击:https://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html
要让客户访问虚假网站,然后浏览器默认会带上cookie,虚假网站再直接向正规网站提交,伪造用户请求)
1.登录受信任网站A,并在本地生成Cookie。
2.在不登出A的情况下,访问危险网站B。
CSRF攻击是源于WEB的隐式身份验证机制!WEB的身份验证机制虽然可以保证一个请求是来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的!
服务端的CSRF方式方法很多样,但总的思想都是一致的,就是在客户端页面增加伪随机数。
(1).Cookie Hashing(所有表单都包含同一个伪随机值):(2).验证码 (3).One-Time Tokens(不同的表单包含一个不同的伪随机值)
Http和Https的区别:http://blog.sina.com.cn/s/blog_603fcfae0102xjeh.html
https://blog.csdn.net/wnx_52055/article/details/8835531
1. https协议需要到CA申请证书,大多数情况下需要一定费用
2. Http是超文本传输协议,信息采用明文传输,Https则是具有安全性SSL加密传输协议
3. Http和Https端口号不一样,Http是80端口,Https是443端口
4. Http连接是无状态的,而Https采用Http+SSL构建可进行加密传输、身份认证的网络协议,更安全。
5. Http协议建立连接的过程比Https协议快。因为Https除了Tcp三次握手,还要经过SSL握手。连接建立之后数据传输速度,二者无明显区别。
http默认端口为80,https默认端口为443
HTTPS的缺点:
1.HTTPS协议握手阶段比较费时,会使页面的加载时间延长近50%,增加10%到20%的耗电;
2.HTTPS连接缓存不如HTTP高效,会增加数据开销和功耗,甚至已有的安全措施也会因此而受到影响;
3.SSL证书需要钱,功能越强大的证书费用越高,个人网站、小网站没有必要一般不会用。
4.SSL证书通常需要绑定IP,不能在同一IP上绑定多个域名,IPv4资源不可能支撑这个消耗。
5.HTTPS协议的加密范围也比较有限,在黑客攻击、拒绝服务攻击、服务器劫持等方面几乎起不到什么作用。最关键的,SSL证书的信用链体系并不安全,特别是在某些国家可以控制CA根证书的情况下,中间人攻击一样可行。
Https建立连接的过程/SSL握手和工作流程,
https://blog.csdn.net/hherima/article/details/52469674
https://www.pianshen.com/article/84731649426/
https://www.cnblogs.com/jjzd/p/9346260.html
客户与服务器协商协议版本,会话ID,密码组,压缩方法,交换随机数;
服务器给客户发送服务器证书,请求客户证书(可选);
如果要求证书,客户发送该证书;
改变密码组,完成握手。
- 客户使用https的URL访问Web服务器,要求与Web服务器建立SSL连接。
- Web服务器收到客户端请求后,会将网站的证书信息(证书中包含公钥)传送一份给客户端。在客户端收到证书后,对证书的证书所有者、有效期等信息进行一一校验。
- 客户端根据双方同意的安全等级选择加密算法和密钥,然后利用公钥将会话密钥加密,并传送给服务端。
- Web服务器利用自己的私钥解密出会话密钥。
- 客户端以对称加密的方与向Web服务器发送请求;
- 服务端收到后,利用对称密钥给客户端回复请求内容;
服务器启动监听端口为1234的应用,客户端无法连接。如何排错
ICMP这个协议他位于网络的第几层知道吧
ICMP协议是一种面向无连接的协议,用于传输出错报告控制信息。它属于网络层协议,主要用于在主机与路由器之间传递控制信息,包括报告错误、交换受限控制和状态信息等。
那链路层的协议有哪些啊
SSH/SSL的区别
ssl是通讯链路的附加层。可以包含很多协议。https, ftps, …..
ssh只是加密的shell,最初是用来替代telnet的。通过port forward,也可以让其他协议通过ssh的隧道而起到加密的效果。
https://zhuanlan.zhihu.com/p/138679729
对称加密和非对称加密,md5的原理
DNS劫持
rpc
这里 user 就是 client 端,当 user 想发起一个远程调用时,它实际是通过本地调用user-stub。user-stub 负责将调用的接口、方法和参数通过约定的协议规范进行编码并通过本地的 RPCRuntime 实例传输到远端的实例。远端 RPCRuntime 实例收到请求后交给 server-stub 进行解码后发起本地端调用,调用结果再返回给 user 端。
http是有状态还是无状态?是有连接还是无连接?
无状态服务器是指一种把每个请求作为与之前任何请求都无关的独立的事务的服务器。
HTTP服务器就是一个例子。以URL形式提交的客户端请求可能包含cookies等带状态的数据,这些数据完全指定了所需的文档,而不需要其他之前请求的上下文或内存。
无连接的含义:是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
无状态、无连接(可以有连接)
我们可知,在网络协议中,我们称TCP为一个有状态的传输层通信协议,而UDP则不是;IP是无状态的。
操作系统
多线程多进程
https://blog.csdn.net/m0_46450122/article/details/106462193
https://blog.csdn.net/linraise/article/details/12979473
进程是与资源有关的,所以进程就是进程实体的运行过程,是系统进行资源分配和调度的一个独立单位。进程实体是由程序段,相关数据段和PCB组成,而PCB是进程控制块,是为了使参与并发执行的程序能独立运行而专门配置的一个数据结构,注意PCB是进程存在的唯一标志。
多进程可以使得系统鲁棒性更高,出错的时候容易找到错误的地方,而且不影响别的进程,比如ROS,比如Apollo。如果是分布式,就用多进程。
多线程可以进行快速创建和数据共享,进程创建的开销很大,上下文切换开销也稍微大一些,频繁创建进程去响应服务器的请求会造成极大的开销,而且会增加响应时间,所以在进行服务器响应的时候会采用多线程。如果是多核处理用多线程。
如何实现一个缓存,能够存储最近使用的信息,比如说ip地址,要使用哪种数据结构来存储,都需要存储些什么,如何实现?
答:LRU缓存吧,LRU缓存的底层结构应该是LinkedHashMap具体可以再去研究一下哈;
LinkedList需要存储IP即可;HashMap<IP,Addr>;
谈谈信号量,信号量如何访问(当时我一直以为没明白他的意思,以为要问操作系统硬件互斥机制,后面才明白要问PV操作),PV具体如何操作:wait signal
进程切换的过程:
进程的切换,实质上就是被中断运行进程与待运行进程的上下文切换。从主观上来理解。只分为两步:
1.切换新的页表,然后使用新的虚拟地址空间
2.切换内核栈,加入新的内容(PCB控制块,资源相关),硬件上下文切换
系统调用
假设操作系统内存是4GB,其中有2.5GB被A进程占用了,操作系统本身占用0.5GB内存,这时候如果fork了这个进程,是否能成功,为什么?
答:可以,答了copy on write https://blog.csdn.net/shreck66/article/details/47039937/
表面看起来fork()创建子进程子进程拷贝了父进程的地址空间其实不然 刚调用完fork()之后,子进程只是拥有一份和父进程相同的页表,其中页表中指向RAM代码段的部分是不会改变的,而指向数据段,堆段,栈段的会在我们将要改变父子进程各自的这部分内容时,才会将要操作的部分进行部分复制
一开始问有没有见过进程的Z状态,没答出来就问了,进程有哪些状态:
答 新建 阻塞 运行 就绪 终结
"R (running)", /* 0 */ "S (sleeping)", /* 1 */ "D (disk sleep)", /* 2 */ "T (stopped)", /* 4 */ "t (tracing stop)", /* 8 */ "X (dead)", /* 16 */ "Z (zombie)", /* 32 */
https://zhuanlan.zhihu.com/p/96098130 当进程退出但是父进程并没有调用wait或waitpid获取子进程的状态信息时就会产生僵尸进程
Linux内存管理
https://www.cnblogs.com/NanoDragon/p/12736887.html
虚拟地址和物理地址
虚拟地址:
- 避免用户直接访问物理内存地址,防止一些破坏性操作,保护操作系统
- 每个进程都被分配了4GB的虚拟内存,用户程序可使用比实际物理内存更大的地址空间
4GB
的进程虚拟地址空间被分成两部分:「用户空间」和「内核空间」物理地址:
当进程要实际访问内存的时候,会由内核的「请求分页机制」产生「缺页异常」调入物理内存页。
把虚拟地址转换成内存的物理地址,这中间涉及利用
MMU
内存管理单元(Memory Management Unit ) 对虚拟地址分段和分页(段页式)地址转换。
Linux
内核会将物理内存分为3个管理区,分别是:ZONE_DMA:
DMA
内存区域。包含0MB~16MB之间的内存页框,可以由老式基于ISA
的设备通过DMA
使用,直接映射到内核的地址空间。ZONE_NORMAL:普通内存区域。包含16MB~896MB之间的内存页框,常规页框,直接映射到内核的地址空间。
ZONE_HIGHMEM:高端内存区域。包含896MB以上的内存页框,不进行直接映射,可以通过永久映射和临时映射进行这部分内存页框的访问。
用户空间和内核空间
用户进程能访问的是「用户空间」,每个进程都有自己独立的用户空间,虚拟地址范围从从
0x00000000
至0xBFFFFFFF
总容量3G进程(执行的程序)占用的用户空间划分成
5
个不同的内存区域:内核空间:1G
Linux 内核地址空间是指虚拟地址从
0xC0000000
开始到0xFFFFFFFF
为止的高端内存地址空间,总计1G
的容量, 包括了内核镜像、物理页面表、驱动程序等运行在内核空间 。动态内存映射区:
vmalloc Region
该区域由内核函数vmalloc
来分配,特点是:线性空间连续,但是对应的物理地址空间不一定连续。vmalloc
分配的线性地址所对应的物理页可能处于低端内存,也可能处于高端内存。内存数据结构:
vm_area_struct
是描述进程地址空间的基本管理单元,一个进程往往需要多个vm_area_struct
来描述它的用户空间虚拟地址,需要使用「链表」和「红黑树」来组织各个vm_area_struct
。链表用于需要遍历全部节点的时候用,而红黑树适用于在地址空间中定位特定内存区域。内核为了内存区域上的各种不同操作都能获得高性能,所以同时使用了这两种数据结构。
说说epoll和select
https://mp.weixin.qq.com/s/7DrH3vdl0xVJp97Q-fjTAA
https://blog.csdn.net/qq_28350863/article/details/104903889
https://blog.csdn.net/org_hjh/article/details/109050629
https://www.cnblogs.com/aspirant/p/9166944.html
- select和epoll都是同步io多路复用机制。
- epoll相比于select加入了回调函数机制和维护了一个就绪列表。
select:把文件描述符收集过来,交给内核,让内核判断哪一个有数据,当里面有一个或多个有数据的时候,select函数会返回,有数据的fd会被置位。返回之后遍历fd的集合,判断下哪一个被set了(被set的哪一个是有数据的),这时候读取fd上的数据,并且进行相应的处理。
https://www.bilibili.com/video/BV1Ka4y177gs?from=search&seid=11539043780970394596 第138分钟
select
fd_set 使用数组实现
1.fd_size 有限制 1024 bitmap
fd【i】 = accept()
2.fdset不可重用,新的fd进来,重新创建
3.用户态和内核态拷贝产生开销
4.O(n)时间复杂度的轮询
成功调用返回结果大于 0,出错返回结果为 -1,超时返回结果为 0
具有超时时间
poll
基于结构体存储fd
struct pollfd{
int fd;
short events;
short revents; //可重用
}
解决了select的1,2两点缺点
epoll
解决select的1,2,3,4
不需要轮询,时间复杂度为O(1):ready list--当socket上有事件发生时,将其加入此列表。epoll每次只扫描ready list,直接跳过那些不符合条件socketfd,算法复杂度为O(1);
epoll_create 创建一个白板 存放fd_events
epoll_ctl 用于向内核注册新的描述符或者是改变某个文件描述符的状态。已注册的描述符在内核中会被维护在一棵红黑树上
epoll_wait 通过回调函数内核会将 I/O 准备好的描述符加入到一个链表中管理,进程调用 epoll_wait() 便可以得到事件完成的描述符
两种触发模式:
LT:水平触发
当 epoll_wait() 检测到描述符事件到达时,将此事件通知进程,进程可以不立即处理该事件,下次调用 epoll_wait() 会再次通知进程。是默认的一种模式,并且同时支持 Blocking 和 No-Blocking。
ET:边缘触发
和 LT 模式不同的是,通知之后进程必须立即处理事件。
下次再调用 epoll_wait() 时不会再得到事件到达的通知。很大程度上减少了 epoll 事件被重复触发的次数,
因此效率要比 LT 模式高。只支持 No-Blocking,以避免由于一个文件句柄的阻塞读/阻塞写操作把处理多个文件描述符的任务饿死。
select poll epoll 操作方式 遍历 遍历 回调 数据结构 bitmap 数组 红黑树 最大连接数 1024(x86)或 2048(x64) 无上限 无上限 最大支持文件描述符数 一般有最大值限制 65535 65535 fd拷贝 每次调用select,都需要把fd集合从用户态拷贝到内核态 每次调用poll,都需要把fd集合从用户态拷贝到内核态 fd首次调用epoll_ctl拷贝,每次调用epoll_wait不拷贝 工作模式 LT LT 支持ET高效模式 工作效率 每次调用都进行线性遍历,时间复杂度为O(n) 每次调用都进行线性遍历,时间复杂度为O(n) 事件通知方式,每当fd就绪,系统注册的回调函数就会被调用,将就绪fd放到readyList里面,时间复杂度O(1)
线程进程的区别 协程
进程是资源分配的最小单位,线程是程序执行的最小单位
https://blog.csdn.net/chengqiuming/article/details/80573288 https://www.jianshu.com/p/6dde7f92951e
协程(Coroutines)是一种比线程更加轻量级的存在,正如一个进程可以拥有多个线程一样,一个线程可以拥有多个协程。
协程不是被操作系统内核所管理的,而是完全由程序所控制,也就是在用户态执行。这样带来的好处是性能大幅度的提升,因为不会像线程切换那样消耗资源。
协程是一个特殊的函数,这个函数可以在某个地方挂起,并且可以重新在挂起处外继续运行。所以说,协程与进程、线程相比并不是一个维度的概念。
简单来说,一个线程内可以由多个这样的特殊函数在运行,但是有一点必须明确的是,一个线程的多个协程的运行是串行的。如果是多核CPU,多个进程或一个进程内的多个线程是可以并行运行的,但是一个线程内协程却绝对是串行的,无论CPU有多少个核。毕竟协程虽然是一个特殊的函数,但仍然是一个函数。一个线程内可以运行多个函数,但这些函数都是串行运行的。当一个协程运行时,其它协程必须挂起。
协程的切换者是用户(编程者或应用程序),切换时机是用户自己的程序所决定的。协程的切换内容是硬件上下文,切换内存保存在用户自己的变量(用户栈或堆)中。协程的切换过程只有用户态,即没有陷入内核态,因此切换效率高。
线程和CPU核的关系
核心数是指物理上,也就是硬件上存在几个核心。比如双核就是包括两个相对独立的CPU核心单元组。
线程数是一个逻辑上的概念,就是模拟出的CPU核心数,比如可以通过一个实际的CPU核心单元组模拟出2线程的CPU,一个实体核心,两个逻辑线程,这个单核心的CPU就被模拟成一个类似双核心CPU的功能,可以同时处理两个线程的工作。从任务管理器的性能标签页中看到的就是两个CPU。这种模拟技术被叫做超线程技术。
常说的四核八线,四核指该CPU有四个实体核心,八线指每个CPU运行两个逻辑线程,总共八个线程。
对于CPU来说,线程数 >= 核心数。在不引入超线程技术时,一个核心对应一个线程。通过超线程技术可以使一个核心对应两个线程,也就是说它可以同时运行两个线程。
进程线程通信方式
进程通信
管道(pipe)
管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
有名管道 (namedpipe)
有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
信号量(semaphore)
Semaphore semaphore = new Semaphore(3);
semaphore.acquire();//得到停车位 semaphore.release(); // release() 释放
信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
消息队列(messagequeue)
消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
它克服了上两种通信方式中信号量有限的缺点,具有写权限得进程可以按照一定得规则向消息队列中添加新信息;对消息队列有读权限得进程则可以从消息队列中读取信息。
信号 (signal)
信号是在软件层次上对中断机制的一种模拟,它是比较复杂的通信方式,用于通知进程有某事件发生,一个进程收到一个信号与处理器收到一个中断请求效果上可以说是一致的。
共享内存(shared memory)
共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。
可以说这是最有用的进程间通信方式。它使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据得更新。这种方式需要依靠某种同步操作,如互斥锁和信号量等。
套接字(socket)
套接口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同设备及其间的进程通信。
其中哪个速度最快?
线程间的通信方式:https://blog.csdn.net/jisuanji12306/article/details/86363390
https://zhuanlan.zhihu.com/p/129374075
https://blog.csdn.net/u011514810/article/details/77131296
临界区:通过多线程的串行化来访问公共资源或一段代码,速度快,适合控制数据访问;
互斥量Synchronized/Lock:采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限。因为互斥对象只有一个,所以可以保证公共资源不会被多个线程同时访问
信号量Semphare:为控制具有有限数量的用户资源而设计的,它允许多个线程在同一时刻去访问同一个资源,但一般需要限制同一时刻访问此资源的最大线程数目。
事件(信号),Wait/Notify:通过通知操作的方式来保持多线程同步,还可以方便的实现多线程优先级的比较操作
方式一:使用 volatile 关键字(内存共享)
基于 volatile 关键字来实现线程间相互通信是使用共享内存的思想,大致意思就是多个线程同时监听一个变量,当这个变量发生变化的时候 ,线程能够感知并执行相应的业务。这也是最简单的一种实现方式
方式二:使用Object类的wait() 和 notify() 方法
众所周知,Object类提供了线程间通信的方法:wait()、notify()、notifyaAl(),它们是多线程通信的基础,而这种实现方式的思想自然是线程间通信。
注意: wait和 notify必须配合synchronized使用,wait方法释放锁,notify方法不释放锁
方式三:使用JUC工具类 CountDownLatch
jdk1.5之后在java.util.concurrent包下提供了很多并发编程相关的工具类,简化了我们的并发编程代码的书写,***CountDownLatch***基于AQS框架,相当于也是维护了一个线程间共享变量state
方式四:使用 ReentrantLock 结合 Condition
方式五:基本LockSupport实现线程间的阻塞和唤醒
线程间的通信目的主要是用于线程同步,所以线程没有像进程通信中的用于数据交换的通信机制。
进程的调度算法
- http://www.xitongzhijia.net/xtjc/20171023/109740.html
FCFS(先来先服务,队列实现,非抢占的):先请求CPU的进程先分配到CPU
SJF(最短作业优先调度算法):平均等待时间最短,但难以知道下一个CPU区间长度
优先级调度算法(可以是抢占的,也可以是非抢占的):优先级越高越先分配到CPU,相同优先级先到先服务,存在的主要问题是:低优先级进程无穷等待CPU,会导致无穷阻塞或饥饿;解决方案:老化
时间片轮转调度算法(可抢占的):队列中没有进程被分配超过一个时间片的CPU时间,除非它是唯一可运行的进程。如果进程的CPU区间超过了一个时间片,那么该进程就被抢占并放回就绪队列。
多级队列调度算法:将就绪队列分成多个独立的队列,每个队列都有自己的调度算法,队列之间采用固定优先级抢占调度。其中,一个进程根据自身属性被永久地分配到一个队列中。
多级反馈队列调度算法:与多级队列调度算法相比,其允许进程在队列之间移动:若进程使用过多CPU时间,那么它会被转移到更低的优先级队列;在较低优先级队列等待时间过长的进程会被转移到更高优先级队列,以防止饥饿发生。
linux用户态内核态
面试题:https://www.cnblogs.com/inception6-lxc/p/9073983.html
用户态和核心态(内核态)之间的区别是什么呢?
权限不一样。
用户态的进程能存取它们自己的指令和数据,但不能存取内核指令和数据(或其他进程的指令和数据)。
核心态下的进程能够存取内核和用户地址某些机器指令是特权指令,在用户态下执行特权指令会引起错误。在系统中内核并不是作为一个与用户进程平行的估计的进程的集合。
用户空间就是用户进程所在的内存区域,相对的,系统空间就是操作系统占据的内存区域。用户进程和系统进程的所有数据都在内存中。处于用户态的程序只能访问用户空间,而处于内核态的程序可以访问用户空间和内核空间。
用户态切换到内核态的方式如下:
系统调用:程序的执行一般是在用户态下执行的,但当程序需要使用操作系统提供的服务时,比如说打开某一设备、创建文件、读写文件(这些均属于系统调用)等,就需要向操作系统发出调用服务的请求,这就是系统调用。
异常:当CPU在执行运行在用户态下的程序时,发生了某些事先不可知的异常,这时会触发由当前运行进程切换到处理此异常的内核相关程序中,也就转到了内核态,比如缺页异常。
外围设备的中断:当外围设备完成用户请求的操作后,会向CPU发出相应的中断信号,这时CPU会暂停执行下一条即将要执行的指令转而去执行与中断信号对应的处理程序,如果先前执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了由用户态到内核态的切换。比如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后续操作等。
linux常用命令,linux会哪些命令,介绍10个 查看内存、查看内核、查看磁盘等
w命令:该命令会显示目前登录的用户及其进程
users命令:users命令显示了目前已登录的用户
ls命令显示了人类可读格式的文件列表
less命令允许快速查看文件 more命令允许快速查看文件,并以百分比的形式显示详细信息
mv命令将fileA更名为fileB
cat命令用来同时查看多个文件
pwd命令会返回当前的工作目录。
cd命令(切换目录)
cp命令将文件从来源拷贝到目的地
free命令显示了闲置内存、总内存和交换内等方面的信息,单位是字节。
top命令显示了系统的处理器活动,还显示了由内核实时管理的任务,它会显示所使用的处理器和内存
tar命令用于压缩Linux下的文件和文件夹
find命令用来搜索文件、字符串和目录
grep可搜索文件中的特定字符串
rm命令用来清除或删除文件
vim
mkdir命令用来在Linux下创建目录
last命令,我们就能观察用户在系统中的活动
进程相关:top、netstate;显示各种网络相关信息,如网络连接,路由表,接口状态、crontab:定时执行脚本、ps
1、jar文件打包命令
解压命令:jar xvf Example.jar (一般格式:jar xvf Filename.jar)
打包命令:jar cf Example.jar /path/filename1 /path/filename2 (第三项为要打包的文件名字;后边为路径文件名,可以有多项内容)
2、war文件打包命令
解压命令:jar xvf Example.war (一般格式:jar xvf Filename.war)
打包命令:jar cf Example.war /path/filename1 /path/filename2 (第三项为要打包的文件名字;后边为路径文件名,可以有多项内容)
Linux中查看进程的端口号,查看哪个进程占用了该端口
ps -e |grep ssh
- netstat -anp|grep 96
Linux的文件系统
说说NIO是什么,为什么快?
NIO的Buffer到底是啥 Channel是I/O的出入口,buffer就是IO的来源或者目标。
你提到NIO用到了直接内存,那直接内存在用户态还是内核
I/O复用
https://blog.csdn.net/org_hjh/article/details/109050629
同步和异步的区别最大在于异步的话调用者不需要等待结果处理,被调用者会通过回调等机制来通知调用者返回结果。
同步:同步就是发起一个调用后,被调用者未处理完请求之前,调用不返回。
异步:异步就是发一个调用后,立刻得到被调用者的回应表示已接收到请求,但是被调用者并没有返回结果,此时可以处理其他的请求,被调用者通常依靠事件、回调等机制来通知调用者其返回结果。
阻塞:阻塞就是发起一个请求,调用者一直等待请求结果返回,也就是当前线程会被挂起,无法从事其他任务,只有当条件就绪才能继续。
非阻塞:非阻塞就是发起一个请求,调用者不用一直等着结果返回,可以先去干其他的事情。
https://blog.csdn.net/lzb348110175/article/details/98941378
小结: 同步与异步针对通信机制,阻塞与非阻塞针对程序调用等待结果的状态
阻塞IO与非阻塞IO:这是最简单的模型,一般配合多线程来实现。
多路复用(select/poll/epoll):一个线程解决多连接的问题
信号驱动IO模型:一种同步IO,更加灵活
异步IO模型:高效主流的模型,效率很高。
IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程。多个网络I/O复用一个或少量的线程来处理这些连接。IO多路复用适用如下场合:
当客户处理多个描述字时(一般是交互式输入和网络套接口),必须使用I/O复用。
当一个客户同时处理多个套接口时,而这种情况是可能的,但很少出现。
如果一个TCP服务器既要处理监听套接口,又要处理已连接套接口,一般也要用到I/O复用。
如果一个服务器即要处理TCP,又要处理UDP,一般要使用I/O复用。
如果一个服务器要处理多个服务或多个协议,一般要使用I/O复用。
与多进程和多线程技术相比,I/O多路复用技术的最大优势是系统开销小,系统不必创建进程/线程,也不必维护这些进程/线程,从而大大减小了系统的开销。
select、poll、epoll源码说一下
零拷贝
虚拟地址空间转换
https://www.zhihu.com/question/389766884/answer/1174942064
https://www.cnblogs.com/sky-heaven/p/11834820.html
虚拟地址和物理地址之间的运行时映射是通过称为MMU(内存管理单元)的硬件设备完成的。
【虚拟地址到物理地址的转化过程】:虚拟地址的高位3比特决定了对应的页(APR),APR的11-0位决定了物理地址基地址的块地址,加上虚拟地址的12-6比特得到物理内存的块地址,再加上作为块内偏移值的虚拟地址的5-0位,就得到了最后的地址。(如下图所解析~)
系统调用
系统调用是操作系统的最小功能单位。根据不同的应用场景,不同的Linux发行版本提供的系统调用数量也不尽相同,大致在240-350之间。这些系统调用组成了用户态跟内核态交互的基本接口,
从某种角度来看,系统调用和普通的函数调用非常相似。区别仅仅在于,系统调用由操作系统核心提供,运行于核心态;而普通的函数调用由函数库或用户自己提供,运行于用户态。
虚拟内存实现机制
虚拟内存允许执行进程不必完全在内存中。虚拟内存的基本思想是:每个进程拥有独立的地址空间,这个空间被分为大小相等的多个块,称为页(Page),每个页都是一段连续的地址。这些页被映射到物理内存,但并不是所有的页都必须在内存中才能运行程序。当程序引用到一部分在物理内存中的地址空间时,由硬件立刻进行必要的映射;当程序引用到一部分不在物理内存中的地址空间时,由操作系统负责将缺失的部分装入物理内存并重新执行失败的命令。这样,对于进程而言,逻辑上似乎有很大的内存空间,实际上其中一部分对应物理内存上的一块(称为帧,通常页和帧大小相等),还有一些没加载在内存中的对应在硬盘上,如图5所示。
注意,请求分页系统、请求分段系统和请求段页式系统都是针对虚拟内存的,通过请求实现内存与外存的信息置换。面试题:https://blog.csdn.net/justloveyou_/article/details/78304294
分段和分页内存管理:https://blog.csdn.net/bupt_tinyfisher/article/details/8939689
用户级线程和内核级线程,用户级线程的实现?
线程的3种实现方式--内核级线程, 用户级线程和混合型线程
https://blog.csdn.net/gatieme/article/details/51892437
库调度器从进程的多个线程中选择一个线程,然后该线程和该进程允许的一个内核线程关联起来。内核线程将被操作系统调度器指派到处理器内核。用户级线程是一种”多对一”的线程映射
每个用户线程都直接与一个内核线程相关联
如何看线程的运行情况
getstate
Linux下查看某进程的线程状态:
1.jps或top或ps -ef|grep java,找到需要的进程pid;
2.jstack pid,查看pid的所有线程状态信息;
jprofiler
页面置换算法
FIFO先进先出算法:在操作系统中经常被用到,比如作业调度(主要实现简单,很容易想到);
LRU(Least recently use)最近最少使用算法:根据使用时间到现在的长短来判断;
LFU(Least frequently use)最少使用次数算法:根据使用次数来判断;
OPT(Optimal replacement)最优置换算法:理论的最优,理论;就是要保证置换出去的是不再被使用的页,或者是在实际内存中最晚使用的算法。
一个任务是CPU并行,一个任务是IO并行,哪一个任务需要创建的线程更多一些?
Linux cpu占用率 内存占用率,还有剩余内存 网络带宽怎么看,压测怎么对他们进行调整
top free
iperf -s 或查看网卡,网络情况:使用nload命令查看
计算机的内存分布
一般我们将内存分为:堆区、栈区、全局区、代码区、常量区,各个区域存放的内容:
栈区:在程序中所创建的局部变量、参数、数组、指针等,当程序执行完后,将释放所占用的该块内存。
堆区:该片区域中存放着我们手工申请的内容,如:Malloc、new所创建。
全局区:全局变量、静态变量,在我们程序执行完之后将自动释放所占用的内存。
代码区:存放着函数体的二进制代码。
常量区:包含着整形常量、字符串常量,该区域内容不能被修改。
什么数据存储在内存
缓存是什么?虚拟内存是什么?虚拟内存和缓存的区别。
缓存是CPU的一部分,它存在于CPU中
CPU存取数据的速度非常的快,一秒钟能够存取、处理十亿条指令和数据(术语:CPU主频1G),而内存就慢很多,快的内存能够达到几十兆就不错了,可见两者的速度差异是多么的大
缓存是为了解决CPU速度和内存速度的速度差异问题
内存中被CPU访问最频繁的数据和指令被复制入CPU中的缓存,这样CPU就可以不经常到象“蜗牛”一样慢的内存中去取数据了,CPU只要到缓存中去取就行了,而缓存的速度要比内存快很多