-
Notifications
You must be signed in to change notification settings - Fork 0
/
local-search.xml
96 lines (45 loc) · 135 KB
/
local-search.xml
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
92
93
94
95
96
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>线代</title>
<link href="/2023/02/24/%E7%BA%BF%E4%BB%A3/"/>
<url>/2023/02/24/%E7%BA%BF%E4%BB%A3/</url>
<content type="html"><![CDATA[<h2 id="1-n-阶行列式"><a href="#1-n-阶行列式" class="headerlink" title="1. $n$阶行列式"></a>1. $n$阶行列式</h2><h3 id="1-1-相关概念"><a href="#1-1-相关概念" class="headerlink" title="1.1. 相关概念"></a>1.1. 相关概念</h3><h4 id="1-1-1-全排列的逆序数、对换"><a href="#1-1-1-全排列的逆序数、对换" class="headerlink" title="1.1.1. 全排列的逆序数、对换"></a>1.1.1. 全排列的逆序数、对换</h4><ul><li><p>逆序数</p><p>$p_1 p_2 \cdots p_n$是$1,2,\cdots ,n$的一个排列。把排在$p_i$前面且比$p_i$大的数的个数$t_i$称为全排列$p_1p_2\cdots p_n$中$p_i$的逆序数,把这个排列中各数逆序数之和<br>$$<br>t_1+t_2+\cdots+t_n<br>$$<br>称为这个排列的<strong>逆序数</strong>,记为$t(p_1p_2\cdots p_n)$</p><p>逆序数为奇数的排列称为<strong>奇排列</strong>,逆序数为偶数的排列称为<strong>偶排列</strong>。排列$1,2,\cdots, n$也称<strong>自然排列</strong>。</p></li><li><p>对换</p><p>在一个排列中,将两个数的位置对调(其他数不动)的变动叫做一个<strong>对换</strong>,两个相邻数的对换称为<strong>相邻对换</strong>。</p></li><li><p>定理</p><p>一个排列中的任意两个数对换后,排列改变奇偶性</p></li></ul><h4 id="1-1-2-n-阶行列式"><a href="#1-1-2-n-阶行列式" class="headerlink" title="1.1.2. $n$阶行列式"></a>1.1.2. $n$阶行列式</h4><p>$$<br>D=\left|<br>\begin{array}{cccc}<br>a_{11} &a_{12} & \cdots &a_{1n}\<br>a_{21} & a_{22} &\cdots &a_{2n}\<br>\vdots &\vdots & &\vdots\<br>a_{n1} & a_{n2} & \cdots &a_{nn}\<br>\end{array}<br>\right|<br>=\sum(-1)^{t(p_1p_2\cdots p_n)}a_{1p_1}a_{2p_2}\cdots a_{np_n}<br>$$<br>称为$n$阶行列式,也可以把行列式简写为$\Delta(a_{ij})$</p><p>事实上可以将每一项写成如下形式<br>$$<br>(-1)^{t(i_1i_2\cdots i_n)+t(j_1j_2\cdots j_n)}a_{i_1j_1}a_{i_2j_2}\cdots a_{i_nj_n}<br>$$<br>因为互换$a_{i_1j_1}a_{i_2j_2}\cdots a_{i_nj_n}$中任意两个数后$t(i_1i_2\cdots i_n)$与$t(j_1j_2\cdots j_n)$奇偶性同时改变</p><ul><li><p>上(下)三角行列式<br>$$<br>\left|<br>\begin{array}{ccccc}<br>a_{11}&a_{12}&a_{13}&\cdots&a_{1n} \<br>0&a_{22}&a_{23}&\cdots&a_{2n} \<br>0&0&a_{33}&\cdots&a_{3n}\<br>\vdots&\vdots&\vdots&&\vdots \<br>0&0&0&\cdots&a_{nn}<br>\end{array}<br>\right|=a_{11}a_{22}\cdots a_{nn}<br>$$</p><p>$$<br>\left|<br>\begin{array}{ccccc}<br>a_{11}&a_{12}&\cdots&a_{1,n-1}&a_{1n} \<br>a_{21}&a_{22}&\cdots&a_{2,n-1}&0 \<br>\vdots&\vdots&&\vdots&\vdots \<br>a_{n-1,1}&a_{n-1,2}&\cdots &0&0 \<br>a_{n1}&0&\cdots&0&0<br>\end{array}<br>\right|=(-1)^{\frac{n(n-1)}{2}}a_{1n}a_{2,n-1}\cdots a_{n1}<br>$$</p></li></ul><h3 id="1-2-行列式的性质"><a href="#1-2-行列式的性质" class="headerlink" title="1.2. 行列式的性质"></a>1.2. 行列式的性质</h3><ul><li><p>行列式与其转置行列式相等</p></li><li><p>互换行列式的两行(列),行列式变号</p><p>推论:<u>如果行列式有两行(列)完全相同,则此行列式为0</u></p></li><li><p>$$<br>\left|\begin{array}{cccc}<br>a_{11}&a_{12}&\cdots&a_{1n} \<br>\vdots&\vdots &&\vdots \<br>ka_{i1}&ka_{i2}&\cdots&ka_{in} \<br>\vdots&\vdots &&\vdots \<br>a_{n1}&a_{n2}&\cdots&a_{nn} \<br>\end{array}\right|<br>=k<br>\left|\begin{array}{cccc}<br>a_{11}&a_{12}&\cdots&a_{1n} \<br>\vdots&\vdots &&\vdots \<br>a_{i1}&a_{i2}&\cdots&a_{in} \<br>\vdots&\vdots &&\vdots \<br>a_{n1}&a_{n2}&\cdots&a_{nn} \<br>\end{array}\right|<br>$$<br>推论:若行列式中有两行(列)元素成比例,则行列式等于0</p></li><li><h1 id="left-begin-array-cccc-a-11-amp-a-12-amp-cdots-amp-a-1n-vdots-amp-vdots-amp-amp-vdots-a-i1-a’-i1-amp-a-i2-a’-i2-amp-cdots-amp-a-in-a’-in-vdots-amp-vdots-amp-amp-vdots-a-n1-amp-a-n2-amp-cdots-amp-a-nn-end-array-right"><a href="#left-begin-array-cccc-a-11-amp-a-12-amp-cdots-amp-a-1n-vdots-amp-vdots-amp-amp-vdots-a-i1-a’-i1-amp-a-i2-a’-i2-amp-cdots-amp-a-in-a’-in-vdots-amp-vdots-amp-amp-vdots-a-n1-amp-a-n2-amp-cdots-amp-a-nn-end-array-right" class="headerlink" title="$$\left|\begin{array}{cccc}a_{11}&a_{12}&\cdots&a_{1n} \\vdots&\vdots &&\vdots \a_{i1}+a’{i1}&a{i2}+a’{i2}&\cdots&a{in}+a’{in} \\vdots&\vdots &&\vdots \a{n1}&a_{n2}&\cdots&a_{nn} \\end{array}\right| "></a>$$<br>\left|\begin{array}{cccc}<br>a_{11}&a_{12}&\cdots&a_{1n} \<br>\vdots&\vdots &&\vdots \<br>a_{i1}+a’<em>{i1}&a</em>{i2}+a’<em>{i2}&\cdots&a</em>{in}+a’<em>{in} \<br>\vdots&\vdots &&\vdots \<br>a</em>{n1}&a_{n2}&\cdots&a_{nn} \<br>\end{array}\right| </h1><p>\left|\begin{array}{cccc}<br>a_{11}&a_{12}&\cdots&a_{1n} \<br>\vdots&\vdots &&\vdots \<br>a_{i1}&a_{i2}&\cdots&a_{in} \<br>\vdots&\vdots &&\vdots \<br>a_{n1}&a_{n2}&\cdots&a_{nn} \<br>\end{array}\right| </p><ul><li>\left|\begin{array}{cccc}<br>a_{11}&a_{12}&\cdots&a_{1n} \<br>\vdots&\vdots &&\vdots \<br>a’<em>{i1}&a’</em>{i2}&\cdots&a’<em>{in} \<br>\vdots&\vdots &&\vdots \<br>a</em>{n1}&a_{n2}&\cdots&a_{nn} \<br>\end{array}\right|<br>$$</li></ul></li><li><h1 id="left-begin-array-cccc-a-11-amp-a-12-amp-cdots-amp-a-1n-vdots-amp-vdots-amp-amp-vdots-a-i1-amp-a-i2-amp-cdots-amp-a-in-vdots-amp-vdots-amp-amp-vdots-a-j1-ka-i1-amp-a-j2-ka-i2-amp-cdots-amp-a-jn-ka-in-vdots-amp-vdots-amp-amp-vdots-a-n1-amp-a-n2-amp-cdots-amp-a-nn-end-array-right"><a href="#left-begin-array-cccc-a-11-amp-a-12-amp-cdots-amp-a-1n-vdots-amp-vdots-amp-amp-vdots-a-i1-amp-a-i2-amp-cdots-amp-a-in-vdots-amp-vdots-amp-amp-vdots-a-j1-ka-i1-amp-a-j2-ka-i2-amp-cdots-amp-a-jn-ka-in-vdots-amp-vdots-amp-amp-vdots-a-n1-amp-a-n2-amp-cdots-amp-a-nn-end-array-right" class="headerlink" title="$$\left|\begin{array}{cccc}a_{11}&a_{12}&\cdots&a_{1n} \\vdots&\vdots &&\vdots \a_{i1}&a_{i2}&\cdots&a_{in} \\vdots&\vdots &&\vdots \a_{j1}+ka_{i1}&a_{j2}+ka_{i2}&\cdots&a_{jn}+ka_{in} \\vdots&\vdots &&\vdots \a_{n1}&a_{n2}&\cdots&a_{nn} \\end{array}\right|"></a>$$<br>\left|\begin{array}{cccc}<br>a_{11}&a_{12}&\cdots&a_{1n} \<br>\vdots&\vdots &&\vdots \<br>a_{i1}&a_{i2}&\cdots&a_{in} \<br>\vdots&\vdots &&\vdots \<br>a_{j1}+ka_{i1}&a_{j2}+ka_{i2}&\cdots&a_{jn}+ka_{in} \<br>\vdots&\vdots &&\vdots \<br>a_{n1}&a_{n2}&\cdots&a_{nn} \<br>\end{array}\right|</h1><p>\left|\begin{array}{cccc}<br>a_{11}&a_{12}&\cdots&a_{1n} \<br>\vdots&\vdots &&\vdots \<br>a_{i1}&a_{i2}&\cdots&a_{in} \<br>\vdots&\vdots &&\vdots \<br>a_{j1}&a_{j2}&\cdots&a_{jn} \<br>\vdots&\vdots &&\vdots \<br>a_{n1}&a_{n2}&\cdots&a_{nn} \<br>\end{array}\right|<br>$$</p></li></ul><h3 id="1-3-行列式的展开定理"><a href="#1-3-行列式的展开定理" class="headerlink" title="1.3. 行列式的展开定理"></a>1.3. 行列式的展开定理</h3><ul><li><p>余子式和代数余子式</p><p>把$a_{ij}$所在的第$i$行和第$j$列的元素划去,余下的元素按原来的排法构成的$n-1$阶行列式叫做元素$a_{ij}$的<strong>余子式</strong>,记为$M_{ij}$。其代数余子式记作$A_{ij}$,定义为$A_{ij}= (-1)^{i+j}M_{ij}$</p></li><li><p>行列式等于它的任一行(列)的各元素与其代数余子式的乘积之和,即<br>$$<br>D=a_{i1}A_{i1}+a_{i2}A_{i2}+\cdots+a_{in}A_{in}, \quad i=1,2,\cdots,n<br>$$</p><p>$$<br>D=a_{1j}A_{1j}+a_{2j}A_{2j}+\cdots+a_{nj}A_{nj}, \quad j=1,2,\cdots,n<br>$$</p></li><li><p>行列式$D$的任一行(列)元素与另一行(列)对应元素的代数余子式乘积之和等于0,即<br>$$<br>a_{i1}A_{j1}+a_{i2}A_{j2}+\cdots+a_{in}A_{jn}=0, \quad i\neq j,\enspace i,j=1,2,\cdots,n<br>$$</p><p>$$<br>a_{1i}A_{1j}+a_{2i}A_{2j}+\cdots+a_{ni}A_{nj}=0, \quad i\neq j,\enspace i,j=1,2,\cdots,n<br>$$</p></li></ul><hr><p><font color="99ccff">一些例题</font></p><ul><li><p>计算<br>$$<br>D_{2n}=\left|<br>\begin{array}{cccccccc}<br>a&&&&&&&b\<br>&a&&&&&b \<br>&&\ddots&&& \<br>&&&a&b \<br>&&&c&d \<br>&&&&&\ddots \<br>&c&&&&&d \<br>c&&&&&&&d<br>\end{array}<br>\right|<br>$$</p><blockquote><p>按第一行展开有<br>$$<br>\begin{aligned}<br>D_{2n} &= a<br>\left|<br>\begin{array}{cccccccc}<br> a&&&&&b&0\<br> &\ddots&&& \<br> &&a&b \<br> &&c&d \<br> &&&&\ddots \<br> c&&&&&d \<br> 0&&&&&&d<br>\end{array}<br>\right|</p><p>+<br>b(-1)^{2n+1}<br>\left|<br>\begin{array}{cccccccc}<br>0&a&&&&&b \<br> &&\ddots&&& \<br> &&&a&b \<br> &&&c&d \<br> &&&&&\ddots \<br> &c&&&&&d \<br>c&&&&&&0<br>\end{array}<br>\right| \<br>\<br>&=adD_{2(n-1)}+b(-1)^{2n+1}\cdot c(-1)^{2n-1+1}D_{2(n-1)} \<br>&=(ad-bc)D_{2(n-1)}<br>\end{aligned}<br>$$<br>因此<br>$$<br>D_{2n}=(ad-bc)^{n-1}<br>\left|\begin{array}{cc}<br>a&b\<br>c&d<br>\end{array}\right|=(ad-bc)^{n}<br>$$</p></blockquote></li><li></li><li><h1 id="证明Vandermonde-范德蒙德-行列式-D-n-x3D-left-begin-array-cccc-1-amp-1-amp-cdots-amp-1-x-1-amp-x-2-amp-cdots-amp-x-n-x-1-2-amp-x-2-2-amp-cdots-amp-x-n-2-vdots-amp-vdots-amp-amp-vdots-x-1-n-1-amp-x-2-n-1-amp-cdots-amp-x-n-n-1-end-array-right"><a href="#证明Vandermonde-范德蒙德-行列式-D-n-x3D-left-begin-array-cccc-1-amp-1-amp-cdots-amp-1-x-1-amp-x-2-amp-cdots-amp-x-n-x-1-2-amp-x-2-2-amp-cdots-amp-x-n-2-vdots-amp-vdots-amp-amp-vdots-x-1-n-1-amp-x-2-n-1-amp-cdots-amp-x-n-n-1-end-array-right" class="headerlink" title="证明Vandermonde(范德蒙德)行列式$$D_n=\left|\begin{array}{cccc}1&1&\cdots&1 \x_1&x_2&\cdots&x_n \x_1^2&x_2^2&\cdots&x_n^2 \\vdots&\vdots&&\vdots \x_1^{n-1}&x_2^{n-1}&\cdots&x_n^{n-1}\end{array}\right|"></a>证明Vandermonde(范德蒙德)行列式<br>$$<br>D_n=\left|\begin{array}{cccc}<br>1&1&\cdots&1 \<br>x_1&x_2&\cdots&x_n \<br>x_1^2&x_2^2&\cdots&x_n^2 \<br>\vdots&\vdots&&\vdots \<br>x_1^{n-1}&x_2^{n-1}&\cdots&x_n^{n-1}<br>\end{array}\right|</h1><p>\prod_{1\leqslant i< j\leqslant n} (x_i-x_j),\quad n\geqslant 2<br>$$</p><blockquote><p>采用数学归纳法证明</p><p>当$n=2$时<br>$$<br>D_2 =\left|\begin{array}{cc}1&1\ x_1 &x_2\end{array}\right| = x_2-x_1 = \prod_{1\leqslant i<j\leqslant 2}(x_i-x_j)<br>$$<br>原始成立</p><p>设当$n-1$时原式成立,则当$n$时<br>$$<br>\begin{aligned}<br>D_n=&\left|\begin{array}{cccc}<br>1&1&\cdots&1 \<br>x_1&x_2&\cdots&x_n \<br>x_1^2&x_2^2&\cdots&x_n^2 \<br>\vdots&\vdots&&\vdots \<br>x_1^{n-1}&x_2^{n-1}&\cdots&x_n^{n-1}<br>\end{array}\right|<br>\overset{\begin{aligned}r_2-x_1r_1\\vdots\quad,\r_n-x_1r_{n-1}<br>\end{aligned}<br>}{=}<br>\left|\begin{array}{cccc}<br>1&1&\cdots&1 \<br>0&x_2-x_1&\cdots&x_n-x_1 \<br>0&x_2(x_2-x_1)&\cdots&x_n(x_n-x_1) \<br>\vdots&\vdots&&\vdots \<br>0&x_2^{n-2}(x_2-x_1)&\cdots&x_n^{n-2}(x_n-x_1)<br>\end{array}\right| \<br>=&<br>\left|\begin{array}{cccc}</p><pre><code class="hljs">x_2-x_1&\cdots&x_n-x_1 \\x_2(x_2-x_1)&\cdots&x_n(x_n-x_1) \\\vdots&&\vdots \\x_2^{n-2}(x_2-x_1)&\cdots&x_n^{n-2}(x_n-x_1)</code></pre><p>\end{array}\right| \<br>=&\prod_{i=2}^n(x_i-x_1)<br>\left|\begin{array}{cccc}<br> 1&\cdots&1 \<br> x_2&\cdots&x_n \<br> \vdots&&\vdots \<br> x_2^{n-2}&\cdots&x_n^{n-2}<br>\end{array}\right|\<br>=&\prod_{i=2}^n(x_i-x_1)\cdot\prod_{2\leqslant i<j\leqslant n}(x_i-x_j)\<br>=&\prod_{1\leqslant i< j\leqslant n} (x_i-x_j)<br>\end{aligned}<br>$$</p></blockquote></li></ul><h3 id="1-4-Cramer法则"><a href="#1-4-Cramer法则" class="headerlink" title="1.4. Cramer法则"></a>1.4. Cramer法则</h3><p>设有线性方程组<br>$$<br>\left{<br>\begin{aligned}<br>&a_{11}x_1+a_{12}x_2+\cdots+a_{1n}x_n = b_1 \<br>&a_{21}x_1+a_{22}x_2+\cdots+a_{2n}x_n = b_2 \<br>&\cdots \<br>&a_{n1}x_1+a_{n2}x_2+\cdots+a_{nn}x_n = b_n \<br>\end{aligned}<br>\right.<br>$$<br>记其系数行列式为<br>$$<br>D=\left|<br>\begin{array}{cccc}<br>a_{11} &a_{12} & \cdots &a_{1n}\<br>a_{21} & a_{21} &\cdots &a_{2n}\<br>\vdots &\vdots & &\vdots\<br>a_{n1} & a_{n1} & \cdots &a_{nn}\<br>\end{array}<br>\right|<br>$$<br>若$D\neq 0$,则方程组有解,且解是唯一的,此时<br>$$<br>x_j = \frac{D_j}{D}<br>$$<br>其中$D_j$是把系数行列式$D$中第$j$列的元素依次用方程组右端常数项代替得到的$n$阶行列式,即<br>$$<br>D_j =<br>\left|<br>\begin{array}{ccccccc}<br>a_{11} &\cdots &a_{1,j-1}&b_1&a_{1,j+1}&\cdots &a_{1n}\<br>a_{21} &\cdots &a_{2,j-1}&b_2&a_{2,j+1} &\cdots &a_{2n}\<br>\vdots &&\vdots &\vdots&\vdots& &\vdots\<br>a_{n1} &\cdots&a_{n,j-1} &b_n&a_{n,j+1}&\cdots &a_{nn}\<br>\end{array}<br>\right|,\quad j=1,2,\cdots,n<br>$$</p><h3 id="1-5-行列式的几何意义"><a href="#1-5-行列式的几何意义" class="headerlink" title="1.5. 行列式的几何意义"></a>1.5. 行列式的几何意义</h3><p>可将实系数$n$阶行列式$D=|\mathbf{a}_1\mathbf{a}_2\cdots\mathbf{a}_n|$视为$n$维实向量空间中以$\mathbf{a}_1\mathbf{a}_2\cdots\mathbf{a}_n$为棱的平行多面体的<u>有向体积</u></p><ul><li><p>$|\mathbf{a}_1,\cdots,k\mathbf{a}_i,\cdots,\mathbf{a}_n| = k|\mathbf{a}_1,\cdots,\mathbf{a}_i,\cdots,\mathbf{a}_n|$</p><p>若一条棱延长$k$倍,则体积增大$k$倍</p></li><li><p>$|\mathbf{a}_1,\cdots,\mathbf{b}_1+\mathbf{b}_2,\cdots,\mathbf{a}_n| = |\mathbf{a}_1,\cdots,\mathbf{b}_1,\cdots,\mathbf{a}_n|+|\mathbf{a}_1,\cdots,\mathbf{b}_2,\cdots,\mathbf{a}_n|$</p><p>若平行多面体的一条棱可以分解成两条棱的和,则这个平行多面体的有向体积可以分解成两个相应的平行多面体的有向体积之和</p></li></ul>]]></content>
<categories>
<category>考研</category>
</categories>
</entry>
<entry>
<title>概率论</title>
<link href="/2023/01/10/%E6%A6%82%E7%8E%87%E8%AE%BA/"/>
<url>/2023/01/10/%E6%A6%82%E7%8E%87%E8%AE%BA/</url>
<content type="html"><![CDATA[<h2 id="1-随机事件与概率"><a href="#1-随机事件与概率" class="headerlink" title="1. 随机事件与概率"></a>1. 随机事件与概率</h2><h3 id="1-1-随机事件"><a href="#1-1-随机事件" class="headerlink" title="1.1. 随机事件"></a>1.1. 随机事件</h3><ul><li><p>随机试验</p><p>满足如下三个条件的试验称为随机试验,简称试验</p><ul><li>试验可在相同的条件下重复进行</li><li>试验的所有可能结果不止一个,而且还是事先已知的</li><li>每次试验总是恰好出现这些可能结果中的一个,但是究竟那个结果在实验前不能确切预言</li></ul></li><li><p>基本事件,也称样本点</p><p>每一个可能的结果</p></li><li><p>样本空间</p><p>全部基本事件的集合</p></li><li><p>事件</p><p>基本事件的集合,即样本空间的某个子集</p></li></ul><h3 id="1-2-事件的关系和运算"><a href="#1-2-事件的关系和运算" class="headerlink" title="1.2. 事件的关系和运算"></a>1.2. 事件的关系和运算</h3><h4 id="1-2-1-基本概念"><a href="#1-2-1-基本概念" class="headerlink" title="1.2.1. 基本概念"></a>1.2.1. 基本概念</h4><ul><li><p>事件的包含与相等</p><p>事件$A$中的每一个样本点都属于事件$B$,则称事件$B$包含事件$A$,记作$A \subset B$</p><p>若$A \subset B,B\subset A$,则称$A$与$B$相等,记作$A=B$</p></li><li><p>事件的积(事件的交)</p><p>同时属于$A$和$B$的样本点的集合称为$A$与$B$的交,记为$A \cap B$或$AB$</p></li><li><p>互不相容事件(互斥事件)</p><p>若$AB = \emptyset$,则称$A$与$B$为互不相容事件,如必然事件$S$和不可能事件$\emptyset$是互不相容事件</p><p>若中的<strong>任意两个事件</strong>是互不相容的,则称$A_1,A_2,\cdots,A_n$是互不相容的</p></li><li><p>事件的差</p><p>包含在$A$中而不包含在$B$中的样本点的集合称作$A$与$B$之差,记作$A-B$</p></li><li><p>对立事件</p><p>$S$与$A$之差称为$A$的对立事件,即为$\overline{A}$</p></li></ul><h4 id="1-2-2-运算律"><a href="#1-2-2-运算律" class="headerlink" title="1.2.2. 运算律"></a>1.2.2. 运算律</h4><ul><li><p>交换律<br>$$<br>A\cup B = B\cup A \<br>AB = BA<br>$$</p></li><li><p>结合律<br>$$<br>(A\cup B)\cup C = A \cup(B\cup C) \<br>(AB)C = A(BC)<br>$$</p></li><li><p>分配律<br>$$<br>(A\cup B)\cap C = (A \cap C)\cup (B\cap C)\<br>(A\cap B)\cup C = (A\cup C)\cap(B\cup C)<br>$$</p></li><li><p>对偶原理<br>$$<br>\overline{A\cup B} = \overline{A}\cap \overline{B}\<br>\overline{A\cap B} = \overline{A}\cup \overline{B}<br>$$</p></li></ul><h3 id="1-3-古典概率"><a href="#1-3-古典概率" class="headerlink" title="1.3. 古典概率"></a>1.3. 古典概率</h3><h4 id="1-3-1-概念"><a href="#1-3-1-概念" class="headerlink" title="1.3.1. 概念"></a>1.3.1. 概念</h4><p>设$E$为一试验,若其样本空间$S$满足如下条件,则称$E$为古典概型试验</p><ul><li>只有有限个基本事件</li><li>每个基本事件发生的可能性相等</li></ul><p>在古典概型情况下,事件$A$的概率定义为<br>$$<br>P(A) = \frac{A\text{中包含的基本事件个数}}{\text{基本事件总数}}<br>$$</p><h4 id="1-3-2-性质"><a href="#1-3-2-性质" class="headerlink" title="1.3.2. 性质"></a>1.3.2. 性质</h4><p>古典概型具有如下性质</p><ul><li>对任意事件$A$有$0\leq P(A) \leq 1$</li><li>$P(S) = 1$</li><li>若$A,B$互不相容,则$P(A+B) = P(A) + P(B)$</li></ul><p>由此衍生出的性质</p><ul><li><p>$P(\overline{A}) = 1 - P(A)$,特殊的$P(\emptyset) = 0$</p><p>证明:<br>$$<br>P(A + \overline{A}) = P(A) + P(\overline{A})<br>$$</p></li><li><p>若$A\subset B$,则$P(A)\leq P(B)$,且$P(B-A) = P(B) - P(A)$</p><p>证明:</p><p>由$A\subset B$,故<br>$$<br>B = A + (B - A)<br>$$<br>其中$A$与$B-A$互斥,故<br>$$<br>P(B) = P(A) + P(B-A)<br>$$</p></li><li><p>任意俩事件$A, B$满足</p><ul><li>$P(A-B) = P(A) - P(AB)$</li><li>$P(A\cup B) = P(A) + P(B) - P(AB)$,可拓展至$n$个事件,数学归纳法证明。</li></ul><p>证明:</p><p>由于$A\cup B = A + (B- A)$,$A$与$B-A$互斥<br>$$<br>P(A\cup B) = P(A) + P(B-A) = P(A) + P(B) - P(B-A)<br>$$</p></li></ul><h3 id="1-4-几何概率"><a href="#1-4-几何概率" class="headerlink" title="1.4. 几何概率"></a>1.4. 几何概率</h3><p>古典概型的推广,适用于无穷多基本事件而又有等可能性的情况</p><ul><li><p>定义</p><p>向某一区域$S$中投掷一质点$M$,如果$M$必落在$S$内,且落在$S$内的任何子区域$A$上的可能性只与$A$的某种度量(如长度,面积……)成正比,而与$A$的位置及形状无关,则称这个试验为几何概型的试验。并定义$M$落在$A$中的概率为<br>$$<br>P(A) = \frac{L(A)}{L(S)}<br>$$</p></li><li><p>性质</p><ul><li><p>对任意事件$A$有$0\leq P(A) \leq 1$</p></li><li><p>$P(S) = 1$</p></li><li><p>若$A_1,A_2,\cdots, A_n$是互不相容的,则<br>$$<br>P(A_1+A_2+\cdots+A_n) = P(A_1)+P(A_2)+\cdots+P(A_n)<br>$$</p></li></ul><p>古典概型中推出的性质对几何概型也成立</p></li></ul><h3 id="1-5-统计概率"><a href="#1-5-统计概率" class="headerlink" title="1.5. 统计概率"></a>1.5. 统计概率</h3><p>对于等可能性的拓展,适用于一般试验的统计概率。</p><ul><li><p>频率</p><p>记$A$为联系于某次试验的事件,将试验在相同条件下重复$n$次,用$m$表示$A$出现的次数,则称比值$\frac{m}{n}$为事件$A$的相对频率,简称频率,记为$f_n(A)$</p></li><li><p>概率</p><p>在一组固定的条件下,重复做$n$次试验。如果当$n$增大时,事件$A$的出现频率$f_n(A)$围绕着某一个常数$p$摆动,而且一般来说,随着$n$的增大,这种摆动的幅度越来越小,则称常数$p$为事件$A$的概率</p></li><li><p>性质</p><ul><li><p>对任意事件$A$,有$0\leq f_n(A) \leq 1$</p></li><li><p>$f_n(S)=1$</p></li><li><p>若$A_1,A_2,\cdots ,A_k$为互不相容的事件,则<br>$$<br>f_n(A_1+A_2+\cdots+A_k)=f_n(A_1)+f_n(A_2)+\cdots+f_n(A_k)<br>$$</p></li></ul></li></ul><h3 id="1-6-概率的公理化定义"><a href="#1-6-概率的公理化定义" class="headerlink" title="1.6. 概率的公理化定义"></a>1.6. 概率的公理化定义</h3><ul><li><p>公理化定义</p><p>设随机试验$E$的样本空间为$S$,如果对每一个事件$A$,都有一个实数$P(A)$与之对应,且满足公理。</p><ul><li><p>$P(A)\geq 0$</p></li><li><p>$P(S) = 1$</p></li><li><p>对于互不相容的事件$A_1,A_2,\cdots,A_n, \cdots$,有<br>$$<br>P(A_1+A_2+\cdots+A_n+\cdots)=P(A_1)+P(A_2)+\cdots+P(A_n)+\cdots<br>$$</p></li></ul><p>则称实数$P(A)$为事件$A$的概率</p></li></ul><h2 id="2-条件概率与独立性"><a href="#2-条件概率与独立性" class="headerlink" title="2. 条件概率与独立性"></a>2. 条件概率与独立性</h2><h3 id="2-1-条件概率及乘法定理"><a href="#2-1-条件概率及乘法定理" class="headerlink" title="2.1. 条件概率及乘法定理"></a>2.1. 条件概率及乘法定理</h3><ul><li><p>条件概率</p><p>设$A$和$B$为任意两个事件,且$P(B)>0$,则称比值$\frac{P(AB)}{P(B)}$为事件$A$在事件$B$发生条件下的条件概率,记作<br>$$<br>P(A|B)=\frac{P(AB)}{P(A)}<br>$$<br>下证明上述定义满足公理</p><ul><li><p>$P(A|B)=\frac{P(AB)}{P(B)}\geq 0$ </p></li><li><p>$P(S|B) = \frac{P(SB)}{P(B)} = \frac{P(B)}{P(B)} = 1$</p></li><li><p>设$A_1,A_2,\cdots$互不相容,则$A_1B,A_2B,\cdots$互不相容,因此<br>$$<br>\begin{aligned}<br>P((A_1 + A_2+\cdots) |B)<br>&= \frac{P((A_1+A_2+\cdots)B)}{P(B)} \<br>& = \frac{P(A_1B+A_2B+\cdots)}{P(B)} \<br>& = \frac{P(A_1B)+P(A_2B)+\cdots}{P(B)}\<br>& = P(A_1|B) + P(A_2|B)+\cdots<br>\end{aligned}<br>$$</p></li></ul></li><li><p>乘法定理</p><p>两个事件的积的概率等于其中一个事件的概率与另一事件在前一事件发生条件下的条件概率的乘积。<br>$$<br>P(AB)=P(A)P(B|A) = P(B)P(A|B)<br>$$<br>这个结果可以推广到$n$个事件上去<br>$$<br>P(A_1A_2\cdots A_n)=P(A_1)P(A_2|A_1)P(A_3|A_2A_1)\cdots P(A_n|A_1A_2\cdots A_n)<br>$$</p></li></ul><h3 id="2-2-全概率公式"><a href="#2-2-全概率公式" class="headerlink" title="2.2. 全概率公式"></a>2.2. 全概率公式</h3><p>设$A_1,A_2,\cdots,A_n$是互不相容的事件且$P(A_i)>0(i=1,2,\cdots,n)$,若对于任意事件$B$,有$A_1+A_2+\cdots+A_n \supset B$,则<br>$$<br>P(B) = \sum_{i=1}^n P(A_i)P(B|A_i)<br>$$</p><h3 id="2-3-贝叶斯公式"><a href="#2-3-贝叶斯公式" class="headerlink" title="2.3. 贝叶斯公式"></a>2.3. 贝叶斯公式</h3><p>设$A_1,A_2,\cdots,A_n$是互不相容的事件,且$P(A_i)>0(i=1,2,\cdots,n)$,若对任意事件$B$有$A_1+A_2+\cdots +A_n \supset B$,且$P(B)>0$,则<br>$$<br>P(A_i|B) = \frac{P(A_i)P(B|A_i)}{\sum\limits_{j=0}^nP(A_j)P(B|A_j)}<br>$$<br>式中,$P(A_i)$称为先验概率,$P(A_i|B)$称作后验概率</p><h3 id="2-4-事件的独立性"><a href="#2-4-事件的独立性" class="headerlink" title="2.4. 事件的独立性"></a>2.4. 事件的独立性</h3><h4 id="2-4-1-两个事件"><a href="#2-4-1-两个事件" class="headerlink" title="2.4.1. 两个事件"></a>2.4.1. 两个事件</h4><ul><li><p>定义</p><p>若$A,B$为任二事件,若$P(B|A)=P(B)$,则称$A$与$B$是相互独立的</p></li><li><p>相关定理</p><p>若$A$与$B$是相互独立的,则$A$与$\overline{B}$,$\overline{A}$与$B$,$\overline{A}$与$B$,$\overline{A}$与$\overline{B}$均是相互独立的</p><p>证明,只需证$A$与$\overline{B}$相互独立:<br>$$<br>\begin{aligned}<br>P(A\overline{B})<br>&= P(A) - P(AB) = P(A) - P(A)P(B) \<br>&= P(A)[1-P(B)] = P(A)P(\overline{B})<br>\end{aligned}<br>$$</p></li></ul><h4 id="2-4-2-多个事件"><a href="#2-4-2-多个事件" class="headerlink" title="2.4.2. 多个事件"></a>2.4.2. 多个事件</h4><ul><li><p>定义</p><p>设$A,B,C$为三个事件</p><ul><li><p>若有<br>$$<br>P(AB) = P(A)P(B)\<br>P(BC) = P(B)P(C)\<br>P(CA) = P(C)P(A)<br>$$<br>则称$A,B,C$<strong>两两独立</strong></p></li><li><p>若$A,B,C$<strong>不仅两两独立</strong>,而且<br>$$<br>P(ABC) = P(A)P(B)P(C)<br>$$<br>则称$A,B,C$是相互独立的</p></li></ul><p>推广到$A_1,A_2,\cdots ,A_n$共$n$个事件</p><p>如果对<strong>任意</strong>$k(1<k\leq n)$,<strong>任意</strong>$1\leq i_1<i_2<\cdots i_k \leq n$,满足等式:<br>$$<br>P(A_{i_1}A_{i_2}\cdots A_{i_k}) = P(A_{i_1})P(A_{i_2})\cdots P(A_{i_k})<br>$$<br>则称$A_1,A_2,\cdots ,A_n$是相互独立的</p></li><li><p>性质</p><p>若事件$A_1,A_2,\cdots ,A_n$相互独立,则将其中任意事件换成对立事件仍然相互独立。</p></li></ul><h3 id="2-5-重复独立试验与二项概率公式"><a href="#2-5-重复独立试验与二项概率公式" class="headerlink" title="2.5. 重复独立试验与二项概率公式"></a>2.5. 重复独立试验与二项概率公式</h3><p> 进行$n$次试验,如果每次试验中,任意事件出现的概率与其他各次实验结果无关,则称这$n$次试验是独立的。将一个试验重复进行$n$次的独立试验称为$n$次<strong>独立重复试验</strong>。</p><h4 id="2-5-1-伯努利试验"><a href="#2-5-1-伯努利试验" class="headerlink" title="2.5.1. 伯努利试验"></a>2.5.1. 伯努利试验</h4><p>若一次试验只有两个结果$A$和$\overline{A}$,则称这个试验为伯努利试验。一般称其一结果为成功,另一结果为失败。</p><p>设在每次试验中成功的概率为$p(0<p<1)$,则在$n$重伯努利实验中成功恰好发生$k$次的概率为<br>$$<br>P_n(k)=C_n^k p^k q^{n-k}<br>$$<br>其中$p+q=1$</p><p>注意到<br>$$<br>\sum_{k=0}^nP_n(k) = \sum_{k=0}^nC_n^k p^k q^{n-k}=(p+q)^n=1<br>$$<br>$C_n^k p^k q^{n-k}$恰好是$(p+q)^n$展开的各项,故称$P_n(k)=C_n^k p^k q^{n-k}$为<strong>二项概率公式</strong>。</p><h2 id="3-随机变量及其分布"><a href="#3-随机变量及其分布" class="headerlink" title="3. 随机变量及其分布"></a>3. 随机变量及其分布</h2><h3 id="3-1-随机变量"><a href="#3-1-随机变量" class="headerlink" title="3.1. 随机变量"></a>3.1. 随机变量</h3><p>把试验中的观察对象用$X$表示,那么$X$随着试验的重复可以取不同值,且无法确切预言,因此称之为随机变量。由于$X$是随着试验的结果(基本事件$e$)不同而变化的,因此$X$实际是基本事件$e$的函数,即$X=X(e)$,如:</p><p>样本空间$S={\text{正},\text{反}}$,则<br>$$<br>X = \left{<br>\begin{aligned}<br>1, \qquad\text{正面出现} \<br>0, \qquad\text{反面出现}<br>\end{aligned}<br>\right.<br>$$<br>由上所述,给出随机变量的定义</p><p>设$E$是随机试验,它的样本空间是$S$。如果对$S$中的每个基本事件$e$,都有唯一的实数值$X(e)$与之对应,则称$X(e)$为随机变量,简记为$X$</p><h3 id="3-2-离散随机变量"><a href="#3-2-离散随机变量" class="headerlink" title="3.2. 离散随机变量"></a>3.2. 离散随机变量</h3><p>只能取有限个值或可列无穷多个值的随机变量$X$称为离散随机变量。</p><p>如$P(X=x_k)=p_k,(k=1,2,\cdots)$的形式称为离散随机变量$X$的概率分布列,或简称分布列(分布律),概率质量函数,它也可以用表格的形式表现。</p><hr><p>$X$ |$x_1$$x_2$$\cdots$$x_4$$\cdots$</p><hr><p>$P$ |$p_1$$p_2$$\cdots$$p_4$$\cdots$</p><hr><h4 id="3-2-1-0-1分布"><a href="#3-2-1-0-1分布" class="headerlink" title="3.2.1. 0-1分布"></a>3.2.1. 0-1分布</h4><p>也称伯努利分布,两点分布。</p><p>随机变量仅能取0和1两个值,其分布列为<br>$$<br>P(X=1)=p,\quad P(X=0)=1-p=q,\quad 0<p<1<br>$$</p><h4 id="3-2-2-二项分布"><a href="#3-2-2-二项分布" class="headerlink" title="3.2.2. 二项分布"></a>3.2.2. 二项分布</h4><p>若随机变量$X$的分布列如下<br>$$<br>P(X=k)=C_n^k p^kq_{n-k}, \quad k=0,1,2,\cdots,n\<br>0<p<1,\quad q=1-p<br>$$<br>则称$X$服从二项分布(参数为$n,p$),常用符号$X\sim B(n,p)$</p><p>特别的,当$n=1$时则退化为0-1分布</p><h4 id="3-2-3-泊松分布"><a href="#3-2-3-泊松分布" class="headerlink" title="3.2.3. 泊松分布"></a>3.2.3. 泊松分布</h4><p>若随机变量$X$的分布列为<br>$$<br>P(X=k) = \frac{\lambda ^ke^{-\lambda}}{k!}, \quad \lambda>0, \quad k=0,1,2,\cdots,<br>$$<br>则称$X$服从参数为$\lambda$的泊松分布,并用记号$X\sim P(\lambda)$表示</p><ul><li><p><a href="https://zhuanlan.zhihu.com/p/139114702">一个泊松分布的例子</a></p><p>有一个栗子树,可能会掉栗子。</p><p>我们把一天时间分成了$n$份,并假设这段时间里至多有一个栗子掉下(这样假设是可行的,因为当$n$足够大时,时间足够小,而不会有两个事件在完全相同时间发生),在这段时间有一个栗子掉下的概率为$p$</p><p>则在一天内有$k$个栗子掉下的概率为<br>$$<br>P(X=k)=C_n^k p^k(1-p)^{n-k}<br>$$<br>一天内掉下的栗子的期望为(<strong>本质上仍为二项分布</strong>)<br>$$<br>E(X)=np<br>$$<br>记为$\lambda$,即$p=\frac{\lambda}{n}$,带入原式得<br>$$<br>P(X=k)=C_n^k(\frac{\lambda}{n})^k(1-\frac{\lambda}{n})^{n-k}<br>$$<br>当$n\to \infty$时<br>$$<br>\begin{aligned}<br>P(X=k)<br>& = \lim_{n\to\infty}\frac{n!}{k!(n-k)!}\frac{\lambda^k}{n^k}(1-\frac{\lambda}{n})^{n-k} \<br>& = \frac{\lambda^k}{k!}\lim_{n\to\infty}\frac{n(n-1)(n-2)\cdots(n-k+1)}{n^k}(1-\frac{\lambda}{n})^{n-k} \<br>& = \frac{\lambda^k}{k!}e^{-\lambda}<br>\end{aligned}<br>$$</p></li></ul><h4 id="3-2-4-超几何分布"><a href="#3-2-4-超几何分布" class="headerlink" title="3.2.4. 超几何分布"></a>3.2.4. 超几何分布</h4><p>若随机变量$X$的分布列为<br>$$<br>P(X=k)=\frac{C_M^kC_{N-M}^{n-k}}{C_N^n},\quad k=0,1,\cdots,l,\quad l=\min(M,m)<br>$$<br>则称$X$服从超几何分布</p><p>超几何分布可以看作不放回抽样,如</p><p>$N$件产品中有$M$件次品,从中任取$n$件产品,这$n$件产品中包含的次品数$X$服从超几何分布。</p><h4 id="3-2-5-几何分布"><a href="#3-2-5-几何分布" class="headerlink" title="3.2.5. 几何分布"></a>3.2.5. 几何分布</h4><p>若随机变量$X$的分布列为<br>$$<br>P(X=k) = (1-p)^{k-1}p,\quad k=1,2,\cdots<br>$$<br>则称$X$服从参数为$p$几何分布,记作$X\sim G(p)$</p><p>几何分布表示每次独立试验成功概率为$p$,直到第一次成功的试验次数为$X$</p><ul><li><p>几何分布具有无记忆性,即<br>$$<br>P(X>n+m|X>n) = P(X>m)<br>$$<br>因为<br>$$<br>\begin{aligned}<br>P(X>n+m|X>n) &= \frac{P(X>n+m,X>n)}{P(X>n)} \<br>&=\frac{\sum\limits_{k=n+m+1}^\infty(1-p)^{k-1}p}{\sum\limits_{k=n+1}^\infty(1-p)^{k-1}p}\<br>&=(1-p)^m<br>\end{aligned}<br>$$</p><p>$$<br>\begin{aligned}<br>P(X>m)&=\sum_{m+1}^\infty (1-p)^{k-1}p \<br>&= \lim_{k\to\infty}\frac{(1-p)^m[1-(1-p)^k]}{1-(1-p)}p \<br>&= (1-p)^m<br>\end{aligned}<br>$$</p></li></ul><h4 id="3-2-6-负二项分布"><a href="#3-2-6-负二项分布" class="headerlink" title="3.2.6. 负二项分布"></a>3.2.6. 负二项分布</h4><p>也称帕斯卡分布,是几何分布的一般化。</p><p>若随机变量$X$的分布列为<br>$$<br>P(X=k)=C_{k-1}^{r-1}p^r(1-p)^{k-r},\quad k=r,r+1,r+2,\cdots<br>$$<br>则称$X$服从参数为$r,p$的负二项分布,记为$X\sim NB(r,p)$</p><p>负二项分布可以看作每次试验成功概率为$p$,连续独立试验直到成功$r$次为止,$X$表示试验次数。</p><h3 id="3-3-随机变量的分布函数"><a href="#3-3-随机变量的分布函数" class="headerlink" title="3.3. 随机变量的分布函数"></a>3.3. 随机变量的分布函数</h3><p>对于非离散的随机变量,无法用分布列描述,故而引入分布函数。</p><p>也可描述离散随机变量。</p><ul><li><p>定义</p><p>设$X$为一随机变量,称<br>$$<br>F(x)=P(X\leq x)<br>$$<br>为$X$的分布函数,其中$x$为任意实数</p></li><li><p>性质</p><ul><li><p>$0\leq F(x)\leq 1, \quad -\infty <x<\infty$</p></li><li><p>若$x_1<x_2$,则$F(x_1)\leq F(x_2)$</p></li><li><p>$F(x)$满足<br>$$<br>F(-\infty)=\lim_{x\to -\infty}F(x)=0\<br>F(+\infty)=\lim_{x\to +\infty}F(x)=1<br>$$</p></li><li><p>$F(x+0)=F(x)$,即$F(x)$是右连续的(如下例)</p><p><img src="https://cdn.jsdelivr.net/gh/tsdsnk/imgs@main/img/QQ%E5%9B%BE%E7%89%8720230111181713.png"></p></li></ul></li></ul><h3 id="3-4-连续型随机变量"><a href="#3-4-连续型随机变量" class="headerlink" title="3.4. 连续型随机变量"></a>3.4. 连续型随机变量</h3><h4 id="3-4-1-连续型随机变量、概率密度"><a href="#3-4-1-连续型随机变量、概率密度" class="headerlink" title="3.4.1. 连续型随机变量、概率密度"></a>3.4.1. 连续型随机变量、概率密度</h4><p>若随机变量$X$的分布函数$F(X)$是可微的,则其导数<br>$$<br>f(x)=F^{‘}(x)=\lim_{\Delta x\to0^+}\frac{P(x\leq X\leq x+\Delta x)}{\Delta x}\geq 0<br>$$<br>称为概率密度,但有些分布函数$F(x)$不一定可微,故采用如下定义</p><p>设$F(x)$是随机变量$X$的分布函数,若存在一个非负的函数$f(x)$,对任何实数$x$有<br>$$<br>F(x)=\int_{-\infty}^x f(t)dt<br>$$<br>则称$X$为连续型随机变量,同时称$f(x)$为$X$的概率密度函数,简称概率密度。</p><p>不难证明下面的函数形式满足$F(x)=\int _{-\infty} ^x f(t)dt$,这种方法称为<strong>分布函数法</strong><br>$$<br>f(x)=\left{<br>\begin{aligned}<br>&F^{‘}(x), & F^{‘}(x)\text{存在}\<br>&0, &F^{‘}(x)\text{不存在}<br>\end{aligned}<br>\right.<br>$$<br>连续型随机变量满足</p><ul><li><p>在整个实轴上,$F(x)$是连续的</p></li><li><p>对$f(x)$的连续点,有<br>$$<br>F^{‘}(x)=f(x)<br>$$</p></li></ul><p>概率密度函数$f(x)$具有如下性质</p><ul><li>$f(x)\geq 0$</li><li>$\int_{-\infty}^{+\infty}f(x)=1$</li><li>$P(x_1<X\leq x_2)=F(x_2)-F(x_1)=\int_{x_1}^{x_2}f(x)dx$</li></ul><p>计算<strong>连续型随机变量</strong>落在某一区间概率时,无需考虑是否包含端点,因为连续型随机变量取个别值的概率为0(夹逼定理可证)</p><h4 id="3-4-2-均匀分布"><a href="#3-4-2-均匀分布" class="headerlink" title="3.4.2. 均匀分布"></a>3.4.2. 均匀分布</h4><p>设连续型随机变量$X$的概率密度为<br>$$<br>f(x)=\left{<br>\begin{aligned}<br>&\frac{1}{b-a} &a\leq x\leq b \<br>&0&\text{其他}<br>\end{aligned}<br>\right.<br>\quad(a<b)<br>$$<br>则称$X$在区间$[a,b]$上服从均匀分布,记作$X\sim U[a,b]$</p><p>相应的分布函数为<br>$$<br>F(x)=\left{<br>\begin{aligned}<br>&0&x<a \<br>&\frac{x-a}{b-a}&a\leq x<b\<br>&1&x\geq b<br>\end{aligned}<br>\right.<br>$$</p><h4 id="3-4-3-指数分布"><a href="#3-4-3-指数分布" class="headerlink" title="3.4.3. 指数分布"></a>3.4.3. 指数分布</h4><p>设连续型随机变量$X$的概率密度为<br>$$<br>f(x)=\left{<br>\begin{aligned}<br>&0 &x\leq 0\<br>&\lambda e^{-\lambda x}&x>0<br>\end{aligned}<br>\right.<br>$$<br>其中$\lambda$是正常数,则称$X$是服从参数为$\lambda$的指数分布</p><p>相应的分布函数为<br>$$<br>F(x)=<br>\left{<br>\begin{aligned}<br>&0 &x\leq 0 \<br>&1-e^{-\lambda x} &x>0<br>\end{aligned}<br>\right.<br>$$</p><h4 id="3-4-4-正态分布"><a href="#3-4-4-正态分布" class="headerlink" title="3.4.4. 正态分布"></a>3.4.4. 正态分布</h4><ul><li><p>定义</p><p>若连续型随机变量$X$的概率密度为<br>$$<br>f(x)=\frac{1}{\sigma\sqrt{2\pi}}e^{-\frac{(x-\mu)^2}{2\sigma^2}},\quad -\infty <x < +\infty<br>$$<br>其中$\mu,\sigma$为常数,且$\sigma >0$则称$X$是服从参数为$\mu,\sigma$的正态分布,也称$X$为正态变量,记作$X\sim N(\mu,\sigma)$</p><p>若$\mu=0,\sigma=1$,则称为标准正态分布</p></li><li><p>分布函数</p><p>记标准正态分布的分布函数为$\Phi(x)$,则一般正态分布$N(\mu,\sigma)$的分布函数$F(x)$<br>$$<br>F(x)=\Phi(\frac{x-\mu}{\sigma})<br>$$</p></li></ul><h3 id="3-5-随机变量函数的分布"><a href="#3-5-随机变量函数的分布" class="headerlink" title="3.5. 随机变量函数的分布"></a>3.5. 随机变量函数的分布</h3><p>设随机变量$Y$是随机变量$X$的函数,且$Y=g(X)$</p><ul><li><p>$X$为离散的,只需按照加法公式计算后相加</p></li><li><p>$X$是连续型随机变量,其概率密度为$f_X(x)$,求随机变量$Y$的概率密度$f_Y(y)$</p><p>采用分布函数法,先求$F_Y(y)$</p><ul><li>已知$X\sim N(\mu, \sigma^2)$,求$Y=\frac{X-\mu}{\sigma}$的概率密度<br>$$<br>F_Y(y)=P(Y\leq y)=P(X\leq \sigma y+\mu)=F_X(\sigma y+\mu)<br>$$<br>可以看出$F_Y(y)$处处连续,故<br>$$<br>f_Y(y)=\sigma f_X(\sigma y + \mu)= \sigma \frac{1}{\sigma\sqrt{2\pi}}e^{-\frac{(\sigma y+\mu-\mu)^2}{2\sigma^2}}=\frac{1}{\sqrt{2\pi}}e^{-\frac{y^2}{2}}<br>$$</li></ul></li></ul><h2 id="4-多维随机变量及其分布"><a href="#4-多维随机变量及其分布" class="headerlink" title="4. 多维随机变量及其分布"></a>4. 多维随机变量及其分布</h2><h3 id="4-1-一些定义"><a href="#4-1-一些定义" class="headerlink" title="4.1. 一些定义"></a>4.1. 一些定义</h3><h4 id="4-1-1-多维随机变量"><a href="#4-1-1-多维随机变量" class="headerlink" title="4.1.1. 多维随机变量"></a>4.1.1. 多维随机变量</h4><p>若$X_1(e),X_2(e),\cdots, X_n(e)$是定义在同一个样本空间上$S$上的$n$个随机变量,$e \in S$,则由他们构成一个$n$维向量$(X_1(e),X_2(e),\cdots, X_n(e))$称为**$n$维随机变量**</p><h4 id="4-1-2-分布函数"><a href="#4-1-2-分布函数" class="headerlink" title="4.1.2. 分布函数"></a>4.1.2. 分布函数</h4><p>设$(X,Y)$为二维随机变量,$x,y$为任意实数,则二元函数<br>$$<br>F(x,y)=P(X\leq x, Y\leq y)<br>$$<br>称为$(X,Y)$的分布函数,或称为$X$和$Y$的联合分布函数</p><p>易知<br>$$<br>F(+\infty,+\infty)=1,F(-\infty,+\infty)=F(+\infty,-\infty)=0<br>$$</p><p><font color="red">注意:求$x_1<X\leq x_2, y_1<Y\leq y_2$的概率时按如下公式</font><br>$$<br>\begin{aligned}<br>&P\left(x_1<X\leq x_2,y_2<Y\leq y_2\right)\<br>=&F(x_2,y_2)-F(x_2,y_1)-F(x_1,y_2)+F(x_1,y_1)<br>\end{aligned}<br>$$</p><h4 id="4-1-3-边缘分布函数"><a href="#4-1-3-边缘分布函数" class="headerlink" title="4.1.3. 边缘分布函数"></a>4.1.3. 边缘分布函数</h4><p>如果二维随机变量$(X,Y)$的分布函数$F(X,Y)$为已知,那么<br>$$<br>F_X(x)=P(X\leq x, y<+\infty) = F(x, +\infty)<br>$$</p><h3 id="4-2-二维离散型随机变量"><a href="#4-2-二维离散型随机变量" class="headerlink" title="4.2. 二维离散型随机变量"></a>4.2. 二维离散型随机变量</h3><p>可利用表格形式表示</p><p><img src="https://cdn.jsdelivr.net/gh/tsdsnk/imgs@main/img/QQ%E6%88%AA%E5%9B%BE20230221171627.png" alt="分布列及边缘分布"></p><h3 id="4-3-二维连续型随机变量"><a href="#4-3-二维连续型随机变量" class="headerlink" title="4.3. 二维连续型随机变量"></a>4.3. 二维连续型随机变量</h3><ul><li><p>联合概率密度</p><p>设二维随机变量$(X,Y)$的分布函数为$F(x,y)$。若存在非负函数$f(x,y)$使得对任意实数$x,y$有<br>$$<br>F(x,y)=\int_{-\infty}^{x}\int_{-\infty}^y f(u,v)dudv<br>$$<br>则称$(X,Y)$为二维连续随机变量,并称$f(x,y)$为二维随机变量$(X,Y)$的<strong>概率密度</strong>,或称$X$与$Y$的联合概率密度</p><p>若$f(x,y)$在点$(x,y)$处连续,则<br>$$<br>\frac{\part^2F(x,y)}{\part x\part y} = f(x,y)<br>$$</p></li><li><p>边缘概率密度<br>$$<br>f_X(x)=\int_{-\infty}^{+\infty}f(x,y)dy<br>$$</p><p>$$<br>f_Y(y)=\int_{-\infty}^{+\infty}f(x,y)dx<br>$$</p></li></ul><h3 id="4-4-随机变量的独立性"><a href="#4-4-随机变量的独立性" class="headerlink" title="4.4. 随机变量的独立性"></a>4.4. 随机变量的独立性</h3><ul><li><p>定义</p><p>设$F(x,y),F_X(x),F_Y(y)$依次为$(X,Y),X,Y$的分布函数。若对任意实数$x,y$成立<br>$$<br>F(x,y)=F_X(x)F_Y(y)<br>$$<br>则称$X$与$Y$是相互独立的</p></li><li><p>充要条件</p><p>$f_X(x)f_Y(y)$是二维随机变量的概率密度</p></li></ul><h3 id="4-5-二维随机变量函数的分布"><a href="#4-5-二维随机变量函数的分布" class="headerlink" title="4.5. 二维随机变量函数的分布"></a>4.5. 二维随机变量函数的分布</h3><p>离散型随机变量与连续型随机变量(求分布函数)均与一维类似</p><p>一些结论</p><ul><li>$X,Y$<u>独立</u>,且$X\sim P(\lambda_1),Y\sim P(\lambda_2)$,则$X+Y\sim P(\lambda_1+\lambda_2)$</li><li>$X,Y$<u>独立</u>,且$X\sim N(\mu_1,\sigma_1^2),Y\sim N(\mu_2,\sigma_2^2)$,则$X+Y\sim N(\lambda_1+\lambda_2,\sigma_1^2+\sigma_2^2)$</li></ul><h4 id="4-5-1-瑞利分布"><a href="#4-5-1-瑞利分布" class="headerlink" title="4.5.1. 瑞利分布"></a>4.5.1. 瑞利分布</h4><p>设$X,Y$是<u>相互独立</u>的且服从同一正态分布$N(0,\sigma^2)$的随机变量,则$Z=\sqrt{X^2+Y^2}$服从瑞利分布</p><blockquote><p>考虑$Z$的分布函数</p><p>当$z\leqslant 0$时,$F_Z(z)=0$</p><p>当$z>0$时<br>$$<br>F_Z(z)=P(\sqrt{X^2+Y^2}\leqslant z)=\iint\limits_{\sqrt{x^2+y^2}\leqslant z}f(x,y)dxdy<br>$$<br>由于$X,Y$相互独立<br>$$<br>F_Z(z)=\iint\limits_{\sqrt{x^2+y^2}\leqslant z}f_X(x)f_Y(y)dxdy=\iint\limits_{\sqrt{x^2+y^2}\leqslant z}\frac{1}{2\pi\sigma^2}e^{-\frac{x^2+y^2}{2\sigma^2}}dxdy<br>$$<br>令$x=\rho\cos\theta,y=\rho\sin\theta$,得<br>$$<br>F_Z(z)=\iint\limits_{\rho \leqslant z}\frac{1}{2\pi\sigma^2}e^{-\frac{\rho^2}{2\sigma^2}}\rho d\rho d\theta = 1-e^{-\frac{z^2}{2\sigma^2}}<br>$$<br>因此$Z$的分布函数为<br>$$<br>F_Z(z)=\left{<br>\begin{aligned}<br>&1-e^{-\frac{z^2}{2\sigma^2}}, &z>0\<br>&0, &z\leqslant0<br>\end{aligned}<br>\right.<br>$$<br>概率密度为<br>$$<br>f_Z(z)=\left{\begin{aligned}<br>&\frac{z}{\sigma^2}e^{-\frac{z^2}{2\sigma^2}}, &z>0\<br>&0,&z\leqslant 0<br>\end{aligned}\right.<br>$$</p></blockquote>]]></content>
<tags>
<tag>考研</tag>
</tags>
</entry>
<entry>
<title>高数</title>
<link href="/2023/01/04/%E9%AB%98%E6%95%B0/"/>
<url>/2023/01/04/%E9%AB%98%E6%95%B0/</url>
<content type="html"><![CDATA[<h2 id="0-常用函数"><a href="#0-常用函数" class="headerlink" title="0. 常用函数"></a>0. 常用函数</h2><p>$$<br>\begin{aligned}<br>(\tan x)^{‘}&=\sec^2 x\<br>(\cot x)^{‘}&=-\csc^2 x\<br>(\sec x)^{‘}&=\sec x\tan x\<br>(\csc x)^{‘}&=-\csc x \cot x\<br>(\arcsin x)^{‘}&=\frac{1}{\sqrt{1-x^2}}\<br>(\arccos x)^{‘}&=-\frac{1}{\sqrt{1-x^2}}\<br>(\arctan x)^{‘}&=\frac{1}{1+x^2}\<br>(\text{arccot }x)^{‘}&=-\frac{1}{1+x^2}<br>\end{aligned}<br>$$</p><h2 id="1-函数与极限"><a href="#1-函数与极限" class="headerlink" title="1. 函数与极限"></a>1. 函数与极限</h2><h3 id="1-1-映射与函数"><a href="#1-1-映射与函数" class="headerlink" title="1.1. 映射与函数"></a>1.1. 映射与函数</h3><ul><li><p>函数的几种特性</p><ul><li><p>有界性</p><p>设函数$f(x)$的定义域为$D$,数集$X\sub D$,如果存在数$K_1$,使得<br>$$<br>f(x)\leqslant K_1<br>$$<br>对任一$x \in X$都成立,那么称函数$f(x)$在$X$上有<strong>上界</strong>,而$K_1$称为函数$f(x)$在$X$上的一个上界</p><p>如果存在正数$M$,使得<br>$$<br>|f(x)|\leqslant M<br>$$<br>对任一$x\in X$都成立,那么称函数$f(x)$在$X$上<strong>有界</strong></p></li><li><p>单调性</p></li><li><p>奇偶性</p></li><li><p>周期性</p><p><font color="red">并非每个周期函数都有最小的正周期</font></p><p>如狄利克雷(Dirichlet)函数<br>$$<br>D(x)=\left{<br>\begin{aligned}<br>& 1, \quad x\in \mathbf{Q}\<br>& 0, \quad x\in \mathbf{Q}^C<br>\end{aligned}<br>\right.<br>$$<br>任何正有理数都是其周期</p></li></ul></li><li><p>初等函数</p><ul><li>基本初等函数<ul><li>幂函数</li><li>指数函数</li><li>对数函数</li><li>三角函数</li><li>反三角函数</li></ul></li><li>由常数和基本初等函数经过有限次的四则运算和有限次的函数复合步骤所构成,并可用一个式子表示的函数称为<strong>初等函数</strong></li></ul></li></ul><h3 id="1-2-数列的极限"><a href="#1-2-数列的极限" class="headerlink" title="1.2. 数列的极限"></a>1.2. 数列的极限</h3><h4 id="1-2-1-定义"><a href="#1-2-1-定义" class="headerlink" title="1.2.1. 定义"></a>1.2.1. 定义</h4><p>设${x_n}$为一数列,如果存在常数$a$,对于任意给定的正数$\epsilon$,总存在正整数$N$,使得当$n>N$时,不等式<br>$$<br>|x_n-a|<\epsilon<br>$$<br>都成立,那么就称常数$a$是数列${x_n}$的极限,或者称数列${x_n}$收敛于$a$,记为<br>$$<br>\lim_{n\to \infty}x_n = a<br>$$<br>或<br>$$<br>x_n \to a(n\to \infty)<br>$$<br>如果不存在这样的常数$a$,就说数列${x_n}$没有极限(或发散),习惯上也说$\lim\limits_{n\to \infty}x_n$不存在</p><h4 id="1-2-2-性质"><a href="#1-2-2-性质" class="headerlink" title="1.2.2. 性质"></a>1.2.2. 性质</h4><ul><li><p>极限的唯一性</p><p>如果数列${x_n}$收敛,那么它的极限唯一</p></li><li><p>收敛数列的有界性</p><p>如果数列${x_n}$收敛,那么数列${x_n}$一定有界</p></li><li><p>收敛数列的保号性</p><p>如果$\lim\limits_{n\to \infty}x_n=a$,且$a>0$(或$a<0$),那么存在正整数$N$,当$n>N$时,都有$x_n>0$(或$x_n<0$)</p><p>推论 如果数列${x_n}$自某项起有$x_n\geqslant 0$,且$\lim\limits_{n\to \infty}x_n=a$,那么$a\geqslant 0$</p></li><li><p>收敛数列与子数列的关系</p><p>如果数列${x_n}$收敛于$a$,那么它的任一子数列也收敛,且极限也是$a$</p><blockquote><p><font color="99ccff">一个例子</font></p><p>证明数列$x_n=(-1)^{n+1},(n=1,2,\cdots)$是发散的</p><p>可证明其存在两个子数列收敛但收敛值不相同</p></blockquote></li></ul><h3 id="1-3-函数的极限"><a href="#1-3-函数的极限" class="headerlink" title="1.3. 函数的极限"></a>1.3. 函数的极限</h3><h4 id="1-3-1-定义"><a href="#1-3-1-定义" class="headerlink" title="1.3.1. 定义"></a>1.3.1. 定义</h4><ul><li><p>自变量趋于有限值</p><p>设函数$f(x)$在点$x_0$的某一去心邻域内有定义。如果存在常数$A$,对于任意给定的正数$\epsilon$,总存在正数$\delta$,使得当$x$满足不等式$0<|x-x_0|<\delta$时,对应的函数值$f(x)$都满足不等式<br>$$<br>|f(x)-A|<\epsilon<br>$$<br>那么常数$A$就叫做函数$f(x)$当$x\to x_0$时的极限</p></li><li><p>自变量趋于无穷大</p><p>设函数$f(x)$在$|x|$大于某一正数时有定义。如果存在常数$A$,对于任意给定的正数$\epsilon$,总存在着正数$X$,使得当$x$满足不等式$x>|X|$时,对应的函数值$f(x)$都满足不等式<br>$$<br>|f(x)-A|<\epsilon<br>$$<br>那么常数$A$就叫做函数$f(x)$当$x\to\infty$时的极限</p></li></ul><h4 id="1-3-2-性质"><a href="#1-3-2-性质" class="headerlink" title="1.3.2. 性质"></a>1.3.2. 性质</h4><ul><li><p>函数极限的唯一性</p><p>如果$\lim\limits_{x\to x_0}f(x)$存在,那么这极限唯一</p></li><li><p>函数极限的局部有界性</p><p>如果$\lim\limits_{x\to x_0}f(x)=A$,那么存在常数$M>0$和$\delta>0$,使得当$0<|x-x_0|<\delta$时,有$|f(x)|\leqslant M$</p></li><li><p>函数极限的局部保号性</p><p>如果$\lim\limits_{x\to x_0}f(x)=A$,且$A>0$,那么存在常数$\delta >0$,使得当$0<|x-x_0|<\delta$时,有$f(x)>0$</p><p>如果$\lim\limits_{x\to x_0}f(x)=A$,且$A\neq 0$,那么存在$x_0$的某一去心邻域$\mathring{U}(x_0)$,当$x\in \mathring{U}(x_0)$时,就有$|f(x)|>\frac{|A|}{2}$</p></li><li><p>函数极限与数列极限的关系</p><p>如果极限$\lim \limits_{x\to x_0}f(x)$存在,${x_n}$为函数$f(x)$的定义域内任一收敛于$x_0$的数列,且满足:$x_n\neq x_0,(n\in \mathbf{N}<em>+)$,那么相应的函数值数列${f(x_n)}$必收敛,且$\lim \limits</em>{n\to \infty}f(x_n)=\lim \limits_{x\to x_0}f(x)$</p></li></ul><h3 id="1-4-无穷小与无穷大"><a href="#1-4-无穷小与无穷大" class="headerlink" title="1.4. 无穷小与无穷大"></a>1.4. 无穷小与无穷大</h3><h4 id="1-4-1-无穷小"><a href="#1-4-1-无穷小" class="headerlink" title="1.4.1. 无穷小"></a>1.4.1. 无穷小</h4><ul><li><p>定义</p><p>如果函数$f(x)$当$x\to x_0$(或$x\to \infty$)时的极限为零,那么称函数$f(x)$为当$x\to x_0$(或$x\to \infty$)时的无穷小</p></li><li><p>定理</p><p>在自变量的同一变化过程$x\to x_0$(或$x\to \infty$)中,函数$f(x)$具有极限$A$的充分必要条件是$f(x)=A+\alpha$,其中$\alpha$是无穷小</p></li></ul><h4 id="1-4-2-无穷大"><a href="#1-4-2-无穷大" class="headerlink" title="1.4.2. 无穷大"></a>1.4.2. 无穷大</h4><ul><li><p>定义</p><p>设函数$f(x)$在$x_0$的某一去心邻域内有定义(或$|x|$大于某一正数时有定义)。如果对于任意给定的正数$M$,总存在正数$\delta$(或正数$X$),只要$x$适合不等式$0<|x-x_0|<\delta$(或$|x-x_0|>X$),对应的函数值总满足不等式<br>$$<br>|f(x)|>M<br>$$<br>那么称函数$f(x)$是当$x\to x_0$(或$x\to \infty$)时的无穷大</p></li><li><p>定理</p><p>在自变量的同一变化过程中,如果$f(x)$为无穷大,那么$\frac{1}{f(x)}$为无穷小;反之,如果$f(x)$为无穷小,且$f(x)\neq 0$,那么$\frac{1}{f(x)}$为无穷大</p></li></ul><h3 id="1-5-极限运算法则"><a href="#1-5-极限运算法则" class="headerlink" title="1.5. 极限运算法则"></a>1.5. 极限运算法则</h3><ul><li><p>两个无穷小的和是无穷小</p><p>数学归纳法可证,有限个无穷小的和是无穷小</p></li><li><p>有界函数和无穷小的乘积是无穷小</p><p>推论</p><ul><li>常数与无穷小的乘积是无穷小</li><li>有限个无穷小的乘积是无穷小</li></ul></li><li><p>如果$\lim f(x)=A,\lim g(x)=B$</p><ul><li>$\lim [f(x)\pm g(x)]=\lim f(x)\pm\lim g(x)$</li><li>$\lim[f(x)\cdot g(x)]=\lim f(x)\cdot \lim g(x)$</li><li>若$B\neq 0$,则$\lim\frac{f(x)}{g(x)}=\frac{\lim f(x)}{\lim g(x)}$</li></ul></li><li><p>(定理三的数列形式)</p></li><li><p>设函数$y=f[g(x)]$是由函数$u=g(x)$与函数$y=f(u)$复合而成,$f[g(x)]$在点$x_0$的某去心邻域内有定义,若$\lim\limits_{x\to x_0}g(x)=u_0$,$\lim\limits_{u\to u_0}f(u)=A$,且存在$\delta_0 >0$,当$x\in\mathring{U}(x_0,\delta_0)$时,有$g(x)\neq u_0$,则<br>$$<br>\lim_{x\to x_0}f[g(x)]=\lim_{u\to u_0}f(u)=A<br>$$</p></li></ul><h3 id="1-6-极限存在准则"><a href="#1-6-极限存在准则" class="headerlink" title="1.6. 极限存在准则"></a>1.6. 极限存在准则</h3><ul><li><p><strong>准则1(夹逼准则)</strong></p><p>如果数列${x_n},{y_n},{z_n}$满足</p><ul><li>$\exist n_0\in\mathbf{N}_+$,当$n>n_0$时有$y_n\leqslant x_n\leqslant z_n$</li><li>$\lim\limits_{n\to \infty}y_n=a,\lim\limits_{n\to \infty}z_n=a$</li></ul><p>那么数列${x_n}$的极限存在,且$\lim\limits_{n\to \infty}x_n = a$</p><p>(可推广至函数)</p><blockquote><p>此准则可证明$\lim\limits_{x\to 0}\frac{\sin x}{x}=1$</p><p>利用扇形内的面积关系即可得到<br>$$<br>\sin x<x<\tan x<br>$$</p></blockquote></li><li><p><strong>准则2</strong></p><p>单调有界数列必有极限</p><p>(可推广至函数,下以$x\to x_0^-$为例)</p><p>设函数$f(x)$在点$x_0$的某个左邻域内单调且有界,则$f(x)$在$x_0$的左极限$f(x_0^-)$一定存在</p><blockquote><p>此准则可以说明$\lim\limits_{x\to \infty}(1+\frac{1}{x})^x$存在,为$e$</p><p>应用复合函数的极限运算法则可以得到$\lim\limits_{x\to \infty}(1-\frac{1}{x})^x=\frac{1}{e}$等</p></blockquote></li><li><p><strong>柯西极限存在准则</strong></p><p>数列${x_n}$收敛的<u>充分必要条件</u>是:对于任意给定的正数$\epsilon$,存在正数$N$,使得当$m>N,n>N$时有<br>$$<br>|x_m-x_n|<\epsilon<br>$$</p></li></ul><h3 id="1-7-无穷小的比较"><a href="#1-7-无穷小的比较" class="headerlink" title="1.7. 无穷小的比较"></a>1.7. 无穷小的比较</h3><h4 id="1-7-1-定义"><a href="#1-7-1-定义" class="headerlink" title="1.7.1. 定义"></a>1.7.1. 定义</h4><ul><li>如果$\lim\frac{\beta}{\alpha}=0$,那么就说$\beta$是比$\alpha$高阶的无穷小,记作$\beta = o(\alpha)$</li><li>如果$\lim\frac{\beta}{\alpha}=\infty$,那么就说$\beta$是比$\alpha$低阶的无穷小</li><li>如果$\lim\frac{\beta}{\alpha}=c\neq 0$,那么就说$\beta$与$\alpha$同阶无穷小</li><li>如果$\lim\frac{\beta}{\alpha^k}=c\neq 0$,那么就说$\beta$是关于$\alpha$的$k$阶无穷小</li><li>如果$\lim\frac{\beta}{\alpha}=1$,那么就说$\beta$与$\alpha$是等价无穷小,记作$\alpha \sim \beta$</li></ul><h4 id="1-7-2-定理"><a href="#1-7-2-定理" class="headerlink" title="1.7.2. 定理"></a>1.7.2. 定理</h4><ul><li>$\beta$与$\alpha$是等价无穷小的充分必要条件是$\beta = \alpha + o(\alpha)$</li><li>设$\alpha \sim \tilde{\alpha},\beta\sim\tilde{\beta}$,且$\lim\frac{\tilde{\beta}}{\tilde{\alpha}}$存在,则$\lim\frac{\alpha}{\beta}=\lim\frac{\tilde{\beta}}{\tilde{\alpha}}$</li></ul><h3 id="1-8-函数的连续性与间断点"><a href="#1-8-函数的连续性与间断点" class="headerlink" title="1.8. 函数的连续性与间断点"></a>1.8. 函数的连续性与间断点</h3><h4 id="1-8-1-函数的连续性"><a href="#1-8-1-函数的连续性" class="headerlink" title="1.8.1. 函数的连续性"></a>1.8.1. 函数的连续性</h4><ul><li><p>定义</p><p>设函数$y=f(x)$在点$x_0$的某一邻域内有定义,如果<br>$$<br>\lim_{\Delta x\to 0}\Delta y = \lim_{\Delta x\to 0}[f(x_0+\Delta x)-f(x_0)] = 0<br>$$<br>那么就称函数$y = f(x)$在$x_0$点连续</p></li></ul><h4 id="1-8-2-函数的间断点"><a href="#1-8-2-函数的间断点" class="headerlink" title="1.8.2. 函数的间断点"></a>1.8.2. 函数的间断点</h4><ul><li><p>定义</p><p>若函数$f(x)$在点$x_0$的某去心邻域内有定义,若满足以下条件之一</p><ul><li>在$x=x_0$没有定义</li><li>在$x=x_0$有定义,但$\lim\limits_{x\to x_0}f(x)$不存在</li><li>在$x=x_0$有定义,$\lim\limits_{x\to x_0}f(x)$存在,但$\lim\limits_{x\to x_0}f(x)\neq f(x_0)$</li></ul><p>那么函数$f(x)$在$x_0$不连续,称点$x_0$为函数$f(x)$的不连续点或间断点</p></li><li><p>分类</p><ul><li>第一类间断点(左右极限都存在)<ul><li>可去间断点(左右极限相等)</li><li>跳跃间断点(左右极限不相等)</li></ul></li><li>第二类间断点<ul><li>无穷间断点</li><li>振荡间断点</li><li>…</li></ul></li></ul></li></ul><h3 id="1-9-连续函数的运算与初等函数的连续性"><a href="#1-9-连续函数的运算与初等函数的连续性" class="headerlink" title="1.9. 连续函数的运算与初等函数的连续性"></a>1.9. 连续函数的运算与初等函数的连续性</h3><ul><li><p>设函数$f(x)$和$g(x)$在点$x_0$连续,则他们的和(差)$f\pm g$,积$f\cdot g$,商$\frac{f}{g}$(当$g(x)\neq 0$时)都在$x_0$连续</p></li><li><p>如果函数$y=f(x)$在区间$I_x$上单调增加(或单调减少)且连续,那么它的反函数$x=f^{-1}(y)$也在对应区间$I_y={y|y=f(x),x\in I_x}$上单调增加(或单调减少)且连续</p></li><li><p>设函数$y=f[g(x)]$由函数$u=g(x)$与函数$y=f(u)$复合而成,$\mathring{U}(x_0)\in D_{f\circ g}$,若$\lim \limits_{x\to x_0}g(x)=u_0$,而函数$f(u)$在$u=u_0$连续,则<br>$$<br>\lim_{x\to x_0}f[g(x)]=\lim_{u\to u_0}f(u)=f(u_0)<br>$$</p></li><li><p>设函数$y=f[g(x)]$由函数$u=g(x)$与函数$y=f(u)$复合而成,$\mathring{U}(x_0)\in D_{f\circ g}$,若$g(x)$在$x=x_0$连续,且$g(x_0)=u_0$,而函数$y=f(u)$在$u=u_0$连续,则复合函数$y=f[g(x)]$在$x=x_0$也连续</p></li><li><p>基本初等函数在其定义域内都是连续的</p></li></ul><hr><p><font color="99ccff">一些例题</font></p><ul><li><p>求$\lim \limits_{x\to 0}\frac{\log_a(x+1)}{x}$</p><blockquote><p>$$<br>\lim_{x\to 0}\frac{\log_a(x+1)}{x} =\lim_{x\to 0}\log_a (1+x)^{\frac{1}{x}}=\frac{1}{\ln a}<br>$$</p></blockquote></li><li><p>求$\lim\limits_{x\to 0}\frac{a^x-1}{x}$</p><blockquote><p>令$t=a^x-1$,则$x=\log_a(t+1)$,当$x\to 0$时$t\to 0$<br>$$<br>\lim_{x\to 0}\frac{a^x-1}{x}=\lim_{t\to 0}\frac{t}{\log_a(t+1)}=\ln a<br>$$</p></blockquote></li><li><p>求$\lim\limits_{x\to 0}\frac{(1+x)^\alpha -1}{x}$</p><blockquote><p>$$<br>\begin{aligned}<br>&\lim_{x\to 0}\frac{(1+x)^\alpha-1}{x} \<br>=&\lim_{x\to 0}\frac{(1+x)^\alpha-1}{\ln (1+x)^\alpha} \frac{\alpha\ln(1+x)}{x}\<br>=&\lim_{x\to 0}\frac{(1+x)^\alpha-1}{\ln (1+x)^\alpha}\lim_{x\to 0}\frac{\alpha\ln(1+x)}{x}\<br>=&\alpha<br>\end{aligned}<br>$$</p></blockquote></li><li><p>求$\lim\limits_{x\to 0}(1+2x)^{\frac{3}{\sin x}}$</p><blockquote><p>$$<br>\begin{aligned}<br>&\lim_{x\to 0}(1+2x)^{\frac{3}{\sin x}}\<br>=& \lim_{x\to 0}(1+2x)^{\frac{1}{2x}\frac{6x}{\sin x}}\<br>=&\lim_{x\to 0}e^{\frac{6x}{\sin x}\ln(1+2x)^{\frac{1}{2x}}} \<br>=&e^{6\lim\limits_{x\to 0}\frac{x}{\sin x}\cdot\lim\limits_{x\to 0}\ln(1+2x)^{\frac{1}{2x}}}\<br>=&e^6<br>\end{aligned}<br>$$</p></blockquote></li></ul><h3 id="1-10-闭区间上的连续函数的性质"><a href="#1-10-闭区间上的连续函数的性质" class="headerlink" title="1.10. 闭区间上的连续函数的性质"></a>1.10. 闭区间上的连续函数的性质</h3><h4 id="1-10-1-有界性与最大最小值定理"><a href="#1-10-1-有界性与最大最小值定理" class="headerlink" title="1.10.1. 有界性与最大最小值定理"></a>1.10.1. 有界性与最大最小值定理</h4><p>在闭区间上连续的函数在该区间有界且一定能取得它的最大值和最小值。</p><h4 id="1-10-2-零点定理"><a href="#1-10-2-零点定理" class="headerlink" title="1.10.2. 零点定理"></a>1.10.2. 零点定理</h4><p>设函数$f(x)$在闭区间$[a,b]$上连续,且$f(a)$与$f(b)$异号(即$f(a)\cdot f(b)<0$),则开区间$(a,b)$内至少有一点$\xi$,使<br>$$<br>f(\xi)=0<br>$$</p><h4 id="1-10-3-介值定理"><a href="#1-10-3-介值定理" class="headerlink" title="1.10.3. 介值定理"></a>1.10.3. 介值定理</h4><p>设函数$f(x)$在闭区间$[a,b]$内连续,且在这区间的端点取不同的函数值<br>$$<br>f(a)=A\quad\text{及}\quad f(b)=B<br>$$<br>则对应$A$与$B$之间的任意一个数$C$,在开区间$(a,b)$内至少有一点$\xi$,使得<br>$$<br>f(\xi)=C<br>$$</p><h4 id="1-10-4-一致连续性"><a href="#1-10-4-一致连续性" class="headerlink" title="1.10.4. 一致连续性"></a>1.10.4. 一致连续性</h4><p>设函数$f(x)$在区间$I$上有定义。如果对于任意给定的正数$\epsilon$,总存在正数$\delta$,使得对于区间上任意的两点$x_1,x_2$,当$|x_1-x_2|<\delta$时<br>$$<br>|f(x_1)-f(x_2)|<\delta<br>$$<br>那么称函数$f(x)$在区间$I$上一致连续</p><h4 id="1-10-5-一致连续性定理"><a href="#1-10-5-一致连续性定理" class="headerlink" title="1.10.5. 一致连续性定理"></a>1.10.5. 一致连续性定理</h4><p>如果函数$f(x)$在闭区间$[a,b]$上连续,那么它在该区间上一致连续</p><h2 id="2-导数与微分"><a href="#2-导数与微分" class="headerlink" title="2. 导数与微分"></a>2. 导数与微分</h2><h3 id="2-1-导数"><a href="#2-1-导数" class="headerlink" title="2.1. 导数"></a>2.1. 导数</h3><ul><li><p>定义</p><p>设函数$y=f(x)$在点$x_0$的某个邻域内有定义,当自变量$x$在$x_0$处取得增量$\Delta x$(点$x_0+\Delta x$仍在该邻域内)时,相应的,因变量取得增量$\Delta y=f(x_0+\Delta x)-f(x_0)$。如果$\lim\limits_{\Delta x\to 0}\frac{\Delta y}{\Delta x}$存在,那么称函数$y=f(x)$在$x=x_0$点可导,并称该极限为函数$y=f(x)$在点$x_0$处的导数,记为$f’(x_0)$,即<br>$$<br>f’(x_0)=\lim_{\Delta x\to 0}\frac{f(x_0+\Delta x)-f(x_0)}{\Delta x}<br>$$</p></li><li><p>单侧导数</p><p><strong>极限存在的充分必要条件是左右极限都存在且相等</strong>,因此$f’(x_0)$存在的充分必要条件是左右极限<br>$$<br>\lim_{h\to 0^-}\frac{f(x_0+h)-f(x_0)}{h}\quad\text{及}\quad\lim_{h\to 0^+}\frac{f(x_0+h)-f(x_0)}{h}<br>$$<br>都存在且相等,上述两极限分别称为左导数和右导数,统称为单侧导数</p></li></ul><h3 id="2-2-函数的求导法则"><a href="#2-2-函数的求导法则" class="headerlink" title="2.2. 函数的求导法则"></a>2.2. 函数的求导法则</h3><h4 id="2-2-1-和差积商"><a href="#2-2-1-和差积商" class="headerlink" title="2.2.1. 和差积商"></a>2.2.1. 和差积商</h4><ul><li>$[u(x)\pm v(x)]’=u’(x)\pm v’(x)$</li><li>$[u(x)v(x)]’=u’(x)v(x)+u(x)v’(x)$</li><li>$[\frac{u(x)}{v(x)}]’=\frac{u’(x)v(x)-u(x)v’(x)}{v^2(x)},(v(x)\neq 0)$</li></ul><h4 id="2-2-2-反函数"><a href="#2-2-2-反函数" class="headerlink" title="2.2.2. 反函数"></a>2.2.2. 反函数</h4><p>如果函数$x=f(y)$在区间$I_y$单调、可导,且$f’(y)\neq 0$,那么它的反函数$y=f^{-1}(x)$在区间$I_x={x|x=f(y),y\in I_y}$内也可导,且<br>$$<br>\frac{dy}{dx}=\frac{1}{\frac{dx}{dy}}<br>$$</p><h4 id="2-2-3-复合函数"><a href="#2-2-3-复合函数" class="headerlink" title="2.2.3. 复合函数"></a>2.2.3. 复合函数</h4><p>如果$u=g(x)$在点$x$可导,而$y=f(u)$在点$u=g(x)$可导,那么复合函数$y=f[g(x)]$在点$x$可导,其导数为<br>$$<br>\frac{dy}{dx}=\frac{dy}{du}\cdot \frac{du}{dx}<br>$$</p><h3 id="2-3-高阶导数"><a href="#2-3-高阶导数" class="headerlink" title="2.3. 高阶导数"></a>2.3. 高阶导数</h3><p>定义略</p><p>莱布尼茨公式:$u+v$的$n$阶导数为(类比二项式展开)<br>$$<br>(u+v)^{(n)}=\sum_{k=0}^{n}C_n^k u^{(n-k)}v^{(k)}<br>$$</p><h3 id="2-4-隐函数、参数方程求导"><a href="#2-4-隐函数、参数方程求导" class="headerlink" title="2.4. 隐函数、参数方程求导"></a>2.4. 隐函数、参数方程求导</h3><h4 id="2-4-1-隐函数"><a href="#2-4-1-隐函数" class="headerlink" title="2.4.1. 隐函数"></a>2.4.1. 隐函数</h4><p>略,注意可以取$\ln$等方法</p><h4 id="2-4-2-参数方程"><a href="#2-4-2-参数方程" class="headerlink" title="2.4.2. 参数方程"></a>2.4.2. 参数方程</h4><p>参数方程<br>$$<br>\left{<br>\begin{aligned}<br>x=\psi(x)\<br>y=\Psi(x)<br>\end{aligned}<br>\right.<br>$$<br>则<br>$$<br>\frac{dy}{dx}=\frac{dy}{dt}\cdot\frac{1}{\frac{dt}{dx}}=\frac{\Psi’(t)}{\psi’(t)}<br>$$</p><h3 id="2-5-函数的微分"><a href="#2-5-函数的微分" class="headerlink" title="2.5. 函数的微分"></a>2.5. 函数的微分</h3><p>设函数$y=f(x)$在某区间内有定义,$x_0$及$x_0+\Delta x$区间内,如果函数的增量<br>$$<br>f(x_0+\Delta x)-f(x_0)<br>$$<br>可以表示为<br>$$<br>\Delta y = A\Delta x+o(\Delta x)<br>$$<br>其中$A$是不依赖于$\Delta x$的常数,那么称函数$y=f(x)$在点$x_0$是可微的,而$A\Delta x$叫做函数$y=f(x)$在点$x_0$相应于自变量增量$\Delta x$的微分,记作$dy$</p><p>函数$f(x)$在点$x_0$可微的<strong>充分必要条件</strong>是函数$f(x)$在点$x_0$可导</p><p><font color="red">注意$\Delta y$与$dy$的区别</font><br>$$<br>\Delta y = dy + o(dy)<br>$$</p>]]></content>
<categories>
<category>考研</category>
</categories>
</entry>
<entry>
<title>操作系统</title>
<link href="/2022/12/31/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/"/>
<url>/2022/12/31/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/</url>
<content type="html"><![CDATA[<h2 id="0-前言"><a href="#0-前言" class="headerlink" title="0. 前言"></a>0. 前言</h2><h3 id="0-1-参考书目"><a href="#0-1-参考书目" class="headerlink" title="0.1. 参考书目"></a>0.1. 参考书目</h3><ul><li>现代操作系统(Modern Operating System) (第4版)</li></ul><h2 id="1-进程与线程"><a href="#1-进程与线程" class="headerlink" title="1. 进程与线程"></a>1. 进程与线程</h2><h3 id="1-1-进程"><a href="#1-1-进程" class="headerlink" title="1.1. 进程"></a>1.1. 进程</h3><p>我们假设进程之间彼此是有敌意的,他们可能所属不同的用户,会相互争夺资源或相互破坏。</p><p>用户态能访问特定的寄存器,而非不能访问,否则正常代码也不能执行。</p><h4 id="1-1-1-进程的创建"><a href="#1-1-1-进程的创建" class="headerlink" title="1.1.1. 进程的创建"></a>1.1.1. 进程的创建</h4><ul><li><p>导致进程创建的4种主要事件</p><ul><li><p>系统初始化</p></li><li><p>正在运行的程序执行了创建进程的系统调用</p></li><li><p>用户请求创建一个新的进程</p><p>如交互式系统键入命令或点击图标</p></li><li><p>一个批处理作业的初始化</p><p>仅在大型机的批处理系统中使用,用户可以提交批处理作业。当操作系统认为资源足够运行另一个作业时,它会新建一个进程并运行输入队列的下一个作业</p></li></ul></li><li><p>地址空间</p><ul><li>在UNIX中<ul><li>不可写的内存区是共享的</li><li>或者,子进程共享父进程的所有内存,但写时复制</li></ul></li><li>在Windows中,从一开始父进程的地址空间和子进程的地址空间就是不同的</li></ul></li></ul><h4 id="1-1-2-进程的终止"><a href="#1-1-2-进程的终止" class="headerlink" title="1.1.2. 进程的终止"></a>1.1.2. 进程的终止</h4><ul><li>进程终止的原因<ul><li>正常退出</li><li>出错退出,自愿</li><li>严重错误,非自愿</li><li>被其他进程杀死</li></ul></li></ul><h4 id="1-1-3-进程的层次结构"><a href="#1-1-3-进程的层次结构" class="headerlink" title="1.1.3. 进程的层次结构"></a>1.1.3. 进程的层次结构</h4><ul><li><p>在UNIX中,树状结构</p><ul><li><p>在启动时,init出现在启动映像中,读入一个说明终端数量的文件。接着为每一个终端创建一个新进程,等待用户登录。如果有一个用户登录成功则执行一个shell</p></li><li><p>进程和其子进程组成一个进程组,用户从键盘发出的信号(如Ctrl + C)被发送给当前与键盘相关的进程组中的所有成员。</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><code class="hljs C"><span class="hljs-type">pid_t</span> <span class="hljs-title function_">getpgid</span><span class="hljs-params">(<span class="hljs-type">pid_t</span> pid)</span>; <span class="hljs-comment">//获取pid的进程组(进程组名一般是某个进程pid)</span><br><span class="hljs-type">int</span> <span class="hljs-title function_">setpgid</span><span class="hljs-params">(<span class="hljs-type">pid_t</span> pid, <span class="hljs-type">pid_t</span> pgid)</span>; <span class="hljs-comment">//设置进程组</span><br></code></pre></td></tr></table></figure><p>一个设置进程组例子如下:</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><code class="hljs C"><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string"><stdio.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string"><stdlib.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string"><unistd.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string"><sys/types.h></span> </span><br><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string"><sys/wait.h></span></span><br><br><span class="hljs-type">int</span> <span class="hljs-title function_">main</span><span class="hljs-params">()</span>{<br><br> <span class="hljs-type">pid_t</span> pid;<br><br> <span class="hljs-keyword">if</span>((pid = fork()) < <span class="hljs-number">0</span>){<br> perror(<span class="hljs-string">"fork"</span>);<br> <span class="hljs-built_in">exit</span>(<span class="hljs-number">-1</span>);<br> }<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(pid == <span class="hljs-number">0</span>){<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Child: pid:%d\tgroup id:%d\n"</span>, getpid(), getpgid(<span class="hljs-number">0</span>));<br> sleep(<span class="hljs-number">3</span>);<br> setpgid(getpid(), getpid());<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Child after change: pid:%d\tgroup id:%d\n"</span>, getpid(), getpgid(<span class="hljs-number">0</span>));<br> }<br> <span class="hljs-keyword">else</span>{<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Parent: pid:%d\tgroup id:%d\n"</span>, getpid(), getpgid(<span class="hljs-number">0</span>));<br> sleep(<span class="hljs-number">2</span>);<br> wait(<span class="hljs-number">0</span>);<br> }<br>}<br></code></pre></td></tr></table></figure></li></ul></li><li><p>Windows中,没有进程层次的概念,所有进程地位是相同的。</p><p>创建进程时父进程会得到一个特殊的令牌(称为句柄),可以控制子进程。令牌可以传送给其他进程</p></li></ul><h4 id="1-1-4-进程的状态"><a href="#1-1-4-进程的状态" class="headerlink" title="1.1.4. 进程的状态"></a>1.1.4. 进程的状态</h4><p>注意哪些状态转换不存在(如阻塞不能直接运行)</p><ul><li><p>五状态</p><p><img src="https://cdn.jsdelivr.net/gh/tsdsnk/imgs@main/img/QQ%E6%88%AA%E5%9B%BE20230105210735.png" alt="五状态"></p></li><li><p>七状态</p><p><img src="https://cdn.jsdelivr.net/gh/tsdsnk/imgs@main/img/QQ%E6%88%AA%E5%9B%BE20230105210755.png" alt="七状态"></p></li></ul><h4 id="1-1-5-进程的实现"><a href="#1-1-5-进程的实现" class="headerlink" title="1.1.5. 进程的实现"></a>1.1.5. 进程的实现</h4><ul><li><p>操作系统维护着一张表格,即进程表。每个进程占用一个表项(也称进程控制块),记录着进程的一些状态。</p></li><li><p>对于中断发生时:</p><ul><li><p>将进程信息压入堆栈,跳转到中断向量的地址。(这些任务由<u>硬件</u>完成)</p></li><li><p>(跳转到的软件)将堆栈中的信息保存到进程表项中,并删除堆栈中数据。</p></li><li><p>将堆栈指针指向进程处理程序所使用的临时堆栈</p></li><li><p>C语言编写的中断服务程序</p></li><li><p>调用调度程序</p></li><li><p>为当前的进程装入寄存器值以及内存映射。</p></li></ul><p>一种可能的实现,使用信号量(PV操作):</p><p>启动IO时进行P操作,再由中断处理程序进行V操作。</p></li></ul><h3 id="1-2-线程"><a href="#1-2-线程" class="headerlink" title="1.2. 线程"></a>1.2. 线程</h3><p>线程同属于一个用户,因而对不同线程的资源进行保护是没有必要的。</p><h4 id="1-2-1-线程的内容"><a href="#1-2-1-线程的内容" class="headerlink" title="1.2.1. 线程的内容"></a>1.2.1. 线程的内容</h4><table><thead><tr><th>线程共享的进程内容</th><th>每个线程中的内容</th></tr></thead><tbody><tr><td>地址空间</td><td>程序计数器</td></tr><tr><td>全局变量</td><td>寄存器</td></tr><tr><td>打开文件</td><td>堆栈</td></tr><tr><td>子进程</td><td>状态</td></tr><tr><td>即将发生的定时器</td><td></td></tr><tr><td>信号与信号处理程序</td><td></td></tr><tr><td>账户信息</td><td></td></tr></tbody></table><p>每个线程都有自己独立的堆栈,否则函数调用过程会出现混乱。</p><h4 id="1-2-2-POSIX线程"><a href="#1-2-2-POSIX线程" class="headerlink" title="1.2.2. POSIX线程"></a>1.2.2. POSIX线程</h4><p>该标准定义的线程包叫<strong>pthread</strong>,大部分UNIX系统均支持该标准</p><p>注意线程资源也需要回收,调用join函数会等待返回值并将该线程回收,或者调用detach使得线程分离,不会取得返回值但自动回收。</p><p>一个例子如下</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><code class="hljs C"><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string"><pthread.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string"><stdio.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string"><stdlib.h></span></span><br><br><span class="hljs-keyword">typedef</span> <span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">thread_param</span>{</span><br> <span class="hljs-type">int</span> param1;<br> <span class="hljs-type">int</span> param2;<br>}Param;<br><br><span class="hljs-type">void</span> * <span class="hljs-title function_">thread_func</span><span class="hljs-params">(<span class="hljs-type">void</span> * arg)</span>{<br> Param param = *(Param *)arg;<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Hello from thread\n"</span>);<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Get param: param1:%d\tparam2:%d\n"</span>, param.param1, param.param2);<br> pthread_exit(<span class="hljs-literal">NULL</span>);<br>}<br><br><span class="hljs-type">int</span> <span class="hljs-title function_">main</span><span class="hljs-params">()</span>{<br> <span class="hljs-type">pthread_t</span> tid;<br> Param param;<br> param.param1 = <span class="hljs-number">1</span>;<br> param.param2 = <span class="hljs-number">2</span>;<br> <span class="hljs-keyword">if</span>(pthread_create(&tid, <span class="hljs-literal">NULL</span>, thread_func, (<span class="hljs-type">void</span> *)&param) != <span class="hljs-number">0</span>){<br> perror(<span class="hljs-string">"pthread_creat"</span>);<br> <span class="hljs-built_in">exit</span>(<span class="hljs-number">-1</span>);<br> }<br> <span class="hljs-built_in">exit</span>(<span class="hljs-literal">NULL</span>);<br>}<br></code></pre></td></tr></table></figure><h4 id="1-2-3-线程的实现"><a href="#1-2-3-线程的实现" class="headerlink" title="1.2.3. 线程的实现"></a>1.2.3. 线程的实现</h4><ul><li><p>在用户空间实现</p><ul><li><p>从内核角度:</p><p>单线程进程</p><p>在用户空间:</p><p>存在一个运行时系统,运行时系统管理着线程表,线程在运行时系统的上层运行</p></li><li><p>优点</p><ul><li>线程调度较为快捷,因为无需陷入内核</li><li>允许每个进程有自己定制的调度算法</li><li>具有较好的扩展性。否则内核空间维护线程信息,在线程数较大时会出现问题</li></ul></li><li><p>缺点</p><ul><li><p>如何实现阻塞系统调用。阻塞系统调用会阻塞进程,即全部线程。</p><p>一种可能的替代方案:</p><p>select系统调用可以允许调用者预知是否会引起阻塞。在系统周围从事检查的这类代码被称为<strong>包装器</strong>。但这个做法效率并不高。(大部分使用多线程的原因是经常会发生线程阻塞)</p></li><li><p>类似于阻塞的问题:缺页中断</p></li><li><p>线程必须主动放弃(yield),否则其他线程会无法运行。</p><p>因为在进程内部并没有时钟中断。一种方案是让运行时系统每秒请求一次时钟信号,但这样并不高效。</p></li></ul></li></ul></li><li><p>在内核中实现</p><ul><li><p>相关实现</p><ul><li><p>内核中有用于记录系统中全部线程信息的线程表。</p></li><li><p>所有能够阻塞线程的调用都以系统调用的形式实现。当线程被阻塞时,根据内核调度器选择其他线程</p></li><li><p>由于内核中创建或撤销线程的开销较大,某些系统采用的”环保”处理方式:</p><p>当线程被撤销时,将其标志为不可运行,但其内核数据结构并没有受到影响。随后在必须创建一个新的线程时,就重启某个旧线程,从而节省了一些开销。</p></li></ul></li><li><p>优点</p><ul><li>不需要新的、非阻塞的系统调用</li></ul></li><li><p>缺点</p><ul><li><p>开销较大</p></li><li><p>带来新的问题,如:</p><ul><li><p>多线程的进程进行fork时,应当创建一个还是多个线程?</p><p>若调用exec启用新程序,可能单个线程更好。但若想要继续运行,则原来的线程更好。</p></li><li><p>信号到达时交由谁处理?</p><p>传统的模型交由进程处理,但现在一个进程包含多个线程。可以让每个线程注册他们感兴趣的信号,但当多个线程注册同一个信号时应当如何处理?</p></li></ul></li></ul></li></ul></li><li><p>混合实现</p><ul><li><p>一种方法是,使用内核级线程,然后将用户级线程与某些或者全部的内核线程多路复用起来。</p><p>这种模型带来较大的灵活度,编程人员可以决定有多少个内核级线程和用户级线程彼此多路复用。</p></li></ul></li><li><p>调度程序激活机制</p><ul><li><p>实现</p><ul><li><p>内核给每个进程安排一定数量的虚拟处理器,并且让运行时系统将线程分配到处理器上,初始为一个。进程可以申请或退回处理器,内核也可以取回。</p></li><li><p>当内核了解到一个线程被阻塞了之后,内核(通过一个已知的起始地址)通知进程的运行时系统,并在堆栈中以参数的形式传递有问题的线程编号和所发生事件的一个描述。这个机制被称为<strong>上行调用</strong></p><p>一旦如此激活,运行时系统就重新调度其线程。稍后,当内核了解到原来的线程又可以运行,则再次上行调用通知运行时系统,该系统按照自己的判断继续运行或将其加入就绪表中。</p></li><li><p>当某个用户线程发生中断时,被中断的CPU切换进内核态。</p><p>若被中断的进程对引起该中断的事件不感兴趣,则在中断处理程序结束后,将被中断的线程恢复到原状态。</p><p>若被中断的进程对中断感兴趣,那么被中断的<u>线程</u>就不再启动,代之为挂起的被中断的<u>线程</u>。而运行时系统则启动对应的<u>虚拟CPU</u>,此时被中断的线程保存在<u>堆栈</u>(而非线程表,线程表是运行时系统维护的)中。随后运行时系统决定启动哪个线程。</p></li></ul></li></ul></li></ul><h4 id="1-2-4-弹出式线程"><a href="#1-2-4-弹出式线程" class="headerlink" title="1.2.4. 弹出式线程"></a>1.2.4. 弹出式线程</h4><p>在分布式系统中经常使用线程。考虑处理消息到来的情况:</p><p>传统的方法是将进程或线程阻塞在receive调用上,不过也可以这样处理:一个消息的到达导致系统创建一个处理该消息的线程,这种线程称为弹出式线程。这种线程没有历史,因而可以快速的创建,消息到达与开始处理之间的时间非常短。</p><p>(如果支持在内核上下文中运行),在内核空间运行弹出式线程会比在用户空间更加便利(访问所有表格和IO设备)。但其在内核空间中出错的线程会带来更大损害(如无法抢占,运行时间过长从而导致信息丢失)</p><h3 id="1-3-进程间通信"><a href="#1-3-进程间通信" class="headerlink" title="1.3. 进程间通信"></a>1.3. 进程间通信</h3><p>进程间通信主要有三个问题</p><ul><li>如何传递消息</li><li>如何确保进程在关键活动上不会出现交叉</li><li>进程间正确的执行顺序(如A等待B的执行结果)</li></ul><p>对于线程来说也是类似的,除了第一点由于共享地址空间可以较好解决。</p><p>对于一个好的对竞争条件的解决方案需要满足:</p><ul><li>任何两个进程不能同时处于临界区</li><li>不应对CPU的速度和数量做任何假设</li><li>临界区外的进程不能阻塞其他进程</li><li>不能使进程无限期等待进入临界区</li></ul><h4 id="1-3-1-忙等待的互斥"><a href="#1-3-1-忙等待的互斥" class="headerlink" title="1.3.1. 忙等待的互斥"></a>1.3.1. 忙等待的互斥</h4><p>连续检查某一变量的方案称为忙等待,用于忙等待的锁称为<strong>自旋锁</strong>。它适用于等待时间较短的情况。</p><p>值得注意的问题:若有两条不同优先级的进程,高优先级的进程等待低优先级进程的自旋锁,会导致高优先级永远等待下去,这种情况叫做优先级反转。</p><p>几种实现忙等待的方法:</p><ul><li><p>屏蔽中断</p><p>在进入临界区时可以屏蔽所有中断(包括时钟中断),但这种权力放在用户空间并不好。</p></li><li><p>严格轮换法</p><p>两个进程轮流进入临界区。</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs C"><span class="hljs-keyword">while</span>(<span class="hljs-literal">true</span>){<br><span class="hljs-keyword">while</span>(turn != <span class="hljs-number">0</span>);<br>critical_region();\\临界区<br>turn = <span class="hljs-number">1</span>;<br>noncritical_region();<br>}<br><br><span class="hljs-keyword">while</span>(<span class="hljs-literal">true</span>){<br><span class="hljs-keyword">while</span>(turn != <span class="hljs-number">1</span>);<br>critical_region();<br>turn = <span class="hljs-number">0</span>;<br>noncritical_region();<br>}<br></code></pre></td></tr></table></figure><p>这种方案在某一个进程快很多时,也不得不等待另一个进程,即便他们都不在临界区。</p></li><li><p>Peterson解法</p><figure class="highlight arduino"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs arduino"><span class="hljs-comment">/* 假定有两个线程0,1*/</span><br><span class="hljs-type">int</span> turn;<span class="hljs-comment">// 现在轮到谁等待</span><br><span class="hljs-type">int</span> interested[<span class="hljs-number">2</span>];<span class="hljs-comment">// 谁对临界区感兴趣</span><br><br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">enter_region</span><span class="hljs-params">(<span class="hljs-type">int</span> process)</span></span>{<br><span class="hljs-type">int</span> other = <span class="hljs-number">1</span> - process;<br>interested[process] = <span class="hljs-literal">true</span>;<br>turn = process;<br><span class="hljs-keyword">while</span>(turn == process && interested[other] == <span class="hljs-literal">true</span>);<br>}<br><br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">leave_region</span><span class="hljs-params">(<span class="hljs-type">int</span> process)</span></span>{<br>interested[process] = <span class="hljs-literal">false</span>;<br>}<br></code></pre></td></tr></table></figure><p>这种方案是谦让的解决方案。</p></li><li><p>TSL指令实现</p><p>这种方式需要硬件支持一条指令</p><figure class="highlight cos"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs cos">TSL RX, <span class="hljs-keyword">LOCK</span><span class="hljs-comment">;测试并加锁</span><br></code></pre></td></tr></table></figure><p>它将内存字LOCK读入寄存器RX中,并向内存中存入一个非零值。</p><p>这个操作是不可分割的,执行该指令的CPU会锁住内存总线</p><figure class="highlight avrasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs avrasm"><span class="hljs-symbol">enter_region:</span><br>TSL REG, LOCK<br>CMPREG, <span class="hljs-meta">#0</span><br>JNE enter_region<br><span class="hljs-keyword">RET</span><br><br><span class="hljs-symbol">leave_region:</span><br>MOVE LOCK, <span class="hljs-meta">#0</span><br></code></pre></td></tr></table></figure><p>一种可替代的指令XCHG,它的作用是交换寄存器和内存的内容,但也是不可分割的。</p></li></ul><h4 id="1-3-2-睡眠与唤醒"><a href="#1-3-2-睡眠与唤醒" class="headerlink" title="1.3.2. 睡眠与唤醒"></a>1.3.2. 睡眠与唤醒</h4><ul><li><p>信号量</p><p>PV操作。P减一,为0则阻塞。V增一,若有进程因为P休眠则唤醒。</p><p>通常将其作为系统调用使用。为保证其不可分割,操作系统需要在执行下列操作时屏蔽中断:测试信号量(P操作),更新信号量以及在需要时使某个进程休眠。如果有多个CPU,则每个信号量应当由一个锁变量(TSL或XCHG实现)来保护(因为多个CPU时,屏蔽中断并不能阻止其他CPU访问内存)。此时自旋锁的等待代价是可以接受的。</p><p>生产者消费者的例子:</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><code class="hljs C"><span class="hljs-meta">#<span class="hljs-keyword">define</span> N 100</span><br><span class="hljs-keyword">typedef</span> <span class="hljs-type">int</span> semaphore;<span class="hljs-comment">// 信号量是一种特殊的整型数据</span><br>semaphore mutex = <span class="hljs-number">1</span>;<br>semaphore empty = N;<br>semaphore full = <span class="hljs-number">0</span>;<br><br><span class="hljs-type">void</span> <span class="hljs-title function_">producter</span><span class="hljs-params">(<span class="hljs-type">void</span>)</span>{<br> <span class="hljs-type">int</span> item;<br> <span class="hljs-keyword">while</span>(<span class="hljs-literal">true</span>){<br> item = produce_item();<br> P(&empty);<br> P(&mutex);<br> insert_item(item);<br> V(&mutex);<br> V(&full);<br> }<br>}<br><br><span class="hljs-type">void</span> <span class="hljs-title function_">consumer</span><span class="hljs-params">(<span class="hljs-type">void</span>)</span>{<br> <span class="hljs-type">int</span> item;<br> <span class="hljs-keyword">while</span>(<span class="hljs-literal">true</span>){<br> P(&full);<br> P(&mutex);<br> item = remove_item();<br> V(&mutex);<br> V(&empty);<br> consume_item(item);<br> }<br>}<br></code></pre></td></tr></table></figure></li><li><p>互斥量(mutex)</p><p>信号量的简化版本,不需要信号量的计数能力。</p><p>但在线程会与在进程的情形会有一些不同,考察如下的实现。</p><figure class="highlight avrasm"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs avrasm"><span class="hljs-symbol">mutex_lock:</span><br>TSL REG, MUTEX<br>CMP REG, <span class="hljs-meta">#0</span><br>JZE ok<br><span class="hljs-keyword">CALL</span> thread_yield<br><span class="hljs-keyword">JMP</span> mutex_look<br><span class="hljs-symbol">ok:</span><br><span class="hljs-keyword">RET</span><br><br><span class="hljs-symbol">mutex_unlock:</span><br><span class="hljs-keyword">MOV</span> MUTEX, <span class="hljs-meta">#0</span><br><span class="hljs-keyword">RET</span><br></code></pre></td></tr></table></figure><p>上面的代码中必须要调用thread_yield,否则由于线程没有时钟中断会一直运行下去。</p><p>一些线程的互斥量实现:</p><ul><li><p>快速用户区互斥量futex</p><p>主要是线程,因为进程切换一定需要陷入内核。</p><p>futex是Linux的一个特性,它实现了基本的锁(很像互斥锁),且尽量避免陷入内核。</p><p>futex包含两部分:一个内核服务和一个用户库。</p><ul><li>内核服务提供一个等待队列(由于在内核,需要系统调用,将线程放在等待队列代价很大)</li><li>用户空间提供进程共享的通用锁变量(32bit整数锁)</li></ul><p>其获取锁逻辑如下</p><ul><li><p>线程执行原子操作减少并检查来夺取锁</p></li><li><p>没有竞争时,futex完全在用户态工作</p><p>在有竞争时,调用系统调用将等待的线程放在等待队列上。</p></li><li><p>当另一线程通过原子操作增加并检验释放锁。如果有阻塞的线程才陷入内核,没有竞争时不会陷入内核。</p></li></ul></li><li><p>pthread中的互斥量</p><p>这些锁需要初始化和销毁,见下面的例子。</p><ul><li><p>使用可以被锁定和解锁的互斥量保护临界区</p><p>进程进入时若互斥量未被加锁,则可以立即进入,同时互斥量会被锁住。</p><p>进程进入时互斥量已被锁定,则会阻塞调用线程直至其解锁。</p><p>该锁被解锁时,允许一个等待线程运行并将互斥量重新锁定</p></li><li><p>除此外,pthread提供了另一种同步机制:条件变量</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs C"><span class="hljs-comment">/* 等待cond上的唤醒(后面两个函数),进入函数时释放mutex,返回时重新获取mutex */</span><br><span class="hljs-type">int</span> <span class="hljs-title function_">pthread_cond_wait</span><span class="hljs-params">(<span class="hljs-type">pthread_cond_t</span> *cond, <span class="hljs-type">pthread_mutex_t</span> *mutex)</span>;<br><br><span class="hljs-comment">/**</span><br><span class="hljs-comment">唤醒在cond上等待的线程</span><br><span class="hljs-comment">signal唤醒一个,broadcast全部唤醒重新竞争</span><br><span class="hljs-comment">*/</span><br><span class="hljs-type">int</span> <span class="hljs-title function_">pthread_cond_signal</span><span class="hljs-params">(<span class="hljs-type">pthread_cond_t</span> *cond)</span>; <br><span class="hljs-type">int</span> <span class="hljs-title function_">pthread_cond_broadcast</span><span class="hljs-params">(<span class="hljs-type">pthread_cond_t</span> *cond)</span>;<br></code></pre></td></tr></table></figure></li></ul><p>一个生产者消费者例子</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><code class="hljs C"><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string"><stdio.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string"><pthread.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> MAX 100</span><br><br><span class="hljs-type">pthread_mutex_t</span> mutex;<br><span class="hljs-type">pthread_cond_t</span> condc, condp;<br><span class="hljs-type">int</span> buffer = <span class="hljs-number">0</span>;<br><br><span class="hljs-type">void</span> *<span class="hljs-title function_">producter</span><span class="hljs-params">(<span class="hljs-type">void</span> *ptr)</span>{<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i=<span class="hljs-number">1</span>; i<=MAX; i++){<br> pthread_mutex_lock(&mutex);<br> <span class="hljs-keyword">while</span>(buffer != <span class="hljs-number">0</span>){<span class="hljs-comment">// 这里的buffer避免了条件变量丢失的情况</span><br> pthread_cond_wait(&condp, &mutex);<br> }<br> buffer = i;<br> pthread_cond_signal(&condc);<br> pthread_mutex_unlock(&mutex);<br> }<br> pthread_exit(<span class="hljs-number">0</span>);<br>}<br><br><span class="hljs-type">void</span> *<span class="hljs-title function_">consumer</span><span class="hljs-params">(<span class="hljs-type">void</span> *ptr)</span>{<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i=<span class="hljs-number">1</span>; i<=MAX; i++){<br> pthread_mutex_lock(&mutex);<br> <span class="hljs-keyword">while</span>(buffer == <span class="hljs-number">0</span>){<br> pthread_cond_wait(&condc, &mutex);<br> }<br> buffer = <span class="hljs-number">0</span>;<br> pthread_cond_signal(&condp);<br> pthread_mutex_unlock(&mutex);<br> }<br> pthread_exit(<span class="hljs-number">0</span>);<br>}<br><br><span class="hljs-type">int</span> <span class="hljs-title function_">main</span><span class="hljs-params">(<span class="hljs-type">int</span> argc, <span class="hljs-type">char</span> ** argv)</span>{<br> <span class="hljs-type">pthread_t</span> pro, con;<br> pthread_mutex_init(&mutex, <span class="hljs-number">0</span>);<br> pthread_cond_init(&condc, <span class="hljs-number">0</span>);<br> pthread_cond_init(&condp, <span class="hljs-number">0</span>);<br> pthread_create(&con, <span class="hljs-number">0</span>, consumer, <span class="hljs-number">0</span>);<br> pthread_create(&pro, <span class="hljs-number">0</span>, producter, <span class="hljs-number">0</span>);<br> pthread_join(pro, <span class="hljs-number">0</span>);<br> pthread_join(con, <span class="hljs-number">0</span>);<br> pthread_cond_destroy(&condc);<br> pthread_cond_destroy(&condp);<br> pthread_mutex_destroy(&mutex);<br>}<br></code></pre></td></tr></table></figure></li></ul></li></ul><h4 id="1-3-3-共享数据"><a href="#1-3-3-共享数据" class="headerlink" title="1.3.3. 共享数据"></a>1.3.3. 共享数据</h4><p>该问题在线程是较容易实现的,故仅仅讨论进程如何共享某些变量。</p><ul><li>共享数据结构,比如信号量,且只能通过系统调用来访问。</li><li>多数现代系统(如UNIX和Windows)让进程与其他进程共享部分地址空间,或使用共享文件。</li></ul><h4 id="1-3-4-管程"><a href="#1-3-4-管程" class="headerlink" title="1.3.4. 管程"></a>1.3.4. 管程</h4><p>管程是一个语言概念,C语言并不支持管程。任意时刻管程中只能有一个活跃的进程。</p><p>进入管程的互斥由编译器负责。当一个调用一个管程的过程时,过程的前几句会检查管程内是否有一个活跃的进程,通常的做法是用一个互斥量或二元信号量。</p><p>同时需要一种方法使得进程在无法继续运行时阻塞,解决的方法是引入条件变量。为了避免管程中同时有两个活跃进程,我们需要指定一条规则说明在signal后应该怎么办,两种方法如下:</p><ul><li>Hoare建议让新唤醒的进程运行而挂起另一个进程</li><li>Brinch Hansen建议执行signal的进程立刻退出管程,这意味着将signal语句作为管程过程的最后一条语句。</li><li>让发信号者继续运行直至退出管程</li></ul><p>但需要注意,条件变量并不能累积起来使用。如果向一个变量发送信号但没有等待进程,该信号会永远丢失。但是该问题可以通过设置变量很好的解决(如上面例子之中的buffer)。</p><figure class="highlight oxygene"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><code class="hljs oxygene">monitor ProducerConsumer<br>condition full, <span class="hljs-keyword">empty</span><span class="hljs-punctuation">;</span><br>integer count<span class="hljs-punctuation">;</span><br><br><span class="hljs-keyword">procedure</span> <span class="hljs-title function_">insert</span><span class="hljs-params">(item: integer)</span>;<br><span class="hljs-keyword">begin</span><br><span class="hljs-keyword">if</span> count = N <span class="hljs-keyword">then</span> wait(full)<span class="hljs-punctuation">;</span><br>insert_item(item)<span class="hljs-punctuation">;</span><br>count := count + <span class="hljs-number">1</span><span class="hljs-punctuation">;</span><br><span class="hljs-keyword">if</span> count = <span class="hljs-number">1</span> <span class="hljs-keyword">then</span> signal(<span class="hljs-keyword">empty</span>)<span class="hljs-punctuation">;</span><br><span class="hljs-keyword">end</span><span class="hljs-punctuation">;</span><br><span class="hljs-keyword">function</span> <span class="hljs-title function_">remove</span>: integer<span class="hljs-punctuation">;</span><br><span class="hljs-keyword">begin</span><br><span class="hljs-keyword">if</span> count = <span class="hljs-number">0</span> <span class="hljs-keyword">then</span> wait(<span class="hljs-keyword">empty</span>)<span class="hljs-punctuation">;</span><br><span class="hljs-keyword">remove</span> = remove_item<span class="hljs-punctuation">;</span><br>count := count - <span class="hljs-number">1</span><span class="hljs-punctuation">;</span><br><span class="hljs-keyword">if</span> count = N - <span class="hljs-number">1</span> <span class="hljs-keyword">then</span> signal(full)<br><span class="hljs-keyword">end</span><span class="hljs-punctuation">;</span><br><br>count := <span class="hljs-number">0</span><span class="hljs-punctuation">;</span><br><span class="hljs-keyword">end</span> monitor<span class="hljs-punctuation">;</span><br><br><span class="hljs-keyword">procedure</span> <span class="hljs-title function_">producer</span>;<br><span class="hljs-keyword">begin</span> <br><span class="hljs-keyword">while</span> <span class="hljs-keyword">true</span> <span class="hljs-keyword">do</span><br><span class="hljs-keyword">begin</span><br>item = produce_item<span class="hljs-punctuation">;</span><br>ProducerConsumer.insert(item)<br><span class="hljs-keyword">end</span><br><span class="hljs-keyword">end</span><span class="hljs-punctuation">;</span><br><br><span class="hljs-keyword">procedure</span> <span class="hljs-title function_">consumer</span>;<br><span class="hljs-keyword">while</span> <span class="hljs-keyword">true</span> <span class="hljs-keyword">do</span><br><span class="hljs-keyword">begin</span><br>item = ProducerConsumer.remove<span class="hljs-punctuation">;</span><br>consume_item(item)<span class="hljs-punctuation">;</span><br><span class="hljs-keyword">end</span><br><span class="hljs-keyword">end</span><span class="hljs-punctuation">;</span><br></code></pre></td></tr></table></figure><p>这里之所以用wait和signal而非sleep与wakeup是可能出现在一个进程想睡眠时去唤醒他。在管程中则无需担心wait完成前切换到消费者。</p><p>Java能够支持管程,使用synchronized关键字,但Java与其他经典管程有本质差别,它并没有条件变量,反之,提供了wait和notify,分别与sleep和wakeup等价。</p><h4 id="1-3-5-消息传递"><a href="#1-3-5-消息传递" class="headerlink" title="1.3.5. 消息传递"></a>1.3.5. 消息传递</h4><p>有的时候,使用信号量太过低级,但管程又是一个语言概念。并且这些原语都为提供机器间信息交换的方法。我们可以设计两条系统调用send和receive(如send(destination, &message)和receive(source, &message)),前者发送消息,后者接受某个或任意源的消息,接受不到则阻塞。</p><ul><li><p>特别对于网络的情况,消息可能被丢失。因而可以达成如下一致:接收到消息后回发确认消息,若发送方未接收到确认,则重发。</p><p>需要考虑消息被正确接受但确认消息丢失,这样接收者将得到两个完全一致的消息,需要解决区分的问题。通常采用在原始信息中嵌入一个连续的序列号。</p></li><li><p>消息还需要考虑如何确定发送者和接受者,以及身份认证的问题。</p></li></ul><p>下面是使用消息来实现生产者消费者的例子</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><code class="hljs C"><span class="hljs-meta">#<span class="hljs-keyword">define</span> N 100</span><br><br><span class="hljs-type">void</span> <span class="hljs-title function_">producer</span><span class="hljs-params">(<span class="hljs-type">void</span>)</span>{<br> <span class="hljs-type">int</span> item;<br> message m;<br> <span class="hljs-keyword">while</span>(<span class="hljs-literal">true</span>){<br> item = produce_item();<br> receive(consumer, &m);<span class="hljs-comment">// 考虑如何编址(见下文)</span><br> build_message(&m, item);<br> send(consumer, &m);<br> }<br>}<br><br><span class="hljs-type">void</span> <span class="hljs-title function_">consumer</span><span class="hljs-params">(<span class="hljs-type">void</span>)</span>{<br> <span class="hljs-type">int</span> item;<br> message m;<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i=<span class="hljs-number">0</span>; i<N; i++){<span class="hljs-comment">// 初始化N个消息</span><br> send(producer, &m);<br> }<br> <span class="hljs-keyword">while</span>(<span class="hljs-literal">true</span>){<br> receive(producer, &m);<br> item = extract_item(&m);<br> send(producer, &m);<br> consume_item(item);<br> }<br>}<br></code></pre></td></tr></table></figure><p>可以看到上面的例子之中需要考虑如何对消息进行编址</p><ul><li>为每一个进程分配一个唯一的地址</li><li>引入一种新的数据结构,信箱,用于缓冲一定量的消息。此时send和receive使用的是信箱的地址。</li></ul><p>当(信箱)极端的,彻底取消缓冲。send在receive之前则send阻塞,receive在send之前,receive阻塞,则称为会合。</p><h4 id="1-3-6-屏障"><a href="#1-3-6-屏障" class="headerlink" title="1.3.6.屏障"></a>1.3.6.屏障</h4><p>对于一组进程而言,需要在某个阶段结尾使其达到同步,则在此安置屏障。</p><p>如实现某大矩阵乘法需将其并行计算迭代时。</p><h4 id="1-3-7-读-复制-更新"><a href="#1-3-7-读-复制-更新" class="headerlink" title="1.3.7. 读-复制-更新"></a>1.3.7. 读-复制-更新</h4><p>为了避免锁,使某个进程读的全部为旧值或全部为新值。如下例</p><p>新增节点</p><p><img src="https://cdn.jsdelivr.net/gh/tsdsnk/imgs@main/img/QQ%E5%9B%BE%E7%89%8720230107212343.png"></p><p>删除节点(当对A,B没有更多读操作时才可以删除)</p><p><img src="https://cdn.jsdelivr.net/gh/tsdsnk/imgs@main/img/QQ%E5%9B%BE%E7%89%8720230107213045.png"></p><p>但是多长时间所有读操作才会读完这些节点,可以规定一个最大引用(该树)时间。如果在读端临界区规定不能够阻塞或休眠,则只需等待所有读操作完成一次上下文切换即可。</p><h3 id="1-4-调度"><a href="#1-4-调度" class="headerlink" title="1.4. 调度"></a>1.4. 调度</h3><p>$$<br>\begin{aligned}<br>& T_{周转时间} = T_{完成时间} - T_{到达时间} \<br>& T_{响应时间} = T_{开始时间} - T_{到达时间}<br>\end{aligned}<br>$$</p><h4 id="1-4-1-批处理系统"><a href="#1-4-1-批处理系统" class="headerlink" title="1.4.1. 批处理系统"></a>1.4.1. 批处理系统</h4><ul><li><p>先来先服务</p><ul><li>易于理解以及应用</li><li>不能协调计算密集型和I/O密集型</li></ul></li><li><p>最短作业优先(非抢占)</p><p>此方法一般需要预知作业时间。在大型批处理系统中,如保险公司处理索赔的一批作业,由于每天都在做类似工作因而可以精确预测。</p><p>此方法可使得平均周转时间最短,如时间为$a,b,c,d$的四个作业,平均周转时间为$\frac{1}{4}(4a+3b+2c+d)$</p></li><li><p>最短剩余作业优先(抢占式)</p><p>仍需要预知时间</p></li></ul><h4 id="1-4-2-交互式系统"><a href="#1-4-2-交互式系统" class="headerlink" title="1.4.2. 交互式系统"></a>1.4.2. 交互式系统</h4><ul><li><p>轮转调度</p><p>核心为时间片的长短,平衡切换代价及响应时间</p></li><li><p>优先级调度</p><ul><li><p>为了防止高优先级无休止运行</p><ul><li>可以在每次时钟中断之后降低优先级</li><li>可以为每个进程赋予一个允许运行的最大时间片,用完这个时间片则允许次高优先级</li></ul></li><li><p>优先级也可以由系统动态确定</p><p>如为了尽可能使I/O密集型提前工作,当这样的进程需要CPU时应立即分给他CPU。一种算法是,将每个进程赋予优先级$\frac{1}{f}$,$f$是该进程在上一次时间片中所占的部分。</p></li></ul></li><li><p>多级队列</p><p>早期内存只能存放一个进程,出现进程切换速度较慢的情况。</p><p>此时为CPU密集型进程分配长时间片比分配短时间片效率较高,但长时间片又会影响到响应时间,因而提出了如下的解决办法:</p><p>为高优先级分配1个时间片,次高分配2个,4个,以此类推(由于I/O密集型具有较高的优先级)。当进程用完则被分到下一优先级。对于一些开始时运行较长时间而后需要交互的进程,为了防止其一直处于被惩罚的状态,可以在终端上每次按下回车键时将其转移到最高优先级。</p></li><li><p>最短进程优先</p><p>仍然需要预知时间。</p><p>一种办法是根据过去行为推测。记当前估计为$T_i$,测量到其下次运行时间为$t_{i+1}$,则更新估计时间为$\alpha T_i + (1 - \alpha)t_{i+1}$</p></li><li><p>保证算法</p><p>保证每个用户能获得CPU的$\frac{1}{n}$,跟踪自进程创建以来使用的CPU时间,计算其应获得的CPU。运行二者之比最低的进程直至其超过最接近的竞争者</p></li><li><p>彩票调度</p><p>为每个进程分配彩票,调用拥有选中彩票的进程。</p><p>这种调度在有新进程时是反应迅速的。它也可以按比例划分CPU的使用</p></li><li><p>公平分享</p><p>不仅仅考虑进程,而是考虑用户,每个用户有相同的机会,然后才去调度用户所拥有的进程</p></li></ul><h4 id="1-4-3-实时系统"><a href="#1-4-3-实时系统" class="headerlink" title="1.4.3. 实时系统"></a>1.4.3. 实时系统</h4><p>实时系统通常分为硬实时和软实时。前者必须满足绝对的截止时间,而后者可以容忍偶尔错失的截止时间。</p><p>实时系统中的事件可以划分为周期性的和非周期性的。对于周期性事件$i$,以周期$P_i$发生,需要处理时间为$C_i$,则只有满足如下条件时才能处理负载,即这个系统是可调度的:<br>$$<br>\sum_{i=1}^m \frac{C_i}{P_i} \leq 1<br>$$<br>实时系统的调度可以是静态的,也可以是动态的。</p><h4 id="1-4-4-策略和机制"><a href="#1-4-4-策略和机制" class="headerlink" title="1.4.4. 策略和机制"></a>1.4.4. 策略和机制</h4><p>我们可以使得调度策略和调度机制分离,也就是将调度算法以某种形式参数化,而参数让用户进程填写。</p><p>如内核使用优先级调度算法,并提供了可以改变优先级的系统调用。这样尽管父进程本身并不参与调度,但他可以制定调度子进程的策略。</p><h4 id="1-4-5-线程调度"><a href="#1-4-5-线程调度" class="headerlink" title="1.4.5. 线程调度"></a>1.4.5. 线程调度</h4><ul><li><p>用户线程</p><p>用户线程的调度由运行时系统决定,可以选择上述算法的任何一种,但缺乏时钟中断,内核并不知道线程的存在。</p></li><li><p>内核级线程</p><p>对于某个线程被阻塞,对于同等重要的线程,最好倾向于同一进程以减小切换开销。但内核也可以不考虑线程所属的进程</p></li></ul><h3 id="1-5-经典的IPC问题"><a href="#1-5-经典的IPC问题" class="headerlink" title="1.5. 经典的IPC问题"></a>1.5. 经典的IPC问题</h3><h4 id="1-5-1-哲学家就餐问题"><a href="#1-5-1-哲学家就餐问题" class="headerlink" title="1.5.1. 哲学家就餐问题"></a>1.5.1. 哲学家就餐问题</h4><figure class="highlight pf"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><code class="hljs pf"><span class="hljs-comment">#define N5</span><br><span class="hljs-comment">#define LEFT(i+N-1) % N</span><br><span class="hljs-comment">#define RIGHT(i+1) % N</span><br><span class="hljs-comment">#define THINKING0</span><br><span class="hljs-comment">#define HUNGRY1</span><br><span class="hljs-comment">#define EATING2</span><br>typedef int segmaphore;<br>int <span class="hljs-keyword">state</span>[N];<br>semaphore mutex = <span class="hljs-number">1</span>;<br>semaphore s[N];<br><br>void philosopher(int i){<br>while(true){<br>// 哲学家进程<br>}<br>}<br><br>void take_forks(int i){<br>P(&mutex);<br><span class="hljs-keyword">state</span>[i] = HUNGRY;<br>test(i);<br>V(&mutex);<br>P(&s[i]);<br>}<br><br>void put_fork(int i){<br>P(&mutex);<br><span class="hljs-keyword">state</span>[i] = THINKING;<br>test(LEFT);// 检查左右是否可以吃(唤醒)<br>test(RIGHT);<br>V(&mutex);<br>}<br><br>void test(int i){<br>if(<span class="hljs-keyword">state</span>[i] == HUNGRY && <span class="hljs-keyword">state</span>[LEFT] != EATING && <span class="hljs-keyword">state</span>[RIGHT] != EATING){<br><span class="hljs-keyword">state</span>[i] = EATING;<br>V(&s[i]);<br>}<br>}<br></code></pre></td></tr></table></figure><h4 id="1-5-2-读者-写者问题"><a href="#1-5-2-读者-写者问题" class="headerlink" title="1.5.2. 读者-写者问题"></a>1.5.2. 读者-写者问题</h4><p>当写者进入时,其他进程禁止进入。</p><figure class="highlight reasonml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><code class="hljs reasonml">typedef <span class="hljs-built_in">int</span> semaphore;<br>semaphore mutex = <span class="hljs-number">1</span>;<br>semaphore db = <span class="hljs-number">1</span>;<br><span class="hljs-built_in">int</span> rc = <span class="hljs-number">0</span>;<span class="hljs-comment">// 正在读或写的进程数目</span><br>void reader(void){<br><span class="hljs-keyword">while</span>(<span class="hljs-literal">true</span>){<br><span class="hljs-constructor">P(&<span class="hljs-params">mutex</span>)</span>;<br>rc = rc + <span class="hljs-number">1</span>;<br><span class="hljs-keyword">if</span>(rc<span class="hljs-operator"> == </span><span class="hljs-number">1</span>){<br><span class="hljs-constructor">P(&<span class="hljs-params">db</span>)</span>;<br>}<br><span class="hljs-constructor">V(&<span class="hljs-params">mutex</span>)</span>;<br>read<span class="hljs-constructor">_data_base()</span>;<br><span class="hljs-constructor">P(&<span class="hljs-params">mutex</span>)</span>;<br>rc = rc - <span class="hljs-number">1</span>;<br><span class="hljs-keyword">if</span>(rc<span class="hljs-operator"> == </span><span class="hljs-number">0</span>){<br><span class="hljs-constructor">V(&<span class="hljs-params">db</span>)</span>;<br>}<br><span class="hljs-constructor">V(&<span class="hljs-params">mutex</span>)</span>;<br>use<span class="hljs-constructor">_data_read()</span>;<br>}<br>}<br><br>void writer(void){<br><span class="hljs-keyword">while</span>(<span class="hljs-literal">true</span>){<br>think<span class="hljs-constructor">_up_data()</span>;<br><span class="hljs-constructor">P(&<span class="hljs-params">db</span>)</span>;<span class="hljs-comment">// 这里不需要mutex是因为reader中rc==1会P(&db)</span><br>write<span class="hljs-constructor">_data_base()</span>;<br><span class="hljs-constructor">V(&<span class="hljs-params">db</span>)</span>;<br>}<br>}<br></code></pre></td></tr></table></figure><h2 id="2-内存管理"><a href="#2-内存管理" class="headerlink" title="2. 内存管理"></a>2. 内存管理</h2><h3 id="2-1-无存储器抽象"><a href="#2-1-无存储器抽象" class="headerlink" title="2.1. 无存储器抽象"></a>2.1. 无存储器抽象</h3><p>即使没有存储器抽象,同时运行多个程序也是可能的,比如交换技术。除此之外,在特殊的硬件帮助下,还可以采用以下技术:</p><p>(早期的IBM 360)内存被划分为2KB的块,每块分配一个4位的保护键,只有操作系统有权修改。PSW (Program Status Word,程序状态字) 中存有4位码。当运行中的进程访问与其PSW不同的内存时,硬件会捕获这一事件。</p><p>然而,仍然需要解决使用绝对地址的问题。IBM 360使用<strong>静态重定位</strong>技术修改它,即在地址上加一常数,但它会减慢装载速度。</p><h3 id="2-2-地址空间"><a href="#2-2-地址空间" class="headerlink" title="2.2. 地址空间"></a>2.2. 地址空间</h3><p>地址空间是一个进程可用于寻址内存的一套地址的集合。每个进程有一个独立的地址空间(除了特殊情况下需要共享)。</p><h4 id="2-2-1-基址寄存器与界限寄存器"><a href="#2-2-1-基址寄存器与界限寄存器" class="headerlink" title="2.2.1. 基址寄存器与界限寄存器"></a>2.2.1. 基址寄存器与界限寄存器</h4><p>使用<strong>动态重定位</strong>技术,将程序的起始物理地址加载到基址寄存器中,程序的长度加载到界限寄存器中。每次访问内存会自动加上基址值,同时检查是否大于等于界限寄存器中的值。</p><p>这样的方法需要加法电路,会由于进位传递时间的问题,在没有特殊电路时显得较慢。</p><h4 id="2-2-2-交换技术"><a href="#2-2-2-交换技术" class="headerlink" title="2.2.2. 交换技术"></a>2.2.2. 交换技术</h4><p>如果进程的数据段可以增长,需要把增长的进程移动到足够大的存储区,或将相邻的进程交换出去。当大部分进程都需要在运行时增长时,可以在换入或移动进程时为其分配额外的内存,但需要注意,交换时应避免交换未被使用的内存。</p><p>若有两个可增长的段,如数据段和堆栈段,可以使得数据段向上增长而堆栈段向下增长。如果用完,可以移动到更大的存储区,或杀死进程。</p><h4 id="2-2-3-空闲内存管理"><a href="#2-2-3-空闲内存管理" class="headerlink" title="2.2.3. 空闲内存管理"></a>2.2.3. 空闲内存管理</h4><p>当内存需要动态分配时,操作系统需要对其进行管理。</p><ul><li><p>位图</p><p>内存被划分为若干分配单元,对应于位图中的每一位。</p><p>需要搜索连续为0的串,这是耗时的,可能跨越字的边界。</p></li><li><p>链表</p><ul><li><p>可以使用如下的双向列表:</p><ul><li>P(进程) / H(空闲区)</li><li>起始位置</li><li>长度</li></ul><p>也可以将进程和空闲区形成两个链表,这将提高寻找空闲区的四种算法的速度,但会使得内存释放速度减慢。可以按照大小对其排序来提高某些适配算法的速度,(如首次适配,下次适配则无意义)。</p></li><li><p>移出时可能引起节点的合并</p></li><li><p>替换时</p><ul><li><p>首次适配</p><p>从头节点开始搜索满足条件的节点</p></li><li><p>下次适配</p><p>从上次搜索位置继续搜索</p></li><li><p>最佳适配</p><p>搜索整个链表</p></li><li><p>最差适配</p><p>总是分配最大的空闲区(因为最佳适配会产生许多小的空闲区)</p></li></ul><p>还有一种分配算法称为<strong>快速适配</strong>算法,它为常用大小的空闲区维护一个单独的链表。如一个n项的表,每个表项都是一个链表。其第一项指向4KB空闲区链表,第二项指向8KB空闲区链表,第三项指向12KB链表……21KB的空闲区既可以存放在20KB的链表中,也可以放在一个单独的特别的链表中。</p></li></ul></li></ul><h3 id="2-3-虚拟内存"><a href="#2-3-虚拟内存" class="headerlink" title="2.3. 虚拟内存"></a>2.3. 虚拟内存</h3><p>注:这种方法和交换技术都是处理内存超载的方法,放在这级标题只是为了方便</p><p>20世纪60年代常用的解决方法:将程序分为许多个片段,称为<strong>覆盖</strong>。程序开始执行时,将覆盖管理模块装入内存,该管理模块立即装入并运行覆盖0。执行完成后通知管理模块装入覆盖1,可占用覆盖0上方位置(若有可用位置),或占用覆盖0。</p><p>覆盖技术要求<u>程序员</u>必须把一个程序划分为不同的程序段,并规定好它们的执行和覆盖顺序,<u>操作系统</u>根据程序员提供的覆盖结构来完成程序段之间的覆盖。</p><p>程序员划分覆盖时容易出错,进而想将全部工作交由计算机完成,这个技术称为虚拟内存。其基本思想是:每个程序拥有自己的地址空间,这个空间被分割成多个块,每一块被称为一<strong>页</strong>或<strong>页面</strong>。每一页有连续的地址范围。这些页被映射到物理内存,但并不是所有的页都必须在内存中才能运行程序。当程序引用一部分在物理内存中的地址空间时,由硬件立刻执行必要的映射。当程序引用到一段不在物理内存中的地址空间时,由操作系统负责将缺失的部分装入物理内存并重新执行失败的指令。</p><h4 id="2-3-1-分页"><a href="#2-3-1-分页" class="headerlink" title="2.3.1. 分页"></a>2.3.1. 分页</h4><p>大部分虚拟内存系统都采用分页技术。</p><p>由程序产生的地址叫做虚拟地址,他们构成了一个虚拟地址空间。</p><p>使用虚拟内存时,虚拟地址被送到<strong>内存管理单元</strong>(Memory Management Unit, MMU),<u>MMU把虚拟地址映射为物理地址</u>。MMU通常作为CPU芯片的一部分,但它多是独立的芯片。</p><p>RAM和磁盘之间的交换总是以整个页面为单元进行的,页面大小可能会有所不同。处理器根据操作系统认为合适的方式,支持对不同大小的页面的混合使用和匹配。</p><p>当程序访问了未映射的页面,<u>MMU使CPU陷入到内核</u>,这个陷阱叫做<strong>缺页中断</strong>或<strong>缺页错误</strong>,操作系统选择一个页框,并将它的内容写入磁盘,把要访问的页面读入到收回的页框中,修改映射关系(包括放弃的虚拟页面的表项和装入的虚拟页面的表项)</p><h4 id="2-3-2-页表"><a href="#2-3-2-页表" class="headerlink" title="2.3.2. 页表"></a>2.3.2. 页表</h4><p>对单个页表项,其结构与机器密切相关,可以规定其结构如下</p><p><img src="https://cdn.jsdelivr.net/gh/tsdsnk/imgs@main/img/2018040414344052.jpg" alt="一个典型的页表项"></p><ul><li><p>一些位的说明</p><ul><li><p>保护位</p><p>指出页允许什么类型的访问,读、写、执行</p></li><li><p>修改和访问位</p><p>在写入时自动设置修改位(也被称为<strong>脏位</strong>),页面是脏的则需要写回磁盘</p><p>无论读写,在访问时都会设置访问位,便于淘汰不使用的页</p></li><li><p>高速缓存禁止位</p><p>对映射到设备寄存器而非常规内存的特殊页面,主要是对内存I/O映射的机器。</p><p>访问时不经过高速缓存,而是直接访问数据。</p></li></ul></li></ul><h4 id="2-3-3-加速分页过程"><a href="#2-3-3-加速分页过程" class="headerlink" title="2.3.3. 加速分页过程"></a>2.3.3. 加速分页过程</h4><p>在分页系统中主要考虑两个问题</p><ul><li>虚拟地址到物理地址的映射必须非常快</li><li>如果虚拟地址空间很大,页表也会很大</li></ul><hr><p>每次访问内存都需要虚拟地址到物理地址的映射,因此页表查询操作必须较短时间内完成。</p><ul><li>如果将页表存储在<u>寄存器</u>中形成单一页表,启动进程时将保存在<u>内存</u>中的页表副本载入到寄存器中,则进程运行中不必再为页表而访问内存,但缺点是代价高昂,且每次切换上下文必须重新装载</li><li>如果整个页表都存储在内存中,切换进程仅需要切换一个起始地址,但在执行指令时需要多次访问内存</li></ul><p>因此设计了<strong>转换检测缓冲区</strong>(Translation Lookaside Buffer, TLB),也称相联存储器或快表,通常包含在MMU中。</p><p>其包含了少量的表项,通常不超过256个,每个表项记录了一个页面相关的信息。其工作过程如下</p><ul><li><p>硬件将虚拟页号与TLB中所有表项同时(并行)进行匹配</p></li><li><p>发现一个有效的匹配</p><ul><li>违反保护位,产生一个保护错误</li><li>不违反保护位,将页框号直接取出</li></ul><p>页号不在TLB中</p><ul><li>进行正常的页表查询,并在TLB中淘汰一个表项替代之</li></ul></li></ul><hr><p>上述过程中页表替换操作由MMU硬件来实现,但也可以根据软件实现。当TLB大到(如64个表项)可以减少缺失率时,TLB的软件管理就会足够有效。</p><p>在TLB访问失败时,会生成一个TLB失效并将问题交由操作系统解决。系统先找到该页面,然后从TLB中删除一个项,并装载一个新的项,最后在执行先前出错的程序。但上述处理需要在有限几条指令中完成,因为TLB失效更加频繁。</p><p>使用软件进行TLB管理时,需要区分两种不同的TLB失效。</p><ul><li>页面在内存中而不在TLB中,将产生<strong>软失效</strong></li><li>页面不在内存中(当然也不在TLB中),将产生<strong>硬失效</strong></li></ul><p>但实际情况可能更为复杂,如在页表中未找到页(<u>不是TLB访问失败</u>)</p><ul><li><p>所需页面就在内存中,但未映射到进程的页表中。如该页面可能由其他进程从硬盘中调入内存。这是典型的软失效,称为<strong>次要缺页错误</strong>。此时只需要将其加入到进程页表中。</p></li><li><p>需要从硬盘重新调入页面,<strong>严重缺页错误</strong></p></li><li><p>访问了非法地址,系统报告<strong>段错误</strong></p></li></ul><h4 id="2-3-4-针对大内存的页表"><a href="#2-3-4-针对大内存的页表" class="headerlink" title="2.3.4. 针对大内存的页表"></a>2.3.4. 针对大内存的页表</h4><ul><li><p>多级页表</p><p>将虚拟地址划分为若干域。</p><ul><li><p>以32位虚拟地址的多级页表为例:</p><p>MMU首先提取出PT1域并把该值作为访问顶级页表的索引。索引得到的表项中含有二级页表的地址或页框号(<u>页表也是个页</u>),再有PT2域作为访问二级页表的索引,得到物理页框号。</p></li></ul></li></ul>]]></content>
<categories>
<category>考研</category>
</categories>
</entry>
<entry>
<title>About this blog</title>
<link href="/2022/12/18/About-this-blog/"/>
<url>/2022/12/18/About-this-blog/</url>
<content type="html"><![CDATA[<h2 id="hello-world"><a href="#hello-world" class="headerlink" title="hello world"></a>hello world</h2><p>记录下第一次写博客,也是刚刚开始使用markdown</p><h2 id="搭建"><a href="#搭建" class="headerlink" title="搭建"></a>搭建</h2><p>使用<a href="https://hexo.io/zh-cn/">Hexo</a>部署在个人GitHub库中</p><p>使用<a href="https://hexo.fluid-dev.com/">Fluid</a>主题,<a href="https://hexo.fluid-dev.com/docs/start/">参考手册</a></p><p>图片借助<a href="https://picgo.github.io/PicGo-Doc/">PicGo</a>存储在个人GitHub库中</p><h2 id="用途"><a href="#用途" class="headerlink" title="用途"></a>用途</h2><p><del>为了整理知识</del></p><p>为了玩</p>]]></content>
</entry>
</search>