-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path1079.html
91 lines (80 loc) · 88.2 KB
/
1079.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
<!DOCTYPE HTML><html lang="zh-CN"><head><meta charset="utf-8"><meta name="keywords" content="操作系统, huang"><meta name="description" content=""><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no"><meta name="renderer" content="webkit|ie-stand|ie-comp"><meta name="mobile-web-app-capable" content="yes"><meta name="format-detection" content="telephone=no"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"><script async src="https://www.googletagmanager.com/gtag/js?id="></script><script>function gtag(){dataLayer.push(arguments)}window.dataLayer=window.dataLayer||[],gtag("js",new Date),gtag("config","")</script><title>操作系统 | huang</title><link rel="icon" type="image/png" href="/favicon.png"><link rel="stylesheet" href="/libs/awesome/css/all.css"><link rel="stylesheet" href="/libs/materialize/materialize.min.css"><link rel="stylesheet" href="/libs/aos/aos.css"><link rel="stylesheet" href="/libs/animate/animate.min.css"><link rel="stylesheet" href="/libs/lightGallery/css/lightgallery.min.css"><link rel="stylesheet" href="/css/matery.css"><link rel="stylesheet" href="/css/my.css"><script src="/libs/jquery/jquery.min.js"></script><meta name="generator" content="Hexo 4.2.0"><link rel="alternate" href="/atom.xml" title="huang" type="application/atom+xml"></head><body><header class="navbar-fixed"><nav id="headNav" class="bg-color nav-transparent"><div id="navContainer" class="nav-wrapper container"><div class="brand-logo"><a href="/" class="waves-effect waves-light"><img src="/medias/logo.png" class="logo-img" alt="LOGO"> <span class="logo-span">huang</span></a></div><a href="#" data-target="mobile-nav" class="sidenav-trigger button-collapse"><i class="fas fa-bars"></i></a><ul class="right nav-menu"><li class="hide-on-med-and-down nav-item"><a href="/" class="waves-effect waves-light"><i class="fas fa-home" style="zoom:.6"></i> <span>首页</span></a></li><li class="hide-on-med-and-down nav-item"><a href="/tags" class="waves-effect waves-light"><i class="fas fa-tags" style="zoom:.6"></i> <span>标签</span></a></li><li class="hide-on-med-and-down nav-item"><a href="/categories" class="waves-effect waves-light"><i class="fas fa-bookmark" style="zoom:.6"></i> <span>分类</span></a></li><li class="hide-on-med-and-down nav-item"><a href="/archives" class="waves-effect waves-light"><i class="fas fa-archive" style="zoom:.6"></i> <span>归档</span></a></li><li class="hide-on-med-and-down nav-item"><a href="/about" class="waves-effect waves-light"><i class="fas fa-user-circle" style="zoom:.6"></i> <span>关于</span></a></li><li class="hide-on-med-and-down nav-item"><a href="/contact" class="waves-effect waves-light"><i class="fas fa-comments" style="zoom:.6"></i> <span>留言板</span></a></li><li class="hide-on-med-and-down nav-item"><a href="/friends" class="waves-effect waves-light"><i class="fas fa-address-book" style="zoom:.6"></i> <span>友情链接</span></a></li><li><a href="#searchModal" class="modal-trigger waves-effect waves-light"><i id="searchIcon" class="fas fa-search" title="搜索" style="zoom:.85"></i></a></li></ul><div id="mobile-nav" class="side-nav sidenav"><div class="mobile-head bg-color"><img src="/medias/logo.png" class="logo-img circle responsive-img"><div class="logo-name">huang</div><div class="logo-desc">Never really desperate, only the lost of the soul.</div></div><ul class="menu-list mobile-menu-list"><li class="m-nav-item"><a href="/" class="waves-effect waves-light"><i class="fa-fw fas fa-home"></i> 首页</a></li><li class="m-nav-item"><a href="/tags" class="waves-effect waves-light"><i class="fa-fw fas fa-tags"></i> 标签</a></li><li class="m-nav-item"><a href="/categories" class="waves-effect waves-light"><i class="fa-fw fas fa-bookmark"></i> 分类</a></li><li class="m-nav-item"><a href="/archives" class="waves-effect waves-light"><i class="fa-fw fas fa-archive"></i> 归档</a></li><li class="m-nav-item"><a href="/about" class="waves-effect waves-light"><i class="fa-fw fas fa-user-circle"></i> 关于</a></li><li class="m-nav-item"><a href="/contact" class="waves-effect waves-light"><i class="fa-fw fas fa-comments"></i> 留言板</a></li><li class="m-nav-item"><a href="/friends" class="waves-effect waves-light"><i class="fa-fw fas fa-address-book"></i> 友情链接</a></li><li><div class="divider"></div></li><li><a href="https://github.com/hyl2048" class="waves-effect waves-light" target="_blank"><i class="fab fa-github-square fa-fw"></i> Fork Me</a></li></ul></div></div><style>.nav-transparent .github-corner{display:none!important}.github-corner{position:absolute;z-index:10;top:0;right:0;border:0;transform:scale(1.1)}.github-corner svg{color:#0f9d58;fill:#fff;height:64px;width:64px}.github-corner:hover .octo-arm{animation:a .56s ease-in-out}.github-corner .octo-arm{animation:none}@keyframes a{0%,to{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}</style><a href="https://github.com/hyl2048" class="github-corner tooltipped hide-on-med-and-down" target="_blank" data-tooltip="Fork Me" data-position="left" data-delay="50"><svg viewBox="0 0 250 250" aria-hidden="true"><path d="M0 0 115 115 130 115 142 142 250 250 250 0Z"></path><path d="M128.3 109C113.8 99.7 119 89.6 119 89.6 122 82.7 120.5 78.6 120.5 78.6 119.2 72 123.4 76.3 123.4 76.3 127.3 80.9 125.5 87.3 125.5 87.3 122.9 97.6 130.6 101.9 134.4 103.2" fill="currentColor" style="transform-origin:130px 106px" class="octo-arm"></path><path d="M115 115C114.9 115.1 118.7 116.5 119.8 115.4L133.7 101.6C136.9 99.2 139.9 98.4 142.2 98.6 133.8 88 127.5 74.4 143.8 58 148.5 53.4 154 51.2 159.7 51 160.3 49.4 163.2 43.6 171.4 40.1 171.4 40.1 176.1 42.5 178.8 56.2 183.1 58.6 187.2 61.8 190.9 65.4 194.5 69 197.7 73.2 200.1 77.6 213.8 80.2 216.3 84.9 216.3 84.9 212.7 93.1 206.9 96 205.4 96.6 205.1 102.4 203 107.8 198.3 112.5 181.9 128.9 168.3 122.5 157.7 114.1 157.9 116.9 156.7 120.9 152.7 124.9L141 136.5C139.8 137.7 141.6 141.9 141.8 141.8Z" fill="currentColor" class="octo-body"></path></svg></a></nav></header><div class="bg-cover pd-header post-cover" style="background-image:url(/medias/featureimages/3.jpg)"><div class="container" style="right:0;left:0"><div class="row"><div class="col s12 m12 l12"><div class="brand"><h1 class="description center-align post-title">操作系统</h1></div></div></div></div></div><main class="post-container content"><link rel="stylesheet" href="/libs/tocbot/tocbot.css"><style>#articleContent h1::before,#articleContent h2::before,#articleContent h3::before,#articleContent h4::before,#articleContent h5::before,#articleContent h6::before{display:block;content:" ";height:100px;margin-top:-100px;visibility:hidden}#articleContent :focus{outline:0}.toc-fixed{position:fixed;top:64px}.toc-widget{width:345px;padding-left:20px}.toc-widget .toc-title{margin:35px 0 15px 0;padding-left:17px;font-size:1.5rem;font-weight:700;line-height:1.5rem}.toc-widget ol{padding:0;list-style:none}#toc-content{height:calc(100vh - 250px);overflow:auto}#toc-content ol{padding-left:10px}#toc-content ol li{padding-left:10px}#toc-content .toc-link:hover{color:#42b983;font-weight:700;text-decoration:underline}#toc-content .toc-link::before{background-color:transparent;max-height:25px}#toc-content .is-active-link{color:#42b983}#toc-content .is-active-link::before{background-color:#42b983}#floating-toc-btn{position:fixed;right:15px;bottom:76px;padding-top:15px;margin-bottom:0;z-index:998}#floating-toc-btn .btn-floating{width:48px;height:48px}#floating-toc-btn .btn-floating i{line-height:48px;font-size:1.4rem}</style><div class="row"><div id="main-content" class="col s12 m12 l9"><div id="artDetail"><div class="card"><div class="card-content article-info"><div class="row tag-cate"><div class="col s7"><div class="article-tag"><span class="chip bg-color">无标签</span></div></div><div class="col s5 right-align"><div class="post-cate"><i class="fas fa-bookmark fa-fw icon-category"></i> <a href="/categories/Basic/" class="post-category">Basic</a></div></div></div><div class="post-info"><div class="post-date info-break-policy"><i class="far fa-calendar-minus fa-fw"></i> 发布日期: 2020-08-19</div></div></div><hr class="clearfix"><div class="card-content article-card-content"><div id="articleContent"><h2 id="计算机系统概述"><a href="#计算机系统概述" class="headerlink" title="计算机系统概述"></a>计算机系统概述</h2><p>基本构成</p><p>处理器</p><p>内存</p><p>输入/输出模块</p><p>系统总线</p><p>微处理器的演化</p><p>指令的执行</p><p>中断</p><p>分类:程序中断(算术溢出、除数为零、执行非法的机器指令、访问用户不允许的存储位置);时钟中断;I/O中断;硬件失效中断;</p><p>中断和指令周期</p><p>中断处理</p><p>程序状态字(PSW)、程序计数器(PC)</p><p>运行中断处理程序</p><p>保存被中断程序的所有状态信息并在以后恢复这些信息,这是十分重要的,因为中断并不是程序调用的一个例程,它可以在任何时候发生,因而可以在用户程序执行过程中的任何一点上发生,它的发生是不可预测的。</p><p>多个中断</p><p>顺序中断处理;嵌套中断处理;考虑优先级的中断处理</p><p>存储器的层次结构</p><p>价格、容量、访问时间之间存在着一定的折衷;</p><p>层次结构能够奏效的原因在于低层访问频率递减(基础是局部性原理)</p><p>高速缓存(利用局部性原理)</p><p>高速缓存对操作系统不可见,但它与其他存储管理硬件相互影响。</p><p>动机</p><p>高速缓存原理</p><p>局部性原理</p><p>高速缓存设计</p><p>设计点:高速缓存大小;块大小(大小影响命中率);映射函数(设计的命中率要高;函数越灵活,逻辑电路设计就越复杂);置换算法(最近最少算法);写策略(何时发生存储写操作;当块被置换时才发生写操作);高速缓存级数。</p><p>直接内存存取</p><p>可编程I/O</p><p>处理器必须等待很长时间,以确定I/O模块是否做好了接受或发送更多数据的准备。</p><p>中断驱动I/O</p><p>I/O传输速度受限于处理器测试设备和提供服务的速度</p><p>处理器忙于管理I/O传送的工作,必须执行很多指令以完成I/O传送</p><p>直接内存存取(DMA)</p><p>大量移动数据,DMA模块负责</p><p>多处理器和多核计算组织结构(提供并行的手段)</p><p>对称多处理器(SMP)</p><p>性能、可用性、将进式增长、可伸缩性</p><p>高速缓存的一致性问题</p><p>多核计算机(单芯片多处理器)</p><p>预取机制</p><h2 id="操作系统概述"><a href="#操作系统概述" class="headerlink" title="操作系统概述"></a>操作系统概述</h2><p>设计目标:方便、有效、扩展能力</p><p>系统程序:实用工具或库程序,实现了在创建程序、管理文件和控制I/O设备中经常使用的功能。</p><p>提供的服务:程序开发:编辑器;调试器(应用程序开发工具)</p><p>程序运行:操作系统为程序的运行调度资源</p><p> I/O设备访问:操作系统隐藏一些细节,并提供接口</p><p>文件访问控制:I/O设备的特性、访问保护机制</p><p>系统访问:对于共享或公共资源,操作系统控制权限以及资源竞争的冲突问题</p><p>错误检测和响应:设计一些机制来应对程序运行时的错误</p><p>记账</p><p>三种重要的接口:指令系统体系结构(ISA):硬件于软件的分界线</p><p>应用程序二进制接口(ABI):</p><p>应用程序编程接口(API):</p><p>操作系统实际上是一组计算机程序,给处理器提供指令。处理器自身也是资源,供操作系统调配。操作系统的一部分为内核程序(含操作系统最常使用的功能)和当前正在使用的其他操作系统程序</p><h2 id="操作系统发展历史"><a href="#操作系统发展历史" class="headerlink" title="操作系统发展历史"></a>操作系统发展历史</h2><p>串行处理</p><p>调度</p><p>准备时间:程序运行前的准备工作</p><p>简单批处理系统</p><p>监控程序(控制事件顺序,完成调度功能):中断处理;设备驱动;作业序列;控制语言解释器;控制权交给作业仅意味着处理器当前取得和执行得都是用户程序中得指令,而控制权返回给监控程序意味着处理器当前从监控程序中取指令并执行指令。其他功能:内存保护;定时器特权指令;中断;</p><p>处理器角度</p><p>缺点:内存交给监控程序;监控程序消耗了一部分机器时间</p><p>多道批处理系统(为解决简单批处理系统的问题而生)</p><p>支持I/O中断;DMA</p><p>待运行作业留在内存中,因此有内存管理。</p><p>运行多个作业,因此有调度算法。</p><p>分时系统(因为交互作业而生)</p><p>一提出新系统就会引发新的问题,如资源竞争的问题、文件系统保护的问题(授权)。</p><p>成就</p><p>进程(比作业这一概念更为通用):</p><p>一段可执行程序;程序所需相关数据;程序的执行上下文(进程状态);</p><p>内存管理</p><p>进程隔离;自动分配管理;支持模块化程序设计;保护和访问控制;长期存储;</p><p>文件系统是访问控制和保护的一个有用的单元</p><p>信息保护和安全</p><p>可用性;保密性;数据完整性;认证</p><p>调度和资源管理(运筹问题)</p><p>设计策略考虑的因素:公平性;有差别的响应性;有效性;</p><p>现代操作系统特征</p><p>微内核体系结构(只分配一些基本的功能;可使系统机构的设计更加简单、灵活,非常适合于分布式环境);</p><p>分布式操作系统;</p><p>多线程(可把应用程序的进程划分为同时运行的多个线程);</p><p>线程:包含上下文环境和栈中自身的数据区域;可以执行中断;</p><p>进程:一个或多个线程和相关系统资源(含有数据和代码的存储器空间、打开的文件和设备)的集合。严格对应于一个正在执行程序的概念。把进程分解为多个线程,程序员可以在很大程度上控制应用程序的<strong>模块性</strong>以相关<strong>事件的时间安排</strong>。应用线程时,线程间切换时的开销少,相对于进程间的切换。</p><p>面向对象设计;</p><p>对称多处理;</p><p>性能:多个进程可分别自不同的处理器上同时运行</p><p>可用性:单个处理器的失效并不会导致机器的额停止,相反,OS可继续运行,只是性能有所降低。</p><p>增量增长:可以添加额外的处理器来增强系统的功能;</p><p>可扩展性:根据系统配置的处理器数量,来提供不同嘉禾和性能特征的产品。</p><p>面向对象设计:用于给小内核增加模块化的扩展。</p><p>容错性</p><p>可靠性:</p><p>平均失效时间(MTTF)</p><p>可用性:系统不可用时间为宕机时间</p><p>错误:</p><p>硬件设备或组件缺陷,如短路或线路损坏;</p><p>计算机程序中不正确的步骤、过程或数据定义。</p><p>永久性错误;硬盘磁头损坏、软件错误、通信部件损坏</p><p>临时性错误;</p><p>一瞬时错误:冲激噪声导致的位传输错误、电源故障</p><p>一间歇性错误:连接松动</p><p>系统的容错性是通过增加冗余度来实现的</p><p>空间冗余:多条并行线路并以多数输出的结果作为输出;备用域名服务器</p><p>时间冗余:检测到错误时重复某一功能或操作。对临时性错误有效,而对永久性的无效,检测异常时,用数据链路控制协议重传数据块。</p><p>信息冗余:通过复制或编码数据的方式来检测和修复位数据,进而提高容错性。存储系统用的差错控制编码电路和RAID磁盘所用的纠错技术。</p><p>用操作系统机制来提高容错性</p><p>进程隔离:</p><p>并发控制:</p><p>虚拟机:</p><p>监测点和回滚机制:</p><p>多处理器和多核操作系统设计考虑因素</p><p>对称多处理器操作系统设计考虑因素</p><p>并发进程或线程:</p><p>调度:</p><p>同步:锁是一种通用的同步机制</p><p>内存管理:分页机制</p><p>可靠性和容错性</p><p>多核操作系统设计考虑因素</p><p>多核设计的核心关注点在于将多核系统固有的并行能力与应用程序的性能需求相匹配。(①,硬件并行,即指令并行;处理器层次上的潜在并行能力,即在每个处理器上多道程序或多线程程序的执行能力;在多核上一个应用程序以并发多进程或多线程形式执行的潜在并行能力)</p><p>应用层并行:GCD为一种线程池机制</p><p>虚拟机方式:操作系统需要一块受保护的空间,以避免用户和程序的干扰,于是出现了内核模式和用户模式的区别。</p><p>Win8从根本上改变了操作系统的内核结构,尤其是线程管理和虚拟内存管理。</p><p>内核是操作系统中唯一不可抢占或分页的部分;内核使用C语言编写,采用的设计原理和面向对象设计密切相关。面向对象方法简化了进程间资源和数据的共享,便于保护资源免受未经许可的访问。</p><p>UNIX系统</p><p>所有的UNIX实现都是用C语言编写</p><p>Linux操作系统</p><p>Linux可加载模块特性:</p><p>动态链接:</p><p>可堆叠模块:</p><p>Android</p><p>操作系统可想象未资源的统一表示,它可被应用程序请求和访问。资源包括内存、网络接口和文件系统等。操作系统为应用程序创建这些资源的抽象表示后,就必须管理它们的使用,例如操作系统可允许资源共享,也可允许资源保护。</p><p>操作系统有序管理应用程序的执行所达到的目标:</p><p>资源对多个应用程序时可用的。</p><p>物理处理器在多个应用程序间切换,以保护所有程序都在执行中。</p><p>处理器和I/O设备能得到充分利用。</p><h2 id="进程"><a href="#进程" class="headerlink" title="进程"></a>进程</h2><p>进程定义,进程与进程控制块之间的关系</p><p>进程的基本元素:程序代码;相关数据集;进程控制块;</p><p>进程控制块:进程表示信息;进程状态信息;进程控制信息;</p><p>进程控制块是操作系统中最重要的数据结构,每个进程控制块都包含操作系统所需进程的所有信息。</p><p>进程描述:</p><p>操作系统的控制结构</p><p>维护四种不同类型的表:</p><p>内存表:</p><p>跟踪内存和外存</p><p>I/O表:</p><p>文件表:</p><p>进程表:</p><p>进程控制结构</p><p>进程位置</p><p>进程映像:程序;数据;栈;属性;</p><p>线程</p><p>进程控制:</p><p>执行模式</p><p>用户模式;系统模式(控制模式、内核模式)</p><p>操作系统内核的典型功能:进程管理;内存管理;I/O管理;支持功能(中断处理;记账;监视);</p><p>进程的创建</p><p>分配标识符</p><p>分配空间</p><p>初始化进程控制块</p><p>真确的链接</p><p>创建或扩充其他数据结构</p><p>进程的切换</p><p>何时切换</p><p>中断(时钟、I/O、陷阱(非法的文件访问))</p><p>内存失效</p><p>进程切换与模式切换不同,模式切换可在不改变运行态进程的状态的情况下出现,此时保存上下文并在以后恢复上下而温暖仅需要很少的开销。但是,若当前正在运行进程将转换为另一状态(就绪、阻塞),则操作系统必须使环境产生实质性的变化。</p><p>进程切换步骤:</p><p>操作系统的执行</p><p>OS与普通计算机软件以同样的方式运行,即它也是由处理器执行多额一个程序</p><p>OS会频繁地释放控制权,并依赖于处理器来恢复控制权。</p><p>无进程内核:进程这一概念仅适用于用户程序,而OS代码则是在特权模式下单独运行的实体。</p><p>较小计算机操作系统(PC、工作站):操作系统例程在用户进程内运行</p><p>基于进程的OS:把OS作为一组系统进程来实现。</p><p>Unix:</p><p>进程描述,采用复杂的数据结构对操作系统管理进程和分派进程所需的信息进行描述。</p><h2 id="线程:"><a href="#线程:" class="headerlink" title="线程:"></a>线程:</h2><p>进程的特点:</p><p>资源所有权:</p><p>调度/执行:</p><p>多线程:OS在单个进程内支持多个并发执行路径的能力。</p><p>在多线程环境中,进程定义为资源分配单元和一个保护单元。进程涉及资源所有权,而线程涉及程序的执行</p><p>创建一个线程要快;终止一个线程要快;线程之间切换的时间要少;提高了笔筒执行程序之间的通信的效率(进程间切换需要内核的介入,此时内核提供保护和通信机制,由于同一进程中多个线程共享内存和文件,因此就无需调用内核就可以相互通信);例如:文件服务器应用程序。前台和后台工作;异步处理;执行速度;模块化程序结构;</p><p>调度和分派实在线程基础上完成的,因此大多是于执行相关的信息可以保存在线程级的数据结构中。</p><p>挂起态对线程没有意义</p><p>线程同步带来的问题和使用的技术通常于进程同步相同</p><p>线程分类</p><p>用户级线程(ULT):</p><p>内核级线程(KLT):</p><p>使用ULT而非KLT的优点如下:</p><p>所有线程管理数据结构都在一个进程的用户地址空间中,线程切换不需要内核模式特权,因此进程不需要为了管理线程而切换到内核模式,进而节省了两次状态转换(从用户模式到内核模式,以及从内核模式返回用户模式)的开销</p><p>调度因应用程序的不同而不同。为了不要然乱底层的操作系统调度程序,可以做到为应用程序量身定做调度算法。</p><p>ULT可在任何操作系统中运行,不需要对底层内核进行修改以支持ULT,线程库是提供所有应用程序共享的一组应用级函数。</p><p>缺点:ULT执行一个系统调用时,不仅会阻赛线程,也会阻塞进程中的所有线程。</p><p>在纯ULT中,多线程应用程序不能利用多处理技术。</p><p>解决线程阻塞的方法:</p><p>把应用程序写成一个多进程程序而非多线程程序,但是,这种方法避开了线程的主要优点,每次切换都换成进程间的切换而导致开销过大。</p><p>使用“套管”技术</p><p>内核级线程:KLT方法,克服了ULT方法的两个缺点;内核例程自身也可是多线程的。</p><p>KLT的缺点:把控制权从一个线程传送到同一个进程内的另一个线程时,要切换到内核模式。</p><p>KLT、ULT、进程操作执行时间,相差数量级。而速度能否实现,则取决于应用程序的性质。若应用程序的大多数线程切换都西药内核模式访问时,基于ULT的方案不见得会比基于KLT的方案好。</p><p>有时使用混合的方法会克服ULT、KLT各自的缺点,如Solaris操作系统。</p><p>线程和进程的关系以及对性能的影响</p><p>线程于进程之间的比例关系</p><p>多核和多线程</p><p>加速比</p><p>从多核和多线程中获益的程序</p><p>Win8进程和线程管理</p><p>进程:由一个或多个进程组成</p><p>用户模式调度:是应用程序用于安排自己的线程的一种轻量级机制。</p><p>Solaris的线程和SMP管理</p><p>使用内核线程来处理中断;内核控制对数据结构的访问,并使用互斥原语在中断线程间进行同步;中断线程被赋予更高的优先级,高于所有其他类型的内核线程。</p><p>Linux的进程当作线程管理器</p><p>Linux中没有给线程单独定义数据结构,因此Linux中的进程和线程没有区别。</p><p>虽然同一个进程组的克隆进程共享同一内存空间,但不能共享同一个用户栈。所以clone()调用会为每个进程创建独立的栈空间。</p><p>命名空间可使一个进程拥有于其他相关命名空间下的其他进程不同的系统视图</p><p>安卓应用:安卓应用都包含一个或多个实例,而每个实例由一个或多个4种类型的应用程序组件组成。(活动、服务、内容提供器、广播接收器)</p><p>在一个给定的应用,其所有进程和线程都在相同的虚拟机中执行。按优先级层次结构来结束进程</p><p>常用栈、队列来对活动顺序控制</p><h2 id="并发性:互斥和同步"><a href="#并发性:互斥和同步" class="headerlink" title="并发性:互斥和同步"></a>并发性:互斥和同步</h2><p>操作系统设计的核心问题是进程和线程的管理</p><p>多道程序设计技术</p><p>多处理器技术</p><p>分布式处理技术</p><p>三种不同的上下文:</p><p>多应用程序</p><p>结构化</p><p>操作系统结构</p><p>共享资源保护问题</p><p>数据一致性</p><p>最终结果取决于多个进程的指令执行顺序</p><p>操作系统必须保护每个进程的数据和物理资源,避免其他进程的五一干扰。</p><p>进程的功能和输出结果必须与执行速度无关(相对于其他并发进程的执行速度)</p><p>与并发相关的术语:原子操作、临界区、死锁、活锁、互斥、竞争条件、饥饿</p><p>操作系统关注的问题:</p><p>OS必须能够跟踪不同的进程(进程控制块)</p><p>OS必须为每个活动进程分配和释放各种资源,这些资源包括</p><p>处理器时间;存储器;文件;I/O设备;</p><p>OS必须保护每个进程的数据和物理资源,避免其他进程的五一干扰,这涉及存储器、文件和I/O设备相关的技术。</p><p>支持并发的机制(满足互斥的机制)</p><p>硬件机制:</p><p>使用专用机器指令,虽然可以减少开销,但却很难成为一种通用的解决方案。</p><p>机器指令用于保证两个动作的原子性,指令完成后,另一个指令才能执行。</p><p>优点:适用于单处理器或共享内存的多处理器上的任意数量的进程;简单且易于证明;可用于支持多个临界区,每个临界区可以用它自己的变量定义。</p><p>缺点:使用了忙等待;可能饥饿;可能思索。</p><p>中断禁用:代价高;效率低不适用于多处理器结构中</p><p>软件机制:</p><p>让并发执行的进程承担这一责任,这类进程需要与另一个进程合作,而不需要程序设计语言或操作系统提供任何支持来实施互斥。但是这种方法会增加开销并存在缺陷。</p><p>进程之间的交互(解决与执行速度无关的问题):</p><p>互相不知道对方的存在(竞争);</p><p>进程间知道对方的存在(通过共享合作);</p><p>进程直接知道对方的存在(通过通信合作);</p><p>操作系统或程序设计语言中提供某种级别的支持。</p><p>信号量;管程;消息传递;</p><p>二元信号量(互斥锁);互斥量;条件变量;事件标志;信箱/消息;自旋锁;</p><p>资源的竞争:在不知道其他进程存在的情况下共享资源</p><p>(面临互斥、死锁、饥饿三个控制问题。只有一个进程能在临界区。)</p><p>进程通过共享合作:它们共享变量,每个进程并未明确地知道其他进程的存在,只知道要维护数据的完整性。</p><p>进程间通过通信合作:在传递消息的过程中进程间未共享任何对象,因而这类合作不需要互斥,但仍然存在思索和饥饿问题。</p><p>任何进程间的复杂合作都可以通过适当的信号结构得到满足。</p><p>s.count>=0:s.count是可执行semWait(t)而不被阻塞的进程数[期间无semSignal(s)执行]。这种情形允许信号量支持同步与互斥。</p><p>s.count<0:s.count的大小是阻塞在s.queue队列中的进程数。</p><p>并发中常见的问题:</p><p>生产者/消费者</p><p>问题是要确保这种情况:当缓存已满时,生产者不会继续向其中添加数据;当缓存为空时,消费者不会从中移走数据。</p><p>理发店问题:</p><p>信号量的实现:</p><p>硬件方案:硬件或固件实现</p><p>软件方案:Dekker算法或者Peterson算法</p><p>管程</p><p>和信号量相比,管程时一种程序设计语言结构,提供的功能和信号量相同,更易于控制。可以用管程锁定任何对象,对类似于链表之类的对象,可以用一个锁锁着整个链表,也可每个表用一个锁,还可以为表中的每个元素用一个锁。</p><p>管程是由一个或多个过程、一个初始化序列和局部数据组成的软件模块,主要特点如下:</p><p>局部数据只能被管程的过程访问;</p><p>一个进程通过调用管程的一个过程进入管程;</p><p>任何时候,只有一个进程在管程中执行,调用管程的其他进程都被阻塞,以等待管程可用。</p><p>管程提供了互斥机制;管程通过使用<strong>条件变量</strong>来支持同步,这些条件变量包含在管程中,并且只有在管程中才能被访问。</p><p>管程优于信号量之处在于,所有的同步机制都被限制在管程内部,因此不但<strong>容易验证同步的正确性,而且易于检测出错误</strong>。<strong>此外,若一个管程被正确地编写,则所有进程对受保护资源的访问都是正确的;而对于信号量,只有当所有访问资源的进程被正确编写时,资源才是正确的</strong>。</p><p>管程的通知与广播</p><p>广播可以使所有在该条件上等待的进程都置于就绪状态,当一个进程不知道由多少进程将被激活时,这种方式非常方便;此外,当一个进程难以准确地判定将激活哪一个进程时,也可使用广播。</p><p> Lampson/Redell管程由于Hoare管程的原因是,Lampson/Redell方法错误较少。在Lampson/Redell方法中,由于每个过程在受到信号后都检查管程变量,且由于使用了while结构,一个进程不正确地广播或发信号,不会导致受到信号的程序出错。受到信号的程序将检查相关的变量,如果期望的条件得不到满足,它会继续等待。</p><p> Lampson/Redell管程的另一个优点是,它有助于在程序结构中采用更加模块化的方法。例如,考虑一个缓冲区分配程序的实现,为了在顺序的进程间合作,必须满足两级条件:保持一致的数据结构。管程强制实施互斥,并在允许对缓冲区的另一个操作之前完成一个输入或输出操作;在1级条件的基础上,为该进程加上足够的内存,完成其分配请求。</p><p>消息传递</p><p>同步</p><p>阻塞send,阻塞receive;无阻塞send,阻塞receive;无阻带send,无阻塞receive;</p><p>寻址</p><p>直接寻址:</p><p>间接寻址:通过信箱传递信息。解除了发送者和接受者之间的耦合关系,可以更灵活地使用消息。发送者和接受者之间的关系可以是1对1(专用通信连接)、也可以是1对多(广播消息)、多对一(关系对客户服务器间地交互非常有用)、多对多(多个服务进程对多个客户进程提供服务)</p><p>消息格式</p><p>取决于消息机制的目标,以及该机制是运行在一台计算机上还是运行在分布式系统中。</p><p>排队原则</p><p>先进先出;优先级;允许接收者检查消息队列并选择下一次接受那个消息。</p><p>互斥</p><p>读者/写者的问题</p><p>读者优先</p><p>使用信号量的解决方案</p><p>写者优先</p><p>并发:死锁和饥饿</p><p>死锁:一组相互竞争系统资源或通信的进程间的“永久”阻塞。</p><p>可重用资源</p><p>资源:可重用资源和可消耗资源</p><p>可重用资源指一次仅供一个进程安全使用且不因使用而耗尽的资源。进程得到资源单元并使用后,会释放这些单元供其他进程再次使用。可重用资源的例子包括处理器、I/O通道、内存和外存、设备,以及诸如文件、数据库和信号量之类的数据结构。</p><p>并发程序设计非常具有挑战性,因此这类死锁的确会发生,而发生的原因 通常隐藏在复杂的程序逻辑中,因此检测非常困难。处理这类死锁的一个策略是,给系统设计施加关于资源请求顺序的约束。</p><p>内存请求,有时,不事先知道请求的存储空间总量,很难通过系统设计约束来处理这类死锁。解决这类特殊问题的最好办法是,使用虚存有效地消除这种可能性。</p><p>可消耗资源是指可被创建和销毁地资源。某种类型可消耗资源的额数量通常设有限制,无阻塞生产进程可以创建任意数量地这类资源。消费进程得到一个资源时,该资源就不再存在。可销耗资源地例子有中断、信号、消息和I/O缓冲区中的信息。</p><p>引发死锁的原因是一个设计错误,这类错误比较微妙,因而很难发现。此外,罕见大的事件组合也会导致死锁,因此只有当程序使用了相当常一段时间甚至几年之后,才可能出现这类问题(即发生死锁)。</p><p>不存在解决所有类型死锁的有效策略。</p><p></p><p>Hlot的资源分配图</p><p>死锁的条件(而非充要条件):</p><p>互斥;占有等待;不可抢占;(死锁的必要条件,也就是联合进程图的敏感区产生的条件)</p><p>循环等待;</p><p>这四个条件构成了死锁的充分必要的条件。处理死锁的三种方法:一十采用某种策略消除四个条件中断额某个条件的出现来预防死锁;二是基于资源分配的当前状态做动态选择来避免死锁;三是试图检测死锁(满足四个条件)的存在并从死锁中恢复。</p><p>死锁预防:</p><p>设计一种系统来排除死锁的可能性</p><p>间接死锁预防:防止三个必要条件中的任何一个发生</p><p>直接死锁预防:防止循环等待的发生。</p><p>占有且等待: 预防时,可要求进程一次性地请求所有需要的资源,并阻塞这个进程直到所有请求都同时满足。这个方法存在的弊端也是应用程序在使用模块化程序设计或多线程结构时产生的实际问题。要同时请求所需的资源,应用程序需要直到其以后将在所有级别或所有模块中请求的所有资源。</p><p>预防不可抢占的进程;占有资源的进程进一步申请资源时若被拒绝,则该进程必须释放其最初占有的资源,必要时可再次申请这些资源和其他资源;一个进程请求当前被另一个进程占有的一个资源时,操作胸痛可以抢占另一个进程,要求它释放资源。</p><p>预防循环等待:定义资源类型的线性顺序来预防。若一个进程已经分配了R类型的资源,则其接下来请求的资源只能是哪些排在R类型之后的资源。</p><p>死锁避免:</p><p>允许三个必要条件,但通过明智的选择,可确保永远不会到达死锁点,因此死锁比避免与死锁预防相比,可允许更多的并发。在死锁避免中,是否允许当前的资源分配请求时通过判断该请求是否可能导致死锁来决定的。因此,死锁避免要直到未来进程资源亲求的情况。方法:若一个进程的请求会导致死锁,则不启动该进程;若进程增加的资源请求会导致死锁,则不允许这一资源分配。</p><p>进程启动拒绝:只有满足所有当前进程的最大亲求量及新的进程请求时,才会启动该进程。这个策略不是最优的,因为假设了最坏的情况:所有进程同时发出它们的最大请求。</p><p>资源分配拒绝(银行家算法——测试安全算法):</p><p>安全状态:至少一个资源分配序列不会导致死锁;不安全状态:指非安全的一个状态。</p><p>死锁避免的优点时,无需死锁预防中的抢占和回滚进程,且与死锁预防相比限制较少,但是,它在使用中也有许多限制:</p><p>必须事先声明每个进程请求的最大资源</p><p>所讨论的进程必须时无关的,</p><p>分配的资源数量必须时固定的</p><p>在占有资源时,进程不能推出。</p><p>死锁检测</p><p>通过限制访问资源和进程上强约束来解决死锁问题</p><p>死锁可以频繁地在每个资源请求发生时进行,也可以进行得少一些,具体取决于发生死锁得可能性。</p><p>检测到死锁后,就需要采用某种策略类恢复死锁</p><p>取消所有死锁进程;</p><p>回滚,重启机制;</p><p>连续取消死锁进程直到不在存在死锁</p><p>连续抢占资源直到不在存在死锁</p><p>一种综合的死锁策略</p><p>不同情况下采用不同的策略</p><p>可交换空间:一次性分配所有请求资源来预防死锁(进程交换所用外存中的存储块)</p><p>进程资源:死锁避免策略通常是很有效的,因为进程可以事先声明它们需要的这类资源。(可分配的设备,如磁带设备和文件)</p><p>内存:基于抢占的预防是最适合的策略(可按页或段分配给进程)</p><p>内部资源:可以使用基于资源排序的预防策略(I/O通道)</p><p>哲学家就餐问题</p><p>可视为应用程序中包含并发执行的线程时,协调处理共享资源的代表性问题</p><p>基于信号量的解决方案</p><p>允许五个人,会存在死锁;只允许四个人就座,不会死锁与饥饿</p><p>基于管程的解决方案</p><p>管程不会发生死锁,因为在同一时刻只有一个进程进入管程。比如,第一位哲学家进入了管程保证了只要他拿起左边的额叉子,其右边的哲学家可以拿到其左边的叉子前,就一定可以拿到右边的叉子。</p><p>UNIX并发机制</p><p><strong>管道、消息和共享内存</strong>提供了进程间传递数据的方法,而<strong>信号量和信号</strong>则用于触发其他进程的行为。</p><p>Linux内核并发机制</p><p>管道;消息;共享内存;信号;实时信号</p><p>原子操作时内核同步法中最简单的。在原子操作的基础上,可构建更复杂的锁机制。</p><p>自旋锁(保护临界区)</p><p>Solaris线程同步原语</p><p>互斥锁;信号量;多读者单写者;条件变量;</p><p>Windows7的并发机制</p><p>等待函数;分派器对象;临界区;轻量级读写锁和条件变量;锁无关同步机制</p><p>Android进程间的通信</p><p>IPC中使用的机制是,在内核中新增了一个连接器,他提供了一个轻量级的远程程序调用功能,在内存和事务处理方面非常高效,非常适合嵌入式系统。</p><h2 id="I-0"><a href="#I-0" class="headerlink" title="I/0"></a>I/0</h2><h2 id="基本概念"><a href="#基本概念" class="headerlink" title="基本概念"></a>基本概念</h2><h3 id="文件描述符fd"><a href="#文件描述符fd" class="headerlink" title="文件描述符fd"></a>文件描述符fd</h3><p>文件描述符(<code>File descriptor</code>)是计算机科学中的一个术语,是一个用于表述指向文件的引用的抽象化概念。</p><p>文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于 <code>UNIX、Linux</code> 这样的操作系统。</p><h3 id="缓存-I-O"><a href="#缓存-I-O" class="headerlink" title="缓存 I/O"></a>缓存 I/O</h3><p>缓存 <code>I/O</code> 又被称作标准 <code>I/O</code>,大多数文件系统的默认 <code>I/O</code> 操作都是缓存 <code>I/O</code>。在 <code>Linux</code> 的<code>缓存 I/O</code> 机制中,操作系统会将 <code>I/O</code> 的数据缓存在文件系统的页缓存( <code>page cache</code> )中,也就是说,数据会先被拷贝到操作系统内核的缓冲区中,然后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间。</p><p>缓存 I/O 的缺点:数据在传输过程中需要在应用程序地址空间和内核进行多次数据拷贝操作,这些数据拷贝操作所带来的 <code>CPU</code> 以及内存开销是非常大的。</p><h2 id="IO模式"><a href="#IO模式" class="headerlink" title="IO模式"></a>IO模式</h2><p>刚才说了,对于一次IO访问(以read举例),数据会先被拷贝到操作系统内核的缓冲区中,然后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间。所以说,当一个read操作发生时,它会经历两个阶段:</p><ol><li>等待数据准备</li><li>将数据从内核拷贝到进程中</li></ol><p>正式因为这两个阶段,Linux系统产生了下面五种网络模式的方案。</p><ul><li><code>阻塞 I/O</code>(blocking IO)</li><li><code>非阻塞 I/O</code>(nonblocking IO)</li><li><code>I/O 多路复用</code>( IO multiplexing)</li><li><code>信号驱动 I/O</code>( signal driven IO)</li><li><code>异步 I/O</code>(asynchronous IO)</li></ul><blockquote><p>由于signal driven IO在实际中并不常用,所以这里只提及剩下的四种 IO Model。</p></blockquote><h3 id="阻塞IO"><a href="#阻塞IO" class="headerlink" title="阻塞IO"></a>阻塞IO</h3><p>在 <code>Linux</code> 中,默认情况下所有的 <code>socket</code> 都是 <code>blocking</code> ,一个典型的读操作流程大概是这样:</p><p><img src="https://hadyang.github.io/interview/docs/basic/os/io/images/359a774ea7d5d1e6ac08845023993796.png" alt="img"></p><p>当用户进程调用了 <code>recvfrom</code> 这个系统调用, <code>kernel</code> 就开始了 IO 的第一个阶段:准备数据(对于网络IO来说,很多时候数据在一开始还没有到达。比如,还没有收到一个完整的 <code>UDP</code> 包。这个时候 <code>kernel</code> 就要等待足够的数据到来)。这个过程需要等待,也就是说数据被拷贝到操作系统内核的缓冲区中是需要一个过程的。而在用户进程这边,整个进程会被阻塞(当然,是进程自己选择的阻塞)。当 <code>kernel</code> 一直等到数据准备好了,它就会将数据从 <code>kernel</code> 中拷贝到用户内存,然后 <code>kernel</code> 返回结果,用户进程才解除 <code>block</code> 的状态,重新运行起来。</p><blockquote><p>blocking IO的特点就是在IO执行的两个阶段都被block了</p></blockquote><h3 id="非阻塞-I-O"><a href="#非阻塞-I-O" class="headerlink" title="非阻塞 I/O"></a>非阻塞 I/O</h3><p><code>Linux</code> 下,可以通过设置 <code>socket</code> 使其变为 <code>non-blocking</code> 。当对一个 <code>non-blocking socket</code> 执行读操作时,流程是这个样子:</p><p><img src="https://hadyang.github.io/interview/docs/basic/os/io/images/076dcab40e2b43efa5d1aa97d96a85e2.png" alt="img"></p><p>当用户进程发出 <code>read</code> 操作时,如果 <code>kernel</code> 中的数据还没有准备好,那么它并不会 <code>block</code> 用户进程,而是立刻返回一个 <code>error</code> 。从用户进程角度讲 ,它发起一个 <code>read</code> 操作后,并不需要等待,而是马上就得到了一个结果。用户进程判断结果是一个 <code>error</code> 时,它就知道数据还没有准备好,于是它可以再次发送 <code>read</code> 操作。一旦 <code>kernel</code> 中的数据准备好了,并且又再次收到了用户进程的 <code>system call</code> ,那么它马上就将数据拷贝到了用户内存,然后返回。</p><blockquote><p>nonblocking IO的特点是用户进程需要不断的主动询问kernel数据好了没有</p></blockquote><h3 id="IO多路复用"><a href="#IO多路复用" class="headerlink" title="IO多路复用"></a>IO多路复用</h3><p>IO多路复用就是我们说的 <code>select,poll,epoll</code> ,有些地方也称这种IO方式为 <code>event driven IO</code> 。<code>select/epoll</code> 的好处就在于单个 <code>process</code> 就可以同时处理多个网络连接的 IO 。它的基本原理就是 <code>select,poll,epoll</code> 这个 <code>function</code> 会不断的轮询所负责的所有 <code>socket</code> ,当某个 <code>socket</code> 有数据到达了,就通知用户进程。</p><p><img src="https://hadyang.github.io/interview/docs/basic/os/io/images/c6d2db53d71a8c76c2c9a546c5811773.png" alt="img"></p><p><strong>当用户进程调用了 select,那么整个进程会被 block</strong>,而同时, <code>kernel</code> 会监视所有 <code>select</code> 负责的 <code>socket</code> ,当任何一个 <code>socket</code> 中的数据准备好了, <code>select</code> 就会返回。这个时候用户进程再调用 <code>read</code> 操作,将数据从 <code>kernel</code> 拷贝到用户进程。</p><blockquote><p>I/O 多路复用的特点是通过一种机制一个进程能同时等待多个文件描述符,而这些文件描述符(套接字描述符)其中的任意一个进入读就绪状态,<code>select()</code> 函数就可以返回。</p></blockquote><p>这个图和 <code>blocking IO</code> 的图其实并没有太大的不同,事实上,还更差一些。因为这里需要使用两个 <code>system call</code> (<code>select</code> 和 <code>recvfrom</code>),而 <code>blocking IO</code> 只调用了一个 <code>system call</code> (<code>recvfrom</code>)。但是,用 <code>select</code> 的优势在于它可以同时处理多个 <code>connection</code> 。</p><p>所以,<strong>如果处理的连接数不是很高的话,使用 <code>select/epoll</code> 的 <code>web server</code> 不一定比使用 <code>multi-threading + blocking IO</code> 的 <code>web server</code> 性能更好,可能延迟还更大</strong>。<code>select/epoll</code> 的优势并不是对于单个连接能处理得更快,而是在于能处理更多的连接。</p><p>在IO多路复用实际使用中,对于每一个socket,一般都设置成为 <code>non-blocking</code> ,但是,如上图所示,整个用户的 <code>process</code> 其实是一直被block的。只不过 <code>process</code> 是被 <code>select</code> 这个函数 <code>block</code> ,而不是被 <code>socket IO</code> 给 <code>block</code> 。</p><h4 id="基本概念-1"><a href="#基本概念-1" class="headerlink" title="基本概念"></a>基本概念</h4><p>在 I/O 编程过程中,当需要同时处理多个客户端接入请求时,可以利用多线程或者 <code>I/O 多路复用</code> 技术进行处理。<strong><code>I/O多路复用</code> 技术通过把多个I/O的阻塞复用到同一个selct的阻塞上,从而使得系统在单线程的情况下可以同时处理多个客户端请求</strong>。<strong>与传统的 <code>多线程/多进程</code> 模型比,I/O多路复用的最大优势是系统开销小,系统不需要创建新的额外进程或者线程,也不需要维护这些进程和线程的运行,降低了系统的维护工作量,节省了系统资源</strong>,I/O多路复用的主要应用场景如下。</p><ul><li>服务器需要同时处理多个处于监听状态或者多个连接状态的套接字</li><li>服务器需要同时处理多种网络协议的套接字</li></ul><p>目前支持I/O多路复用的系统调用有 <code>select、pselect、poll、epoll</code>,在Linux网络编程; 过程中,很长一段时间都使用 <code>select</code> 做轮询和网络事件通知,然而 <code>select</code> 的一些固有缺陷导致了它的应用受到了很大的限制。最终 <code>Linux</code> 不得不在新的内核版本中寻找 <code>select</code> 的替代方案,最终选择了 <code>epoll</code>。 <code>epoll</code> 与 <code>select</code> 的原理比较类似,为了克服 <code>select</code> 的缺点, <code>epoll</code> 作了很多重大改进,现总结如下。</p><h5 id="支持一个进程打开的-socket-描述符(FD)不受限制(仅受限于操作系统的最大文件句柄数)。"><a href="#支持一个进程打开的-socket-描述符(FD)不受限制(仅受限于操作系统的最大文件句柄数)。" class="headerlink" title="支持一个进程打开的 socket 描述符(FD)不受限制(仅受限于操作系统的最大文件句柄数)。"></a>支持一个进程打开的 socket 描述符(FD)不受限制(仅受限于操作系统的最大文件句柄数)。</h5><p><strong><code>select</code> 最大的缺陷就是单个进程所打开的 FD 是有一定限制的</strong>,它由 <code>FD_SETSIZE</code> 设置,默认值是 <code>1024</code> 。对于那些需要支持上万个 TCP 连接的大型服务器来说显然太少了。可以选择修改这个宏然后重新编译内核,不过这会带来网络效率的下降。我们也可以通过选择多进程的方案(传统的 Apache 方案)解决这个问题,不过虽然在 Linux上创建进程的代价比较小,但仍旧是不可忽视的,另外,进程间的数据交换非常麻烦,对于 Java 由于没有共享内存,需要通过 <code>Socket</code> 通信或者其他方式进行数据同步,这带来了额外的性能损耗,增加了程序复杂度,所以也不是一种完美的解决方案。值得庆幸的是, <code>epoll</code> 并没有这个限制,它所支持的 <code>FD</code> 上限是操作系统的 <strong>最大文件句柄数</strong>,这个数字远远大于 <code>1024</code> 。例如,在 <code>1 GB</code> 内存的机器上大约是 10万个句柄左右,具体的值可以通过<code>cat /proc/sys/fs/file- max</code> 察看,<strong>通常情况下这个值跟系统的内存关系比较大</strong>。</p><h5 id="I-O效率不会随着FD数目的增加而线性下降。"><a href="#I-O效率不会随着FD数目的增加而线性下降。" class="headerlink" title="I/O效率不会随着FD数目的增加而线性下降。"></a>I/O效率不会随着FD数目的增加而线性下降。</h5><p>传统的 <code>select/poll</code> 另-个致命弱点就是当你拥有一个很大的 <code>socket</code> 集合,由于网络延时或者链路空闲,任一时刻只有少部分的 <code>socket</code> 是“活跃”的,但是 <strong><code>select/poll</code> 每次调用都会线性扫描全部的集合,导致效率呈现线性下降</strong>。 <code>epoll</code> 不存在这个问题,它只会对“活跃”的 <code>socket</code> 进行操作,这是因为在内核实现中 <code>epoll</code> 是根据每个 <code>fd</code> 上面的 <code>callback</code> 函数实现的,那么,只有“活跃”的 <code>socket</code> 才会主动的去调用 <code>callback</code> 函数,其他 <code>idle</code> 状态 <code>socket</code> 则不会。<strong>在这点上, <code>epoll</code> 实现了一个伪 AIO</strong>。针对 <code>epoll</code> 和 <code>select</code> 性能对比的 <code>benchmark</code> 测试表明:<strong>如果所有的 <code>socket</code> 都处于活跃态,例如一个高速 <code>LAN</code> 环境, <code>epoll</code> 并不比 <code>select/poll</code> 效率高太多;相反,如果过多使用 <code>epoll_ ctl</code> , 效率相比还有稍微的下降。但是一旦使用 <code>idleconnections</code> 模拟 <code>WAN</code> 环境,<code>epoll</code> 的效率就远在 <code>select/poll</code> 之上了</strong>。</p><h5 id="使用-mmap-加速内核与用户空间的消息传递"><a href="#使用-mmap-加速内核与用户空间的消息传递" class="headerlink" title="使用 mmap 加速内核与用户空间的消息传递"></a>使用 mmap 加速内核与用户空间的消息传递</h5><p>无论是 <code>select</code>,<code>poll</code> 还是 <code>epoll</code> 都需要内核把 FD 消息通知给用户空间,如何避免不必要的内存复制(Zero Copy)就显得非常重要, <code>epoll</code> 是通过内核和用户空间 <code>mmap</code> 共享同一块内存来实现。</p><h5 id="Epoll-的-API-更加简单"><a href="#Epoll-的-API-更加简单" class="headerlink" title="Epoll 的 API 更加简单"></a>Epoll 的 API 更加简单</h5><p>包括创建一个 <code>epoll</code> 描述符、添加监听事件、阻塞等待所监听的事件发生,关闭 <code>epoll</code> 描述符等。</p><p>值得说明的是,用来克服 <code>select/poll</code> 缺点的方法不只有 <code>epoll</code> , <code>epoll</code> 只是一种 <code>Linux</code> 的 实现方案。在 <code>freeBSD</code> 下有 <code>kqueue</code></p><h3 id="Epoll-边缘触发-amp-水平触发"><a href="#Epoll-边缘触发-amp-水平触发" class="headerlink" title="Epoll 边缘触发&水平触发"></a>Epoll 边缘触发&水平触发</h3><p>epoll 对文件描述符的操作有两种模式:LT(<code>level trigger</code>)和ET(<code>edge trigger</code>)。LT模式是 <strong>默认模式</strong> ,LT模式与ET模式的区别如下:</p><ul><li><strong>LT模式</strong>:当 epoll_wait 检测到描述符事件发生并将此事件通知应用程序,应用程序可以不立即处理该事件。下次调用 epoll_wait 时,会再次响应应用程序并通知此事件。</li><li><strong>ET模式</strong>:当 epoll_wait 检测到描述符事件发生并将此事件通知应用程序,应用程序必须立即处理该事件。如果不处理,下次调用 epoll_wait 时,不会再次响应应用程序并通知此事件。</li></ul><blockquote><p>ET模式 在很大程度上减少了 epoll 事件被重复触发的次数,因此 <strong>效率要比LT模式高</strong>。epoll 工作在ET模式的时候,<strong>必须使用非阻塞套接口</strong>,以避免由于一个文件句柄的阻塞读/阻塞写操作把处理多个文件描述符的任务饿死。</p></blockquote><h2 id="异步-I-O"><a href="#异步-I-O" class="headerlink" title="异步 I/O"></a>异步 I/O</h2><p><img src="https://hadyang.github.io/interview/docs/basic/os/io/images/3b385bdf805241ee6cd0d4634bd7510a.png" alt="img"></p><p>用户进程发起 <code>read</code> 操作之后,立刻就可以开始去做其它的事。而另一方面,从 <code>kernel</code> 的角度,当它受到一个 <code>asynchronous read</code> 之后,首先它会立刻返回,所以不会对用户进程产生任何 <code>block</code> 。然后,<code>kernel</code> 会等待数据准备完成,然后将数据拷贝到用户内存,当这一切都完成之后,<code>kernel</code> 会给用户进程发送一个 <code>signal</code> ,告诉它 <code>read</code> 操作完成了。</p><h2 id="blocking-vs-non-blocking"><a href="#blocking-vs-non-blocking" class="headerlink" title="blocking vs non-blocking"></a>blocking vs non-blocking</h2><p>调用 <code>blocking IO</code> 会一直 <code>block</code> 住对应的进程直到操作完成,而 <code>non-blocking IO</code> 在 <code>kernel</code> 还准备数据的情况下会立刻返回。</p><h2 id="synchronous-IO-vs-asynchronous-IO"><a href="#synchronous-IO-vs-asynchronous-IO" class="headerlink" title="synchronous IO vs asynchronous IO"></a>synchronous IO vs asynchronous IO</h2><p>在说明<code>synchronous IO</code>和<code>asynchronous IO</code>的区别之前,需要先给出两者的定义。 <code>POSIX</code> 的定义是这样子的:</p><ul><li>A synchronous I/O operation causes the requesting process to be blocked until that I/O operation completes;</li><li>An asynchronous I/O operation does not cause the requesting process to be blocked;</li></ul><p>两者的区别就在于 <code>synchronous IO</code> 做 <code>IO operation</code> 的时候会将 <code>process</code> 阻塞。按照这个定义,之前所述的 <code>blocking IO,non-blocking IO,IO multiplexing</code> 都属于 <code>synchronous IO</code>。</p><p>有人会说,<code>non-blocking IO</code> 并没有被 <code>block</code> 啊。这里有个非常 <strong>狡猾</strong> 的地方,定义中所指的 <code>IO operation</code> 是指真实的 IO 操作,就是例子中的 <code>recvfrom</code> 这个 <code>system call</code> 。<code>non-blocking IO</code> 在执行 <code>recvfrom</code> 这个 <code>system call</code> 的时候,如果 <code>kernel</code> 的数据没有准备好,这时候不会 <code>block</code> 进程。但是,当 <code>kernel</code> 中数据准备好的时候,<code>recvfrom</code> 会将数据从 <code>kernel</code> 拷贝到用户内存中,这个时候进程是被 <code>block</code> 了,在这段时间内,进程是被 <code>block</code> 的。</p><p>而 <code>asynchronous IO</code> 则不一样,当进程发起 <code>IO</code> 操作之后,就直接返回再也不理睬了,直到 <code>kernel</code> 发送一个信号,告诉进程说IO完成。在这整个过程中,进程完全没有被 <code>block</code> 。</p><p>参考:</p><p>【1】<a href="https://segmentfault.com/a/1190000003063859" target="_blank" rel="noopener">https://segmentfault.com/a/1190000003063859</a></p><p>【2】<a href="https://hadyang.github.io/interview/docs/basic/os/io/" target="_blank" rel="noopener">https://hadyang.github.io/interview/docs/basic/os/io/</a></p><h2 id="内存:"><a href="#内存:" class="headerlink" title="内存:"></a>内存:</h2><p>内存管理</p><p>单道程序设计系统中,内存划分为两部分,一部分供操作系统使用(驻留监控程序,内核),另一部分供当前正在执行的程序使用。在多道程序设计系统中,必须在内存中进一步划分用户部分,以满足多个进程的要求,细分的任务由操作系统动态完成,这称为内存管理。</p><p>内存管理术语:页框(内存中固定长度的块);页(二级存储器中固定长度的块);段(二级存储器中变长数据块);</p><p>内存管理需求:</p><p>重定位;保护;共享;逻辑组织;物理组织;</p><p>重定位:</p><p>内存分区:</p><p>固定分区的内部碎片</p><p>动态分区的外部碎片</p><p>放置算法:</p><p>固定分配</p><p>动态分配</p><p>最佳适配</p><p>首次适配</p><p>下次适配</p><p>动态分配克服外部碎片的方法:压缩</p><p>伙伴系统(在并行系统中有许多应用):</p><p> UNIX内核存储分配中使用了一种经过改进后的伙伴系统</p><p>重定位的硬件支持(针对进程的换进换出的地址变化的问题):重定位加载器</p><p>分页:</p><p>分页对程序员是透明的,而分段对程序员是可见的</p><p>内存管理是操作系统中最重要、最复杂的任务之一。内存管理吧内存视为一个资源,可以分配给许多活动进程,或由多个活动进程共享。为有效地使用处理器和I/O设备,需要在内存中保留尽可能多地进程。此外,程序员在开发程序时最好能不受程序大小地限制。</p><p>内存管理的基本工具是分页和分段。</p><p>虚拟内存</p><p>虚拟内存术语</p><p>虚拟内存;虚拟地址;虚拟地址空间;地址空间;实地址;</p><p>进程中的所有内存访问都是逻辑地址,这些逻辑地址会在运行时动态地转换为物理地址。这意味着一个进程可被换入或换出内存,因此进程可在执行过程地不同时刻占据内存中地不同区域。</p><p>一个进程可划分为许多块,在执行过程中,这些块不需要连续地位于内存中,动态运行时地址转换和也变或段表的使用使得这一点成为可能。</p><p>局部性原理:描述了一个进程中程序和数据引用的集簇倾向。局部性原理表明虚拟内存是可行的,要使虚存比较使用并且高效。首先,必须由对所采用分页或分段方案的硬件支持;其次,操作系统必须有管理页或段在内存和辅助存储器之间移动的软件。</p><p>系统抖动:处理器的大部分时间都用于交换块而非执行指令</p><p>操作系统软件</p><p>是否使用虚存技术</p><p>是使用分页还是使用分段,或同时使用二者</p><p>为各种存储管理特征采用的算法。</p><p>分页</p><p>页表结构与设计</p><p>一级或多级方案来组织大型页表:页表大小于虚拟地址空间的大小成正比。</p><p>倒排页表:页号部分使用一个简单的散列函数映射到散列表中。</p><p>调度</p><p>转换检测缓冲区:为克服内存访问时间加倍,设置转换检测缓冲区,类似于高速缓冲储存器</p><p>每次虚存的访问都可能会引起两次物理内存访问:一次取相应的页表项,另一次取需要的数据。</p><p>虚存系统需要与高速缓系统交互</p><p>页尺寸设计:</p><p>内部碎片</p><p>基于大多数辅存设备的物理特性,希望页尺寸比较大,从而实现更有效的数据块传送。</p><p>与物理内存的大小和程序大小有关。</p><p>页尺寸对却也中断发生概率的影响使得硬件设计决策复杂,另外,缺页率还取决于分配给一个进程的页框数量。软件策略(分配给每个进程的内存总量)影响着硬件设计决策。</p><p>对于给定大小的TLB,当进程的内存大小增加且局部性降低时,TLB访问的命中率降低。</p><p>操作系统有时支持多种页尺寸,但是大多数商业系统仍然只支持一种页尺寸。</p><p>分段</p><p>优点:</p><p>简化了第不断增长的数据结构的处理</p><p>允许程序独立地改变或重新编译,而不是要求整个程序集重新链接和重新加载;</p><p>有助于进程间的共享</p><p>有助于保护</p><p>段页式:</p><p>分段和妇女也俄油长处。分页对程序员是透明的,它消除了外部碎片,因而能更有效地使用内存。此外,由于移入或移出内存的块是固定的、大小相等的,因而有可能开发出更精致的存储管理算法。分段对程序员是可见的,它具有处理不断增长的数据结构的能力,及支持共享和保护的能力。为结合二者的优点,有些系统配备了特殊的处理器硬件和操作系统软件来同时支持分段与分页。</p><p>虚存的实现需要硬件的支持</p><p>读取策略(决定某页何时取入内存)</p><p>放置策略(决定进程快驻留在实存中什么位置)</p><p><strong>置换策略</strong>和高速缓存大小</p><p>能提高分页的性能并允许使用较简单的页面置换策略的一种方法是<strong>页缓冲</strong>。</p><p>驻留集管理(为进程分配多大的内存)</p><p>解决可变分配、全局范围策略潜在性能问题的一种方法是使用页缓冲。</p><p>工作集策略</p><p>工作集的概念可用于知道有关驻留集大小的策略</p><p>缺页中断频率算法</p><p>可变采样间隔的工作集</p><p>清除策略(用于确定何时将已修改的一页写回辅存)</p><p>加载控制会影响到驻留在内存中进程的数量,这称为系统并发度。系统并发度会影响处理器的利用率</p><p>UNIX内存管理和Solaris内存管理</p><p>分页式虚存方案;内核内存分配器</p><p>Linux内存管理</p><p>进程虚拟没存和内核内存分配</p><p>多道程序设计的关键是调度。</p><p>调度类型:</p><p>长程调度:决定加入待执行进程池</p><p>中程调度:决定加入部分或全部位于内存中的进程合集</p><p>短程调度:决定处理器执行哪个可运行进程</p><p>I/O调度:决定可用I/O设备处理那个进程挂起的I/O亲求</p><p>处理器调度的目的是,满足系统目标(响应时间、吞吐率、处理器效率)的方式,把进程分配到一个或多个处理器上执行。</p><p>调度——调度属于队列管理问题,用于在排队环境中减少延迟并优化性能</p><p>单处理器调度</p><p>多处理器和实时调度</p><p>长程调度:控制了系统的并发度</p><p>中程调度:换入决定取决于管理系统并发度的需求。</p><p>短程调度(分派程序):</p><p>导致当前进程阻塞或抢占当前运行进程的事件发生时,调用短程调度程序。这类事件包括:</p><p>时钟中断;I/O中断;操作系统调用;信号(信号量)</p><p>调度算法:</p><p>短程调度规则</p><p>优先级的运用</p><p>决策模式:</p><p>抢占:虽然开销大,但是,能为所有进程提供较好的服务。</p><p>非抢占:</p><p>先来先服务:适合于处理器密集型的进程,但可能导致处理器和I/O设备都未得到充分利用。</p><p>轮转法:在通用的分时系统或事务处理系统中特别有效,但是 ,对处理器密集型进程和I/O密集型进程的处理不同。会让处理器密集型进程不公平地使用了大部分处理器时间。</p><p>虚拟轮转算法:避免轮转算法的不公平性</p><p>最短进程优先(SPN):适用于短进程,但是,难点在于需要知道或至少需要估计每个进程所需的处理时间。风险在于,只要持续不断提供更短的进程,长进程就有可能饥饿。</p><p>基于过去的时间序列预测将来的一种更为常用的技术是<strong>指数平均法,有益于最短进程优先</strong></p><p>最短剩余时间:在SPN上增加了抢占机制的策略。</p><p>最短响应比优先:</p><p>反馈法:基于抢占原则并使用动态优先级机制</p><p>反馈q=1:</p><p>反馈q=2:</p><p>排队分析</p><p>通过一些分析(排队分析、仿真建模、公平共享调度),得出了调度测量性能比较的通用结论。</p><p>假设</p><p>多处理器和实时调度</p><p>多处理器系统分类:</p><p>松耦合、分布式多处理器、集群:</p><p>专用处理器:如I/O处理器</p><p>紧耦合多处理器:由一系列共享同一个内存并受操作系统完全控制的处理器组成。</p><p>多处理器调度的设计问题:</p><p>把进程分配到处理器</p><p>在单处理器上使用多道程序设计</p><p>一个进程的实际分派;</p><p>解决以上三个问题所用的方法通常取决于应用程序的粒度等级和可用处理器的数量</p><p>实时调度</p><p>实时计算正在成为越来越重要的原则。操作系统,特别市调度程序,可能是实时系统中最重要的组件。目前实时系统应用的例子包括实验控制、过程控制设别、机器人、空中交通管制、电信、军事指挥与控制系统,下一代系统还包括自动驾驶汽车、弹簧关节机器人控制器、智能制造中的系统查找、空间站和海底勘探。</p><p>实时计算:系统的正确性不仅取决于计算的逻辑结果,而且取决于产生结果的时间。</p><p>实时操作系统的特点:</p><p>实时调度</p><p>限期调度</p><p>速率单调调度</p><p>优先级反转</p><p>Linux调度</p><p>实时调度</p><p>非实时调度</p><p>UNIX SVR4调度</p><p>FreeBSD调度程序</p><p>优先级</p><p>对称多处理器与多核支持</p><p>Windows调度</p><p>多处理器调度比较复杂,需要花比较多的时间(2天左右)来读,</p><p>输入/输出和文件</p><p>由于存在许多不同的设备及这些设备的应用,因此,很难有一种通用的、一致的解决方案。</p><h2 id="文件管理"><a href="#文件管理" class="headerlink" title="文件管理"></a>文件管理</h2><h2 id="嵌入式系统"><a href="#嵌入式系统" class="headerlink" title="嵌入式系统"></a>嵌入式系统</h2><h2 id="虚拟机"><a href="#虚拟机" class="headerlink" title="虚拟机"></a>虚拟机</h2><h2 id="计算机安全技术"><a href="#计算机安全技术" class="headerlink" title="计算机安全技术"></a>计算机安全技术</h2><h2 id="常见问题"><a href="#常见问题" class="headerlink" title="常见问题"></a>常见问题</h2><p>PE文件</p><p>PE文件的全称是<code>Portable Executable</code>,意为可移植的可执行的文件,常见的EXE、DLL、OCX、SYS、COM都是PE文件,PE文件是微软Windows操作系统上的程序文件(可能是间接被执行,如DLL)。</p><hr><h3 id="什么是活锁?与死锁有和区别?"><a href="#什么是活锁?与死锁有和区别?" class="headerlink" title="什么是活锁?与死锁有和区别?"></a>什么是活锁?与死锁有和区别?</h3><p>活锁指的是 <strong>任务或者执行者没有被阻塞,由于某些条件没有满足,导致一直重复尝试,失败,尝试,失败</strong>。 活锁和死锁的区别在于,处于活锁的实体是在不断的改变状态,所谓的“活”, 而处于死锁的实体表现为等待;<strong>活锁有可能自行解开,死锁则不能</strong>。</p><p>活锁应该是一系列进程在轮询地等待某个不可能为真的条件为真。活锁的时候进程是不会<code>blocked</code>,这会导致耗尽CPU资源。</p><p>为解决活锁可以引入一些随机性,例如如果检测到冲突,那么就暂停随机的一定时间进行重试。这回大大减少碰撞的可能性。典型的例子是以太网的<code>CSMA/CD</code>检测机制。</p><hr><h3 id="直接寻址与间接寻址?"><a href="#直接寻址与间接寻址?" class="headerlink" title="直接寻址与间接寻址?"></a>直接寻址与间接寻址?</h3><p>寻址方式就是处理器根据指令中给出的地址信息来寻找物理地址的方式,是确定本条指令的数据地址以及下一条要执行的指令地址的方法。在操作系统中分为指令寻址和操作数寻址。</p><p><strong>指令寻址</strong>:在内存中查找指令的方式。</p><ul><li><strong>顺序寻址方式</strong>:即采用PC计数器来计数指令的顺序;</li><li><strong>跳跃寻址方式</strong>:下条指令的地址码不是由程序计数器给出,而是由本条指令给出。</li></ul><p><strong>操作数寻址</strong>:形成操作数的有效地址的方法称为操作数的寻址方式。</p><ul><li><strong>立即寻址</strong>:操作数作为指令的一部分而直接写在指令中;</li><li><strong>直接寻址</strong>:直接寻址是一种基本的寻址方法。<strong>在指令格式的地址的字段中直接指出操作数在内存的地址。由于操作数的地址直接给出而不需要经过某种变换</strong>,所以称这种寻址方式为直接寻址方式。</li><li><strong>简介寻址</strong>:间接寻址是相对直接寻址而言的,在间接寻址的情况下,<strong>指令地址字段中的形式地址不是操作数的真正地址,而是操作数地址的指示器,或者说此形式地址单元的内容才是操作数的有效地址</strong>。</li></ul><hr><h3 id="如何从用户态切换到内核态?"><a href="#如何从用户态切换到内核态?" class="headerlink" title="如何从用户态切换到内核态?"></a>如何从用户态切换到内核态?</h3><ol><li>程序请求系统服务,执行系统调用</li><li>程序运行期间产生中断事件,运行程序被中断,转向中断处理程序处理</li><li>程序运行时产生异常事件,运行程序被打断,转向异常处理程序。</li></ol><p>这三种情况都是通过中断机制发生,可以说 <strong>中断和异常是用户态到内核态转换的仅有途径</strong>。</p><hr><h3 id="实时操作系统和分时操作系统的区别?"><a href="#实时操作系统和分时操作系统的区别?" class="headerlink" title="实时操作系统和分时操作系统的区别?"></a>实时操作系统和分时操作系统的区别?</h3><ul><li><strong>分时操作系统</strong>:<strong>多个联机用户同时适用一个计算机系统在各自终端上进行交互式会话,程序、数据和命令均在会话过程中提供,以问答方式控制程序运行</strong>。系统把处理器的时间划分为时间片轮流分配给各个连接终端。</li><li><strong>实时操作系统</strong>:当外部时间或数据产生时,能够对其予以接受并以足够快的速度进行处理,所得结果能够在规定时间内控制生产过程或对控制对象作出快速响应,并控制所有实时任务协调的操作系统。因而,<strong>提供及时响应和高可靠性是其主要特点</strong>。实时操作系统有硬实时和软实时之分,硬实时要求在规定的时间内必须完成操作,这是在操作系统设计时保证的;软实时则只要按照任务的优先级,尽可能快地完成操作即可。我们通常使用的操作系统在经过一定改变之后就可以变成实时操作系统。</li></ul><p>下面还要补充一个批处理操作系统:<strong>批处理是指用户将一批作业提交给操作系统后就不再干预,由操作系统控制它们自动运行。这种采用批量处理作业技术的操作系统称为批处理操作系统</strong>。批处理操作系统分为单道批处理系统和多道批处理系统。批处理操作系统不具有交互性,它是为了提高CPU的利用率而提出的一种操作系统。</p><p>如果某个操作系统兼有批处理、分时和实时处理的全部或两种功能,我们称为通用操作系统。</p></div><hr><div class="reprint" id="reprint-statement"><div class="reprint__author"><span class="reprint-meta" style="font-weight:700"><i class="fas fa-user">文章作者:</i></span> <span class="reprint-info"><a href="https://hyl2048.github.io" rel="external nofollow noreferrer">yulin</a></span></div><div class="reprint__type"><span class="reprint-meta" style="font-weight:700"><i class="fas fa-link">文章链接:</i></span> <span class="reprint-info"><a href="https://hyl2048.github.io/1079.html">https://hyl2048.github.io/1079.html</a></span></div><div class="reprint__notice"><span class="reprint-meta" style="font-weight:700"><i class="fas fa-copyright">版权声明:</i></span> <span class="reprint-info">本博客所有文章除特別声明外,均采用 <a href="https://creativecommons.org/licenses/by/4.0/deed.zh" rel="external nofollow noreferrer" target="_blank">CC BY 4.0</a> 许可协议。转载请注明来源 <a href="https://hyl2048.github.io" target="_blank">yulin</a> !</span></div></div><script async defer>document.addEventListener("copy", function (e) {
let toastHTML = '<span>复制成功,请遵循本文的转载规则</span><button class="btn-flat toast-action" onclick="navToReprintStatement()" style="font-size: smaller">查看</a>';
M.toast({html: toastHTML})
});
function navToReprintStatement() {
$("html, body").animate({scrollTop: $("#reprint-statement").offset().top - 80}, 800);
}</script><div class="tag_share" style="display:block"><div class="post-meta__tag-list" style="display:inline-block"><div class="article-tag"><span class="chip bg-color">无标签</span></div></div><div class="post_share" style="zoom:80%;width:fit-content;display:inline-block;float:right;margin:-.15rem 0"><link rel="stylesheet" href="/libs/share/css/share.min.css"><div id="article-share"><div class="social-share" data-sites="twitter,facebook,google,qq,qzone,wechat,weibo,douban,linkedin" data-wechat-qrcode-helper="<p>微信扫一扫即可分享!</p>"></div><script src="/libs/share/js/social-share.min.js"></script></div></div></div><style>#reward{margin:40px 0;text-align:center}#reward .reward-link{font-size:1.4rem;line-height:38px}#reward .btn-floating:hover{box-shadow:0 6px 12px rgba(0,0,0,.2),0 5px 15px rgba(0,0,0,.2)}#rewardModal{width:320px;height:350px}#rewardModal .reward-title{margin:15px auto;padding-bottom:5px}#rewardModal .modal-content{padding:10px}#rewardModal .close{position:absolute;right:15px;top:15px;color:rgba(0,0,0,.5);font-size:1.3rem;line-height:20px;cursor:pointer}#rewardModal .close:hover{color:#ef5350;transform:scale(1.3);-moz-transform:scale(1.3);-webkit-transform:scale(1.3);-o-transform:scale(1.3)}#rewardModal .reward-tabs{margin:0 auto;width:210px}.reward-tabs .tabs{height:38px;margin:10px auto;padding-left:0}.reward-content ul{padding-left:0!important}.reward-tabs .tabs .tab{height:38px;line-height:38px}.reward-tabs .tab a{color:#fff;background-color:#ccc}.reward-tabs .tab a:hover{background-color:#ccc;color:#fff}.reward-tabs .wechat-tab .active{color:#fff!important;background-color:#22ab38!important}.reward-tabs .alipay-tab .active{color:#fff!important;background-color:#019fe8!important}.reward-tabs .reward-img{width:210px;height:210px}</style><div id="reward"><a href="#rewardModal" class="reward-link modal-trigger btn-floating btn-medium waves-effect waves-light red">赏</a><div id="rewardModal" class="modal"><div class="modal-content"><a class="close modal-close"><i class="fas fa-times"></i></a><h4 class="reward-title">你的赏识是我前进的动力</h4><div class="reward-content"><div class="reward-tabs"><ul class="tabs row"><li class="tab col s6 alipay-tab waves-effect waves-light"><a href="#alipay">支付宝</a></li><li class="tab col s6 wechat-tab waves-effect waves-light"><a href="#wechat">微 信</a></li></ul><div id="alipay"><img src="/medias/reward/alipay.jpg" class="reward-img" alt="支付宝打赏二维码"></div><div id="wechat"><img src="/medias/reward/wechat.jpg" class="reward-img" alt="微信打赏二维码"></div></div></div></div></div></div><script>$(function(){$(".tabs").tabs()})</script></div></div><link rel="stylesheet" href="/libs/gitalk/gitalk.css"><link rel="stylesheet" href="/css/my-gitalk.css"><div class="card gitalk-card" data-aos="fade-up"><div class="comment_headling" style="font-size:20px;font-weight:700;position:relative;padding-left:20px;top:15px;padding-bottom:5px"><i class="fas fa-comments fa-fw" aria-hidden="true"></i> <span>评论</span></div><div id="gitalk-container" class="card-content"></div></div><script src="/libs/gitalk/gitalk.min.js"></script><script>let gitalk = new Gitalk({
clientID: '9e23a93e6d565c5b255e',
clientSecret: '3b42941e0d79049bad19fac40d7d0c1cae96edbe',
repo: 'hyl2048.github.io',
owner: 'hyl2048',
admin: "hyl2048",
id: '2020-08-19T22-38-51',
distractionFreeMode: false, // Facebook-like distraction free mode
proxy: "https://antiproxy.hyl2048.workers.dev/?https://github.com/login/oauth/access_token"
});
gitalk.render('gitalk-container');</script><article id="prenext-posts" class="prev-next articles"><div class="row article-row"><div class="article col s12 m6" data-aos="fade-up"><div class="article-badge left-badge text-color"><i class="fas fa-chevron-left"></i> 上一篇</div><div class="card"><a href="/63394.html"><div class="card-image"><img src="/medias/featureimages/21.jpg" class="responsive-img" alt="数据库"> <span class="card-title">数据库</span></div></a><div class="card-content article-content"><div class="summary block-with-text">InnoDB 索引数据存储当 InnoDB 存储数据时,它可以使用不同的行格式进行存储;MySQL 5.7 版本支持以下格式的行存储方式: Antelope 是 InnoDB 最开始支持的文件格式,它包含两种行格式 Compact 和</div><div class="publish-info"><span class="publish-date"><i class="far fa-clock fa-fw icon-date"></i> 2020-08-19</span><span class="publish-author"><i class="fas fa-bookmark fa-fw icon-category"></i> <a href="/categories/Basic/" class="post-category">Basic</a></span></div></div></div></div><div class="article col s12 m6" data-aos="fade-up"><div class="article-badge right-badge text-color">下一篇 <i class="fas fa-chevron-right"></i></div><div class="card"><a href="/28758.html"><div class="card-image"><img src="/medias/featureimages/9.jpg" class="responsive-img" alt="计算机网络"> <span class="card-title">计算机网络</span></div></a><div class="card-content article-content"><div class="summary block-with-text">计算机网络 概览 完成端到端传输的工作,可简要分为三类工作 ① 文件传送模块(应用程序间)应用层(表示层、会话层) 应用层协议 TELNET、FTP、SMTP、HTTP 报文 ②</div><div class="publish-info"><span class="publish-date"><i class="far fa-clock fa-fw icon-date"></i> 2020-08-19</span><span class="publish-author"><i class="fas fa-bookmark fa-fw icon-category"></i> <a href="/categories/Basic/" class="post-category">Basic</a></span></div></div></div></div></div></article></div><script>$("#articleContent").on("copy",function(e){if(void 0!==window.getSelection){var n=window.getSelection();if(!((""+n).length<Number.parseInt("120"))){var t=document.getElementsByTagName("body")[0],o=document.createElement("div");o.style.position="absolute",o.style.left="-99999px",t.appendChild(o),o.appendChild(n.getRangeAt(0).cloneContents()),"PRE"===n.getRangeAt(0).commonAncestorContainer.nodeName&&(o.innerHTML="<pre>"+o.innerHTML+"</pre>");var i=document.location.href;o.innerHTML+='<br />来源: huang<br />文章作者: yulin<br />文章链接: <a href="'+i+'">'+i+"</a><br />本文章著作权归作者所有,任何形式的转载都请注明出处。",n.selectAllChildren(o),window.setTimeout(function(){t.removeChild(o)},200)}}})</script><script src="/libs/codeBlock/codeBlockFuction.js"></script><script src="/libs/codeBlock/codeLang.js"></script><script src="/libs/codeBlock/codeCopy.js"></script><script src="/libs/codeBlock/codeShrink.js"></script><style>code[class*=language-],pre[class*=language-]{white-space:pre!important}</style></div><div id="toc-aside" class="expanded col l3 hide-on-med-and-down"><div class="toc-widget"><div class="toc-title"><i class="far fa-list-alt"></i> 目录</div><div id="toc-content"></div></div></div></div><div id="floating-toc-btn" class="hide-on-med-and-down"><a class="btn-floating btn-large bg-color"><i class="fas fa-list-ul"></i></a></div><script src="/libs/tocbot/tocbot.min.js"></script><script>$(function () {
tocbot.init({
tocSelector: '#toc-content',
contentSelector: '#articleContent',
headingsOffset: -($(window).height() * 0.4 - 45),
collapseDepth: Number('0'),
headingSelector: 'h2, h3, h4'
});
// modify the toc link href to support Chinese.
let i = 0;
let tocHeading = 'toc-heading-';
$('#toc-content a').each(function () {
$(this).attr('href', '#' + tocHeading + (++i));
});
// modify the heading title id to support Chinese.
i = 0;
$('#articleContent').children('h2, h3, h4').each(function () {
$(this).attr('id', tocHeading + (++i));
});
// Set scroll toc fixed.
let tocHeight = parseInt($(window).height() * 0.4 - 64);
let $tocWidget = $('.toc-widget');
$(window).scroll(function () {
let scroll = $(window).scrollTop();
/* add post toc fixed. */
if (scroll > tocHeight) {
$tocWidget.addClass('toc-fixed');
} else {
$tocWidget.removeClass('toc-fixed');
}
});
/* 修复文章卡片 div 的宽度. */
let fixPostCardWidth = function (srcId, targetId) {
let srcDiv = $('#' + srcId);
if (srcDiv.length === 0) {
return;
}
let w = srcDiv.width();
if (w >= 450) {
w = w + 21;
} else if (w >= 350 && w < 450) {
w = w + 18;
} else if (w >= 300 && w < 350) {
w = w + 16;
} else {
w = w + 14;
}
$('#' + targetId).width(w);
};
// 切换TOC目录展开收缩的相关操作.
const expandedClass = 'expanded';
let $tocAside = $('#toc-aside');
let $mainContent = $('#main-content');
$('#floating-toc-btn .btn-floating').click(function () {
if ($tocAside.hasClass(expandedClass)) {
$tocAside.removeClass(expandedClass).hide();
$mainContent.removeClass('l9');
} else {
$tocAside.addClass(expandedClass).show();
$mainContent.addClass('l9');
}
fixPostCardWidth('artDetail', 'prenext-posts');
});
});</script></main><script src="https://cdn.bootcss.com/mathjax/2.7.5/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script><script>MathJax.Hub.Config({tex2jax:{inlineMath:[["$","$"],["(",")"]]}})</script><footer class="page-footer bg-color"><link rel="stylesheet" href="/libs/aplayer/APlayer.min.css"><style>.aplayer .aplayer-lrc p{font-size:12px;font-weight:700;line-height:16px!important}.aplayer .aplayer-lrc p.aplayer-lrc-current{font-size:15px;color:#42b983}.aplayer.aplayer-fixed.aplayer-narrow .aplayer-body{left:-66px!important}.aplayer.aplayer-fixed.aplayer-narrow .aplayer-body:hover{left:0!important}</style><div><div><meting-js class="col l8 offset-l2 m10 offset-m1 s12" server="netease" type="playlist" id="503838841" fixed="true" autoplay theme="#42b983" loop order="random" preload="auto" volume="0.7" list-folded="true"></meting-js></div></div><script src="/libs/aplayer/APlayer.min.js"></script><script src="https://cdn.jsdelivr.net/npm/meting@2/dist/Meting.min.js"></script><div class="container row center-align"><div class="col s12 m8 l8 copy-right">©huang. 版权所有 <i class="fa fa-area-chart"></i> 站点总字数: <span class="white-color">105.1k</span><br><span id="sitetime"></span><br><span id="busuanzi_container_site_pv" style="display:none"><i class="fa fa-heart-o"></i> 本站总访问量<span id="busuanzi_value_site_pv" class="white-color"></span></span> <span id="busuanzi_container_site_uv" style="display:none">人次, 访客数<span id="busuanzi_value_site_uv" class="white-color"></span> 人.</span></div><div class="col s12 m4 l4 social-link social-statis"><a href="https://github.com/hyl2048" class="tooltipped" target="_blank" data-tooltip="访问我的GitHub" data-position="top" data-delay="50"><i class="fab fa-github"></i></a><a href="mailto:[email protected]" class="tooltipped" target="_blank" data-tooltip="邮件联系我" data-position="top" data-delay="50"><i class="fas fa-envelope-open"></i></a><a href="tencent://AddContact/?fromId=50&fromSubId=1&subcmd=all&uin=2745506937" class="tooltipped" target="_blank" data-tooltip="QQ联系我: 2745506937" data-position="top" data-delay="50"><i class="fab fa-qq"></i></a><a href="/atom.xml" class="tooltipped" target="_blank" data-tooltip="RSS 订阅" data-position="top" data-delay="50"><i class="fas fa-rss"></i></a></div></div></footer><div class="progress-bar"></div><script>$(document).ready(function(){var e=setInterval(function(){"none"!=document.getElementById("busuanzi_container_site_pv").style.display&&($("#busuanzi_value_site_pv").html(parseInt($("#busuanzi_value_site_pv").html())+n),clearInterval(e));"none"!=$("#busuanzi_container_site_pv").css("display")&&($("#busuanzi_value_site_uv").html(parseInt($("#busuanzi_value_site_uv").html())+t),clearInterval(e))},50),n=0,t=0})</script><script language="javascript">function siteTime(){window.setTimeout("siteTime()",1e3);var e=36e5,t=24*e,o=new Date,i=o.getFullYear(),a=o.getMonth()+1,n=o.getDate(),r=o.getHours(),l=o.getMinutes(),s=o.getSeconds(),M=Date.UTC(2020,3,28,0,0,0),g=Date.UTC(i,a,n,r,l,s)-M,m=Math.floor(g/31536e6),T=Math.floor(g/t-365*m),f=Math.floor((g-(365*m+T)*t)/e),h=Math.floor((g-(365*m+T)*t-f*e)/6e4),u=Math.floor((g-(365*m+T)*t-f*e-6e4*h)/1e3);document.getElementById("sitetime").innerHTML="本站已运行 "+m+" 年 "+T+" 天 "+f+" 小时 "+h+" 分钟 "+u+" 秒"}siteTime()</script><div id="searchModal" class="modal"><div class="modal-content"><div class="search-header"><span class="title"><i class="fas fa-search"></i> 搜索</span> <input type="search" id="searchInput" name="s" placeholder="请输入搜索的关键字" class="search-input"></div><div id="searchResult"></div></div></div><script src="/js/search.js"></script><script>$(function(){searchFunc("/search.xml","searchInput","searchResult")})</script><div id="backTop" class="top-scroll"><a class="btn-floating btn-large waves-effect waves-light" href="#!"><i class="fas fa-arrow-up"></i></a></div><script src="/libs/materialize/materialize.min.js"></script><script src="/libs/masonry/masonry.pkgd.min.js"></script><script src="/libs/aos/aos.js"></script><script src="/libs/scrollprogress/scrollProgress.min.js"></script><script src="/libs/lightGallery/js/lightgallery-all.min.js"></script><script src="/js/matery.js"></script><script>var _hmt=_hmt||[];!function(){var e=document.createElement("script");e.src="https://hm.baidu.com/hm.js?";var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t)}()</script><script>!function(){var t=document.createElement("script"),e=window.location.protocol.split(":")[0];t.src="https"===e?"https://zz.bdstatic.com/linksubmit/push.js":"http://push.zhanzhang.baidu.com/push.js";var s=document.getElementsByTagName("script")[0];s.parentNode.insertBefore(t,s)}()</script><script src="/libs/others/clicklove.js" async></script><script async src="/libs/others/busuanzi.pure.mini.js"></script><script src="/libs/instantpage/instantpage.js" type="module"></script></body></html>