<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>操作系统 on bystander&#39;s blog</title>
    <link>http://blog.leaver.me/tags/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/</link>
    <description>Recent content in 操作系统 on bystander&#39;s blog</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <lastBuildDate>Wed, 22 May 2013 16:16:24 +0000</lastBuildDate>
    <atom:link href="http://blog.leaver.me/tags/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/rss.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>引用和指针(C&#43;&#43;)</title>
      <link>http://blog.leaver.me/2013/05/22/%E5%BC%95%E7%94%A8%E5%92%8C%E6%8C%87%E9%92%88c/</link>
      <pubDate>Wed, 22 May 2013 16:16:24 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/05/22/%E5%BC%95%E7%94%A8%E5%92%8C%E6%8C%87%E9%92%88c/</guid>
      <description>&lt;p&gt;今天在整理收藏夹的时候，又看到了这两篇非常不错的文章，关于指针和引用的，我就不翻译了，文章很简单，不过把其中我觉得很有意思的两部分结合我的理解希望说的更清楚,假定你读这篇文章之前已经知道指针，但是不是很清楚其中的部分。&lt;/p&gt;
&lt;p&gt;首先是关于指针的一个直观的一个认识.&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;#include &amp;lt;iostream&amp;gt;

int main()
{
  using namespace std;

// 声明并初始化指针.
  unsigned short int * pPointer = 0;
// 定义一个unsigned short int 变量 值为35698
  unsigned short int twoInt = 35698;
// 定义一个unsigned short int 变量 值为 77
  unsigned short int oneInt = 77;
// 使用&amp;amp;操作符将twoInt的地址赋给指针
  pPointer = &amp;amp;twoInt;
// pPointer 现在的值就是twoInt的地址了

// 打印
  cout &amp;lt;&amp;lt; &#34;pPointer的内存地址:\t\t&#34; &amp;lt;&amp;lt; &amp;amp;pPointer &amp;lt;&amp;lt; endl;
  cout &amp;lt;&amp;lt; &#34;oneInt的内存地址:\t&#34; &amp;lt;&amp;lt; &amp;amp;oneInt &amp;lt;&amp;lt; &#34;\t整数值:\t&#34; &amp;lt;&amp;lt; oneInt &amp;lt;&amp;lt; endl;
  cout &amp;lt;&amp;lt; &#34;twoInt的内存地址:\t&#34; &amp;lt;&amp;lt; &amp;amp;twoInt &amp;lt;&amp;lt; &#34;\t整数值:\t&#34; &amp;lt;&amp;lt; twoInt &amp;lt;&amp;lt; endl;
  cout &amp;lt;&amp;lt; &#34;pPointer所指向的地址(也就是pPoint的值):\t&#34; &amp;lt;&amp;lt; pPointer &amp;lt;&amp;lt; &#34;\t整数值:\t&#34; &amp;lt;&amp;lt; *pPointer &amp;lt;&amp;lt; endl;

return 0;
}&lt;/pre&gt;
&lt;p&gt;上面这段代码，声明了一个指针，和两个整数，指针指向第一个整数，然后输出结果（每个人的输出结果不一样）是：&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;pPointer的内存地址:                   0xbff43314
oneInt的内存地址:                     0xbff43318       整数值:  77
twoInt的内存地址:                     0xbff4331a       整数值:  35698
pPointer所指向的地址(也就是pPoint的值): 0xbff4331a       整数值:  35698&lt;/pre&gt;
&lt;p&gt;&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/36294_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/ef97273d51f6843eb062463a3091a8edb177b30e.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这张图是这几个变量的内存分布图，上面一排是内存地址编号，正对我们的是该处的值&lt;/p&gt;
&lt;p&gt;指针pPointer这个变量从最左边0xbff43314这个内存位置开始，占用了四个字节，这个一个指针占四个字节，大家都知道的，这个变量的值是一个地址，也就是他的指向地址。&lt;/p&gt;
&lt;p&gt;pPointer 所指向的地址呢，是一个short int 类型的值所在的位置，在这里就是我们的twoint，twoint在内存中呢，是从0xbff4331a开始的，也就是说，我们的pPointer指向了twoint所在的地址，&lt;/p&gt;
&lt;p&gt;注意，看一下左边四个方块前面的二进制数，转换成16进制就是0xbff4331a了&lt;/p&gt;
&lt;p&gt;因此，取指针所指向的值就是35698了。指针本身的值则是0xbff4331a，指针所在的位置是0xbff43314。&lt;/p&gt;
&lt;p&gt;参考文章：&lt;a href=&#34;http://linuxconfig.org/c-understanding-pointers&#34;&gt;C++ : Understanding pointers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;p&gt;另一个呢是关于引用的实现原理&lt;/p&gt;
&lt;p&gt;大家都知道，引用就是别名，比如下面这段代码&lt;/p&gt;
&lt;pre class=&#34;lang:default decode:true&#34;&gt;#include &amp;lt;iostream&amp;gt;
using namespace std;

int main() {
   int number = 88;          // 定义一个int变量
   int &amp;amp; refNumber = number; // 声明并初始化一个引用
                             // 现在他们都表示了同一个值

   cout &amp;lt;&amp;lt; number &amp;lt;&amp;lt; endl;    // 打印number的值 (88)
   cout &amp;lt;&amp;lt; refNumber &amp;lt;&amp;lt; endl; // 打印引用的值 (88)

   refNumber = 99;            // 给refNumber重新赋一个值
   cout &amp;lt;&amp;lt; refNumber &amp;lt;&amp;lt; endl;
   cout &amp;lt;&amp;lt; number &amp;lt;&amp;lt; endl;    // number的值也就变成了 (99)

   number = 55;               // 重新给number赋一个值
   cout &amp;lt;&amp;lt; number &amp;lt;&amp;lt; endl;
   cout &amp;lt;&amp;lt; refNumber &amp;lt;&amp;lt; endl; // refNumber也就变成了(55)
}&lt;/pre&gt;
&lt;p&gt;输出结果肯定一目了然，其中的原理想过没&lt;/p&gt;</description>
    </item>
    <item>
      <title>操作系统的死锁和内存管理</title>
      <link>http://blog.leaver.me/2013/02/02/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E7%9A%84%E6%AD%BB%E9%94%81%E5%92%8C%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86/</link>
      <pubDate>Sat, 02 Feb 2013 06:58:09 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/02/02/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E7%9A%84%E6%AD%BB%E9%94%81%E5%92%8C%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86/</guid>
      <description>&lt;p&gt;这部分是最后一部分笔记。《现代操作系统》第三版的笔记就这样了。
&lt;strong&gt;死锁；&lt;/strong&gt;
把需要排他性使用的对象称为资源，资源分为可抢占的和不可抢占的。可抢占资源可以从拥有它的进程中抢占而不会具有任何副作用。存储器就是可抢占的。不可抢占资源是指在不引起相关的计算失败的情况下，无法把它从占有她的进程处抢占过来。比如CD刻录机，如果一个进程开始刻盘，突然分配给CD刻录机到另一进程，就会划坏CD盘。死锁会发生在不可抢占资源中
&lt;strong&gt;死锁的规范定义&lt;/strong&gt;：如果一个进程集合中的每个进程都在等待只能由该进程集合中的其他进程才能引发的事件，那么，该进程集合就是死锁的。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;死锁的四个必要条件&lt;/strong&gt;
1.互斥条件。每个资源要么已经分配给一个进程，要么就是可用的。
2.占有和等待条件，已经得到了某个资源的进程可以再请求新的资源。
3.不可抢占条件，已经分配给一个进程的资源不可强制性的被抢占，他只能由占有她的进程显式的释放。
4.环路等待条件。死锁发生时，系统中一定有友两个/多个进程组成的一条回路，该环路中的每个进程都在等待着下一个进程所占有的资源。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;死锁处理的四种策略&lt;/strong&gt;
1.忽略该问题，如果可以忽略。则忽略
2.检测死锁并恢复，让死锁发生，检测他们是否发生，一旦发生。采取行动。
3.仔细对资源进行分配。动态的避免死锁。
4.通过破坏引起的四个必要条件之一。防止死锁发生。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;银行家算法&lt;/strong&gt;就是对每个请求进行检查。检查如果满足这一请求是否会达到安全状态，或是，那么满足这请求，若否。就推迟这一请求的满足。为了看状态是否安全。类似于银行家投资。看自己是否有足够的资源满足客户。如果可以。就认为投资是可以收回的。接着检查最接近最大限额的一个客户。如果所有投资最终都被收回。则该状态安全。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;通信死锁&lt;/strong&gt;：两个/以上的进程发送消息通信。A向B发送请求信息，然后阻塞直到B回复。假设请求信息丢失，A将阻塞等待回复。B则阻塞等待一个向其发送命令的请求。则发生死锁。他不能通过对资源排序/安排调度来避免，因此。采用了超时来中断通信死锁。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;活锁&lt;/strong&gt;：两个进程A和B，A获得1.B获得2.轮询请求对方的。没有进程被阻塞。看起来像是死锁发生了。就叫做活锁。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;内存管理&lt;/strong&gt;
每个linux进程都有一个地址空间，逻辑上有三段组成：代码。数据和堆栈段。代码段包含了形成程序可执行代码的机器指令。通常是只读的。是由编译器把源码转换成机器码形成的。
数据段包含了所有程序变量。字符串。数字和其他数据的存储。由两部分，初始化数据和未初始化数据。后者即为BSS，符号起始块。加载后被初始化为0.数据段可以修改。可以增加数据段的大小。
第三段是栈段。大多数机器里。从虚拟地址空间的顶部/附近开始。并且向下生长。&lt;/p&gt;
&lt;p&gt;linux内存由三部分组成。前两部分是内核和内存映射，被钉在内存中。页面从不换粗。内存的其他部分，被划分为页框。每个页框都可以包含一个代码。数据或栈页面。&lt;/p&gt;
&lt;p&gt;window如何知道系统配置的细节呢。答案就是windows会挂载一种特殊的文件系统，其为小文件做了优化，到名字空间，也就是注册表。注册表被阻止成了不同的卷，称作储巢。hive。一个叫做system的储巢会在系统启动时。装入内存。这里面包含了驱动什么设备工作。什么软件要初始化。那些变量等等。&lt;/p&gt;</description>
    </item>
    <item>
      <title>操作系统中的输入输出</title>
      <link>http://blog.leaver.me/2013/02/01/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E4%B8%AD%E7%9A%84%E8%BE%93%E5%85%A5%E8%BE%93%E5%87%BA/</link>
      <pubDate>Fri, 01 Feb 2013 08:43:18 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/02/01/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E4%B8%AD%E7%9A%84%E8%BE%93%E5%85%A5%E8%BE%93%E5%87%BA/</guid>
      <description>&lt;p&gt;&lt;strong&gt;输入输出&lt;/strong&gt;
&lt;strong&gt;I/O硬件：&lt;/strong&gt;
I/O设备分为两类：块设备和字符设备，块设备吧信息存储在固定大小的块中，每个块有自己的地址，传输以块为单位，每个块都能独立于其他块读写，硬盘，CD-ROM和USB盘都是常见的块设备。字符设备是以字符为单位发送和接收一个字符流，而不考虑任何块结构，字符设备不可寻址，也不寻道，打印机，网络几口，鼠标，以及大多数与磁盘不同的设备都可看作是字符设备。&lt;/p&gt;
&lt;p&gt;I/O设备一般由机械部件和电子部件两部分组成，通常分开处理，实现模块化和通用设计，电子部件称作设备控制器/适配器，在个人计算机上，通常以主板上的芯片的形式出现，或者以插入PCI的印刷电路板的形式出现。控制器卡上通常有一个连接器，通向设备本身的电缆可以插入到这个连接器中，
控制器的任务是吧串行的位流转换成字节块，并进行必要的错误校正工作，字节块通常首先在控制器内部的一个缓冲区中按位进行组装，然后再对校验和进行校验并证明字节块没有错误后再将它复制到主存中。&lt;/p&gt;
&lt;p&gt;每个控制器都有几个寄存器用来和cpu通信，通过写入这些寄存器，操作系统可以命令设备发送数据等等操作。
1.内存映射io
将所有控制寄存器映射到内存空间中，每个寄存器被分配一个唯一的内存地址，并且不会有内存被分配这一地址，这样的系统称为内存映射I/O，通常位于地址空间的顶端。使用内存映射io，设备控制器只是内存中的变量，c语言可以和其他变量一样寻址，这样，I/O设备驱动程序就可以采用c语言编写。
2.DMA
无论CPU是否具有内存映射I/O,他都需要寻址设备控制器以便和他们交换数据，但浪费eficpu时间，所以经常使用直接存储器存储。可独立于cpu访问地址总线。&lt;/p&gt;
&lt;p&gt;没有DMA的时候，首先控制器从磁盘驱动器串行的一位一位的读一个块，直到将整块信息放入控制器的内存缓冲区中，接着，他计算校验和，以保证没有读错误发生，然后控制器产生一个中断，当操作系统开始运行时，它重复地从控制器的缓冲区中一次一个字节/一个字的读取该块的信息，并将其放入内存中。
当有DMA的时候，首先CPU通过设置DMA控制器的寄存器对它进行编程，所以DMA控制器知道将什么数据传送到什么地方，(第1步)DMA控制器还要向磁盘控制器发送一个命令，通知他从磁盘读数据到其内部的缓冲区中，并且对校验和进行检验，如果磁盘控制器中的缓冲区中的数据是有效的的。那么DMA开始
DMA控制器通过在总线上发出一个读请求到磁盘控制器而发起DMA传送（第2步），这一读请求和其他一样，并且磁盘控制器并不关心是来自DMA还是CPU，一般情况下，要写的内存地址在总线的地址线上，所以磁盘控制器从内部缓冲区中读取下一个字的时候，她知道要写的什么地方，写到内存是另一个标准总线周期，（第3步）
当写操作完成时，磁盘控制器在总线上发起一个应答信号到DMA（第4步），于是DMA控制器部增要使用的内存地址，并且步减字节计数，如果字节计数仍然大于0，则从父2-4步。完成后产生中断告诉cpu，操作系统开始工作时，数据已经在内存中了。
&lt;strong&gt;中断：&lt;/strong&gt;
将机器留在一个明确状态的中断称为精确中断，四个特征，1.PC保存在一个已知的地方。2.PC所指向的指令之前的所有指令都已经完全执行。3.PC所指向的指令之后的所有指令都没有执行。4.PC所指向的指令的执行状态是已知的。注意，对于PC所指向的指令以后的指令，并没有禁止他们开始执行，而只是要求在中断发生之前必须撤销他们对寄存器或内存所做的任何修改。
&lt;strong&gt;I/O软件：&lt;/strong&gt;
设计I/O软件时一个关键的点就是设备独立性，意思是我们可以访问任意I/O设备而无需事先指定设备。也就是对于不同的I/O硬件。同一段程序是可以的。&lt;/p&gt;
&lt;p&gt;具有标准接口的驱动程序的工作方式如下：对于每一种设备类型，例如磁盘和打印机。操作系统定义一组驱动程序必须支持的函数，对于磁盘而言，这些函数自然的包含读和写，除此之外还包含开启和关闭电源，格式化以及其他与磁盘有关的事情。驱动程序通常包含一张表格，这张表格具有针对这些函数指向驱动程序自身的指针。当驱动程序装载时，操作系统记录下这张函数指针表的地址。所以当操作系统需要调用一个函数时，可以通过表格发出间接调用。这张函数指针表定义了驱动程序与操作系统其他部分之间的接口。&lt;/p&gt;
&lt;p&gt;**双缓冲：**当第二个缓冲区正在复制用户空间的时候，第一个缓冲区用来接收新的字符。以这样的方法。两个缓冲区轮流使用。称为双缓冲。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;磁盘臂调度算法：&lt;/strong&gt;
读/写一个磁盘块需要时间：1.寻道时间（将磁盘臂移动到适当的柱面上所需的时间）2.旋转延迟（等待适当扇区旋转到磁头下所需的时间）。3.实际数据传输时间。&lt;/p&gt;
&lt;p&gt;一个磁盘子系统具有如下特性：当一个写命令发给它时，磁盘要么正确地写数据，要么什么也不做，让现有的数据完整无缺的留下，这样的系统称为稳定存储器，并且是在软件中实现的。目标是不惜一切代价保持磁盘的一致性。&lt;/p&gt;
&lt;p&gt;**时钟：**两种。1种是直接接到电源线上。就可以每个电压周期产生一个终端。现在比较少。另一种是由晶体振荡器，计数器和存储寄存器三个构成。当把一块石英晶体适当的切割并且安装到一定的压力之下时就可以产生非常精确的周期性信号。时钟启动时，存储寄存器的值被复制到计数器中，每一个脉冲使计数器-1，直到为0，产生中断。&lt;/p&gt;</description>
    </item>
    <item>
      <title>操作系统中的文件系统</title>
      <link>http://blog.leaver.me/2013/01/31/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E4%B8%AD%E7%9A%84%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F/</link>
      <pubDate>Thu, 31 Jan 2013 15:00:44 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/01/31/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E4%B8%AD%E7%9A%84%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F/</guid>
      <description>&lt;p&gt;&lt;strong&gt;文件系统&lt;/strong&gt;
进程，地址空间，文件这些抽象概念均是操作系统中的重要概念，如果理解了这三个概念，就迈上了成为一个操作系统专家的道路。
文件系统存放在磁盘上，多数磁盘划分为一个/多个分区，每个分区有一个独立的文件系统，磁盘的0号扇区称为主引导记录，也就是MBR，用来引导计算机，MBR的结尾就是分区表了。该表给出了每个分区的起始和结束地址。表中的一个分区被标记为活动分区。在计算机被引导时，BIOS读入并执行MBR，MBR做的第一件事就是确定活动分区，读入他的第一个块，称为引导块，并执行之，引导块中的程度将装载该分区中的操作系统，为统一起见，每个分区都从一个启动块开始，即使它不含有一个可以启动的操作系统。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/32257_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/2e6edaf72b3ff2b35c5e98e4a1538ae14d74d858.png&#34;&gt;&lt;/a&gt;
&lt;strong&gt;文件的实现：&lt;/strong&gt;
1.连续分配，每个文件作为一连串连续数据存储在磁盘上。实现简单，读操作性能好，一次就可以了。但不足是删除之后不能移动，因为成本太高，使得空块增多。碎片化严重。更诡异的是对于文件编辑软件，实现无法准确预测大小，如果预测错了。。就跪了。
//研究那些具有清晰和简洁概念的老式系统和思想是很重要的，因为他们可能以一种令人吃惊的方式在未来系统中获得应用。&lt;/p&gt;
&lt;p&gt;2.链表分配
为每个文件构造磁盘块链表，一个文件分为N个文件块，N个文件块构成一个链表，存储在物理上的多个地方。顺序读取很方便，但随机读取则相当缓慢，由于指针的存在，每个磁盘块存储数据的字节不再是2的整数次幂，导致系统运行效率降低，因为很多程序都是以2的整数次幂来读写磁盘的。&lt;/p&gt;
&lt;p&gt;3.在内存中采用表的链表分配
去除每个文件块在磁盘上的指针字，放入内存的一个表上，就可以解决上一个分配的不足。直观的例子如图。
文件A使用了磁盘块4，7，2，10，12&lt;/p&gt;
&lt;p&gt;内存中这样的表格称为文件分配表，也就是FAT了。主要缺点是对于大磁盘的小块，这种表需要的内存占用太大。。不太适用。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/32256_o.png&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/b3afb8b5bedaaa50b38292cd6eb90a388d5081d1.png&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;4.i节点
记录各个文件包含哪些磁盘块的方法是给每个文件赋予一个称为i节点的数据结构,其中类除了文件属性和文件块的磁盘地址.相对于在内存中采用表的方式,这种机制的优势在于只有对应文件打开时,其i节点才进入内存.&lt;/p&gt;
&lt;p&gt;文件系统的一致性检查分为两种:块的一致性检查和文件的一致性检查.构造两张表,一张跟踪块在文件中的出现次数,另一张跟踪该块在空闲表中的出现次数,如果一致,则某一块必然在两个表中1/2中为1,如果某一块没有出现在任何一张表中,则称为块丢失,浪费了磁盘空间.解决方法是让文件系统检验程序把他们加入到空闲表中
如果在空闲表中出现了两次.则重新建议建议空闲表即可.
如果在文件表中出现了两次.则比较麻烦.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;文件系统性能&lt;/strong&gt;
1.高速缓存,最常用,指的是一系列的块,逻辑上属于磁盘.但实际上被保存在内存上.基本算法是检查全部的读请求,查看在高速缓存中是否有所需要的块,如果存在,就读,否则读入高速缓存在复制到其他地方.
2.块提前读,在需要用到块之前,试图提前将其写入高速缓存,从而提高命中率.比如某个文件有n个块,则请求k块的时候,则同时预读k+1块.只适用于顺序读取的文件,对随机读取文件,则没有效果/反效果.
3.减少磁盘臂运动
把所有可能顺序读取的块放在一起,当然最好是放在同一个柱面上,从而减少磁盘臂的移动次数.&lt;/p&gt;</description>
    </item>
    <item>
      <title>操作系统中的页面置换算法</title>
      <link>http://blog.leaver.me/2013/01/30/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E4%B8%AD%E7%9A%84%E9%A1%B5%E9%9D%A2%E7%BD%AE%E6%8D%A2%E7%AE%97%E6%B3%95/</link>
      <pubDate>Wed, 30 Jan 2013 09:18:05 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/01/30/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E4%B8%AD%E7%9A%84%E9%A1%B5%E9%9D%A2%E7%BD%AE%E6%8D%A2%E7%AE%97%E6%B3%95/</guid>
      <description>&lt;div&gt;最近读完了《现代操作系统》。页面置换算法的读书笔记。其他的笔记慢慢整理一下在博客做个备份。&lt;/div&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div&gt;虚拟内存的基本思想：每个程序都拥有自己的内存空间，这个空间被分割成很多块，每一块称为一页/页面，每一页有连续的地址范围，这些页被映射到物理内。&lt;/div&gt;
页面置换算法
1.最优页面置换算法，每个页面都可以用在该页面首次被访问前所需要执行的指令数作为标记。因此我们选择标记最大的页面，也就是把不愉快的事情往后拖延。但是，唯一的问题是无法实现。
2.最近未使用页面置换算法。系统每一个页面设置两个状态位，当页面被访问时设置R位，当被修改时设置M位，包含在页表项中，初始时，都被设置0，R被定期地清零，以区别最近没有被访问和被访问的页面。NRU算法随机的从类编号最小的非空类中挑选一个页面淘汰之，
根据R和W可以将页面分为4类
0没有被访问，没有被修改/1没有被访问，被修改/2已被访问，没有被修改/3已被访问，已被修改。第一类只有在定期清R的时候才会出现。
隐含的意思是，淘汰一个没有被访问的已修改页面要比淘汰一个被频繁使用的干净页面要好。
3.先进先出置换，找出最先进入的替换掉，很少单独使用
4.第二次机会页面置换算法。FIFO可能将经常使用的页面置换出来。为此，检查最老页面的r位，如果R为0，则既老又没有被使用，则就置换掉，如果是1，就清0，放在链表尾，修改装入时间为最新。继续搜索。
5.时钟页面置换算法，第二次机会算法经常要在链表中移动页面，更好的方法是将页面保存在一个类似钟面的环形链表中，表针指向最老的页面。发生缺页时，如果R是0就
淘汰该页面，并插入新页面，然后表针前移，如果是1，就清除R并前移，直到找到一个R位为0的页面。这也是时钟的由来
[![](/images/e198f5889716b00f06a452789f0c413474927e87.jpg)](http://leaverimage.b0.upaiyun.com/32235_o.jpg)
6.最近最少使用页面置换算法。在发生缺页时，置换未使用时间最长的页面，这个策略称为LRU，最简单的一个实现策略是有一个64位计数器，每条指令执行完加1.每个页表项必须有一个足够容纳这个计数器值的域，每次访问内存后，将C值保存到被访问页面的页表项，一旦中断，检查所有页面项的计数器值，找到最小的即可。
7.NFU最不常用算法，是LRU的软件模拟实现。每个页面与一个软件计数器管理。初值为0，每次时钟中断时，操作系统扫描内存中的所有页面，将每个页面中的R位值加到他的计数器上，计数器的值即为访问的频繁程度。该算法的问题是记住的事情太多，如果第一次执行扫描的时间最长。比如第一次某个页面的值很大。这个很大的值会影响到下一次扫描，结果操作系统将置换有用的页面而不是不再使用的页面。
8.修改一下NFU：R位被加进之前，将计数器右移一位，同时将R加到计数器的左端。即为老化算法
9.工作集页面置换算法。一个进程当前正在使用的页面的集合称作他的工作集。基本思路是找出一个不在工作集中的页面并淘汰它。
10.工作集时钟页面置换算法。基于时钟算法，并且使用了工作集信息。
&lt;p&gt;页面调度算法总结；
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/32236_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/8aeb6656133389828c802b546823152810700003.jpg&#34;&gt;&lt;/a&gt;
最好的两种算法是老化算法和工作集时钟算法，分别基于LRU和工作集。具有良好的页面调度性能。&lt;/p&gt;</description>
    </item>
    <item>
      <title>现代操作系统的调度</title>
      <link>http://blog.leaver.me/2013/01/24/%E7%8E%B0%E4%BB%A3%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E7%9A%84%E8%B0%83%E5%BA%A6/</link>
      <pubDate>Thu, 24 Jan 2013 14:08:51 +0000</pubDate>
      <guid>http://blog.leaver.me/2013/01/24/%E7%8E%B0%E4%BB%A3%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E7%9A%84%E8%B0%83%E5%BA%A6/</guid>
      <description>&lt;p&gt;这几天在读《现代操作系统》，想起当时学这门课的时候，并没有感觉那么爽，现在通读这本书，知识的过渡性和结构性令我叹服。感受操作系统的魅力吧。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;批处理系统中的调度：&lt;/strong&gt;
1.先来先服务&lt;/p&gt;
&lt;p&gt;2.最短作业优先
只有在所有的作业都可以同时运行(也即同时到达)的情况下，最短作业优先算法才是最优化的。&lt;/p&gt;
&lt;p&gt;3.最短剩余时间优先-最短作业优先的抢占式版本。调度算法总是选择剩余时间最短的那个进程运行，注意，运行时间必须提前掌握，当一个新的作业到达时，其整个时间同当前进程的剩余时间做比较，如果更少。就运行新进程。可以使新的短作业获得良好的服务。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;交互式系统的调度&lt;/strong&gt;
1.轮转调度。
最古老，最简单，最公平切使用最广，每个进程被分配一个时间片。如果进程在时间片结束之前阻塞或结束，则CPU立即切换。调度程序只是维护一张可运行进程列表，当进程用完它的时间片后，就被移到队列的末尾。时间片太短会导致进程切换过多，降低CPU效率，设置的太长又引起对短的交互请求的响应时间变长。通常20-50ms算合理。&lt;/p&gt;
&lt;p&gt;2.优先级调度
为了防止高优先级进程无休止的运行下去，可以在一个时钟中断里降低当前进程的优先级，如果这导致该进程的优先级低于次高优先级的进程，则切换或者也可以赋予每个进程一个时间片。可以和轮转调度一起工作，设置每个优先级上有多个进程。优先运行高优先级，并未高优先级上的进程按照轮转换着运行，如果高优先级没了。就进入到较低优先级。。。问题是如果不偶尔对优先级进行调整，则可能发生饥饿现象。&lt;/p&gt;
&lt;p&gt;3.多级队列
CTSS的设计者发现为CPU密集型进程设置较长的时间片比频繁的分给他们很短的时间片更为高效（减少了交换次数），但长时间的进程又会影响响应时间，方法是设立优先级类，最高优先级类里的进程运行1个时间片。次高运行2个。以此类推。当一个进程用完分配的时间片后，被移动到下一类。大致算法都是用于讨好交互用户和进程，而不惜牺牲后台进程
//故事：可以采用只要终端上有Enter键按下，就将该终端上的进程移到最高优先级类。假设当前进程急需交互，但是。一个人发现了。大家都开始用。。。理论和实际差异太大。。哈哈&lt;/p&gt;
&lt;p&gt;4.最短进程优先
这个很好立即，但难点在于如何找出最短的那个。一种方法是根据过去的行为推测。假设每个命令执行时间为T0，下一次运行时间为T1，则可以根据aT0+(1-a)T1来估计时间。。a被用来决定尽快忘掉老的运行时间还是记住它。这种算法成为老化算法。通常选a=1/2&lt;/p&gt;
&lt;p&gt;5.保证调度
就是保证每个用户获得cpu的1/n，系统需要跟踪进程的cpu时间，他实际获得如果多于应该获得的。则转向实际获得小于应该获得的。&lt;/p&gt;
&lt;p&gt;6.彩票调度
保证调度很难实现，而彩票调度算法是向进程提供各种系统资源的彩票。一旦需要做出一项调度决策时，就随机抽出一张彩票。谁获得谁就上。比如视频服务器，可以为不同的帧速率提供不同的彩票。然后分配cpu&lt;/p&gt;
&lt;p&gt;7.公平分享调度
这个就考虑到了进程的所有者。需要我们定义公平的含义。是保证每个用户只占用的时间相等还是其他了。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;实时系统的调度：&lt;/strong&gt;
可以分为硬实时和软实时，前者必须满足绝对的截止时间，后者则可以容忍一些。用户级线程系统是不知道的。用户级和内核级的差异主要在性能，用户级需少量的机器指令，而内核级需要很多的。过程。采用轮转和优先级调度更常见一些。&lt;/p&gt;
&lt;p&gt;//操作系统的大神们太强大了。哲学家进餐问题居然可以通过拿起左边叉子以后，检测右边是否可用，如果不可用，则等待一个随机的时间。这种方案是可行的。在极少的情况下不可用。。&lt;/p&gt;</description>
    </item>
    <item>
      <title>汇编-32位CPU所含有的寄存器</title>
      <link>http://blog.leaver.me/2012/09/24/%E6%B1%87%E7%BC%96-32%E4%BD%8Dcpu%E6%89%80%E5%90%AB%E6%9C%89%E7%9A%84%E5%AF%84%E5%AD%98%E5%99%A8/</link>
      <pubDate>Mon, 24 Sep 2012 08:02:36 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/09/24/%E6%B1%87%E7%BC%96-32%E4%BD%8Dcpu%E6%89%80%E5%90%AB%E6%9C%89%E7%9A%84%E5%AF%84%E5%AD%98%E5%99%A8/</guid>
      <description>&lt;p&gt;今年的课程有汇编。真为校领导的智商捉鸡。。不过还是要学的。分享一篇来自&lt;a href=&#34;http://blog.minidx.com/2007/12/10/233.html&#34;&gt;中文FLEX例子&lt;/a&gt;的汇编寄存器的文章。很不错的一篇寄存器详解的文章。文章最后是我找到的一个汇编指令助手。&lt;/p&gt;
&lt;p&gt;　　4个数据寄存器(EAX、EBX、ECX和EDX)　　
　　2个变址和指针寄存器(ESI和EDI) 2个指针寄存器(ESP和EBP)
　　6个段寄存器(ES、CS、SS、DS、FS和GS)
　　1个指令指针寄存器(EIP) 1个标志寄存器(EFlags)&lt;/p&gt;
&lt;h3 id=&#34;1数据寄存器&#34;&gt;1、数据寄存器&lt;/h3&gt;
&lt;p&gt;　　数据寄存器主要用来保存操作数和运算结果等信息，从而节省读取操作数所需占用总线和访问存储器的时间。32位CPU有4个32位的通用寄存器EAX、EBX、ECX和EDX。对低16位数据的存取，不会影响高16位的数据。这些低16位寄存器分别命名为：AX、BX、CX和DX，它和先前的CPU中的寄存器相一致。&lt;/p&gt;
&lt;p&gt;　　4个16位寄存器又可分割成8个独立的8位寄存器(AX：AH-AL、BX：BH-BL、CX：CH-CL、DX：DH-DL)，每个寄存器都有自己的名称，可独立存取。程序员可利用数据寄存器的这种”可分可合”的特性，灵活地处理字/字节的信息。&lt;/p&gt;
&lt;p&gt;　　寄存器AX和AL通常称为累加器(Accumulator)，用累加器进行的操作可能需要更少时间。累加器可用于乘、 除、输入/输出等操作，它们的使用频率很高； 寄存器BX称为基地址寄存器(Base Register)。它可作为存储器指针来使用； 寄存器CX称为计数寄存器(Count Register)。在循环和字符串操作时，要用它来控制循环次数；在位操作 中，当移多位时，要用CL来指明移位的位数；&lt;/p&gt;
&lt;p&gt;　　寄存器DX称为数据寄存器(Data Register)。在进行乘、除运算时，它可作为默认的操作数参与运算，也 可用于存放I/O的端口地址。在16位CPU中，AX、BX、CX和DX不能作为基址和变址寄存器来存放存储单元的地址，但在32位CPU中，其32位寄存器EAX、EBX、ECX和EDX不仅可传送数据、暂存数据保存算术逻辑运算结果，而且也可作为指针寄存器，所以，这些32位寄存器更具有通用性。&lt;/p&gt;
&lt;h3 id=&#34;2变址寄存器&#34;&gt;2、变址寄存器&lt;/h3&gt;
&lt;p&gt;　　32位CPU有2个32位通用寄存器ESI和EDI。其低16位对应先前CPU中的SI和DI，对低16位数据的存取，不影响高16位的数据。&lt;/p&gt;
&lt;p&gt;　　寄存器ESI、EDI、SI和DI称为变址寄存器(Index Register)，它们主要用于存放存储单元在段内的偏移量，用它们可实现多种存储器操作数的寻址方式，为以不同的地址形式访问存储单元提供方便。变址寄存器不可分割成8位寄存器。作为通用寄存器，也可存储算术逻辑运算的操作数和运算结果。它们可作一般的存储器指针使用。在字符串操作指令的执行过程中，对它们有特定的要求，而且还具有特殊的功能。&lt;/p&gt;
&lt;h3 id=&#34;3指针寄存器&#34;&gt;3、指针寄存器&lt;/h3&gt;
&lt;p&gt;　　32位CPU有2个32位通用寄存器EBP和ESP。其低16位对应先前CPU中的SBP和SP，对低16位数据的存取，不影响高16位的数据。&lt;/p&gt;
&lt;p&gt;　　寄存器EBP、ESP、BP和SP称为指针寄存器(Pointer Register)，主要用于存放堆栈内存储单元的偏移量，用它们可实现多种存储器操作数的寻址方式，为以不同的地址形式访问存储单元提供方便。指针寄存器不可分割成8位寄存器。作为通用寄存器，也可存储算术逻辑运算的操作数和运算结果。&lt;/p&gt;
&lt;p&gt;　　它们主要用于访问堆栈内的存储单元，并且规定：&lt;/p&gt;
&lt;p&gt;　　BP为基指针(Base Pointer)寄存器，用它可直接存取堆栈中的数据；&lt;/p&gt;
&lt;p&gt;　　SP为堆栈指针(Stack Pointer)寄存器，用它只可访问栈顶。&lt;/p&gt;
&lt;h3 id=&#34;4段寄存器&#34;&gt;4、段寄存器&lt;/h3&gt;
&lt;p&gt;　　段寄存器是根据内存分段的管理模式而设置的。内存单元的物理地址由段寄存器的值和一个偏移量组合而成&lt;/p&gt;
&lt;p&gt;　　的，这样可用两个较少位数的值组合成一个可访问较大物理空间的内存地址。&lt;/p&gt;
&lt;p&gt;　　CPU内部的段寄存器：&lt;/p&gt;
&lt;p&gt;　　CS——代码段寄存器(Code Segment Register)，其值为代码段的段值；
　　DS——数据段寄存器(Data Segment Register)，其值为数据段的段值；　
　　ES——附加段寄存器(Extra Segment Register)，其值为附加数据段的段值；
　　SS——堆栈段寄存器(Stack Segment Register)，其值为堆栈段的段值；
　　FS——附加段寄存器(Extra Segment Register)，其值为附加数据段的段值；
　　GS——附加段寄存器(Extra Segment Register)，其值为附加数据段的段值。&lt;/p&gt;
&lt;p&gt;　　在16位CPU系统中，它只有4个段寄存器，所以，程序在任何时刻至多有4个正在使用的段可直接访问；在32位微机系统中，它有6个段寄存器，所以，在此环境下开发的程序最多可同时访问6个段。32位CPU有两个不同的工作方式：实方式和保护方式。在每种方式下，段寄存器的作用是不同的。有关规定简单描述如下：&lt;/p&gt;
&lt;p&gt;　　实方式： 前4个段寄存器CS、DS、ES和SS与先前CPU中的所对应的段寄存器的含义完全一致，内存单元的逻辑地址仍为”段值：偏移量”的形式。为访问某内存段内的数据，必须使用该段寄存器和存储单元的偏移量。&lt;/p&gt;
&lt;p&gt;　　保护方式： 在此方式下，情况要复杂得多，装入段寄存器的不再是段值，而是称为”选择子”(Selector)的某个值。&lt;/p&gt;
&lt;h3 id=&#34;5指令指针寄存器&#34;&gt;5、指令指针寄存器&lt;/h3&gt;
&lt;p&gt;　　32位CPU把指令指针扩展到32位，并记作EIP，EIP的低16位与先前CPU中的IP作用相同。&lt;/p&gt;
&lt;p&gt;　　指令指针EIP、IP(Instruction Pointer)是存放下次将要执行的指令在代码段的偏移量。在具有预取指令功能的系统中，下次要执行的指令通常已被预取到指令队列中，除非发生转移情况。所以，在理解它们的功能时，不考虑存在指令队列的情况。&lt;/p&gt;
&lt;p&gt;　　在实方式下，由于每个段的最大范围为64K，所以，EIP中的高16位肯定都为0，此时，相当于只用其低16位的IP来反映程序中指令的执行次序。&lt;/p&gt;
&lt;h3 id=&#34;6标志寄存器&#34;&gt;6、标志寄存器&lt;/h3&gt;
&lt;p&gt;　　一、运算结果标志位&lt;/p&gt;
&lt;p&gt;　　1、进位标志CF(Carry Flag)&lt;/p&gt;
&lt;p&gt;　　进位标志CF主要用来反映运算是否产生进位或借位。如果运算结果的最高位产生了一个进位或借位，那么，其值为1，否则其值为0。使用该标志位的情况有：多字(字节)数的加减运算，无符号数的大小比较运算，移位操作，字(字节)之间移位，专门改变CF值的指令等。&lt;/p&gt;
&lt;p&gt;　　2、奇偶标志PF(Parity Flag)&lt;/p&gt;
&lt;p&gt;　　奇偶标志PF用于反映运算结果中”1″的个数的奇偶性。如果”1″的个数为偶数，则PF的值为1，否则其值为0。&lt;/p&gt;
&lt;p&gt;　　利用PF可进行奇偶校验检查，或产生奇偶校验位。在数据传送过程中，为了提供传送的可靠性，如果采用奇偶校验的方法，就可使用该标志位。&lt;/p&gt;
&lt;p&gt;　　3、辅助进位标志AF(Auxiliary Carry Flag)&lt;/p&gt;
&lt;p&gt;　　在发生下列情况时，辅助进位标志AF的值被置为1，否则其值为0：&lt;/p&gt;
&lt;p&gt;　　(1)、在字操作时，发生低字节向高字节进位或借位时；　　
　　(2)、在字节操作时，发生低4位向高4位进位或借位时。&lt;/p&gt;
&lt;p&gt;　　对以上6个运算结果标志位，在一般编程情况下，标志位CF、ZF、SF和OF的使用频率较高，而标志位PF和AF的使用频率较低。&lt;/p&gt;
&lt;p&gt;　　4、零标志ZF(Zero Flag)&lt;/p&gt;
&lt;p&gt;　　零标志ZF用来反映运算结果是否为0。如果运算结果为0，则其值为1，否则其值为0。在判断运算结果是否为0时，可使用此标志位。&lt;/p&gt;
&lt;p&gt;　　5、符号标志SF(Sign Flag)&lt;/p&gt;
&lt;p&gt;　　符号标志SF用来反映运算结果的符号位，它与运算结果的最高位相同。在微机系统中，有符号数采用补码表示法，所以，SF也就反映运算结果的正负号。运算结果为正数时，SF的值为0，否则其值为1。&lt;/p&gt;
&lt;p&gt;　　6、溢出标志OF(Overflow Flag)&lt;/p&gt;
&lt;p&gt;　　溢出标志OF用于反映有符号数加减运算所得结果是否溢出。如果运算结果超过当前运算位数所能表示的范围，则称为溢出，OF的值被置为1，否则，OF的值被清为0。”溢出”和”进位”是两个不同含义的概念，不要混淆。如果不太清楚的话，请查阅《计算机组成原理》课程中的有关章节。&lt;/p&gt;
&lt;p&gt;　　二、状态控制标志位&lt;/p&gt;
&lt;p&gt;　　状态控制标志位是用来控制CPU操作的，它们要通过专门的指令才能使之发生改变。&lt;/p&gt;
&lt;p&gt;　　1、追踪标志TF(Trap Flag)&lt;/p&gt;
&lt;p&gt;　　当追踪标志TF被置为1时，CPU进入单步执行方式，即每执行一条指令，产生一个单步中断请求。这种方式主要用于程序的调试。指令系统中没有专门的指令来改变标志位TF的值，但程序员可用其它办法来改变其值。&lt;/p&gt;
&lt;p&gt;　　2、中断允许标志IF(Interrupt-enable Flag)&lt;/p&gt;
&lt;p&gt;　　中断允许标志IF是用来决定CPU是否响应CPU外部的可屏蔽中断发出的中断请求。但不管该标志为何值，CPU都必须响应CPU外部的不可屏蔽中断所发出的中断请求，以及CPU内部产生的中断请求。具体规定如下：&lt;/p&gt;
&lt;p&gt;　　(1)、当IF=1时，CPU可以响应CPU外部的可屏蔽中断发出的中断请求；
　　(2)、当IF=0时，CPU不响应CPU外部的可屏蔽中断发出的中断请求。&lt;/p&gt;
&lt;p&gt;　　CPU的指令系统中也有专门的指令来改变标志位IF的值。&lt;/p&gt;
&lt;p&gt;　　3、方向标志DF(Direction Flag)&lt;/p&gt;
&lt;p&gt;　　方向标志DF用来决定在串操作指令执行时有关指针寄存器发生调整的方向。具体规定在第5.2.11节——字符串操作指令——中给出。在微机的指令系统中，还提供了专门的指令来改变标志位DF的值。&lt;/p&gt;
&lt;p&gt;　　三、32位标志寄存器增加的标志位&lt;/p&gt;
&lt;p&gt;　　1、I/O特权标志IOPL(I/O Privilege Level)&lt;/p&gt;
&lt;p&gt;　　I/O特权标志用两位二进制位来表示，也称为I/O特权级字段。该字段指定了要求执行I/O指令的特权级。如果当前的特权级别在数值上小于等于IOPL的值，那么，该I/O指令可执行，否则将发生一个保护异常。&lt;/p&gt;
&lt;p&gt;　　2、嵌套任务标志NT(Nested Task)&lt;/p&gt;
&lt;p&gt;　　嵌套任务标志NT用来控制中断返回指令IRET的执行。具体规定如下：&lt;/p&gt;
&lt;p&gt;　　(1)、当NT=0，用堆栈中保存的值恢复EFLAGS、CS和EIP，执行常规的中断返回操作；
　　(2)、当NT=1，通过任务转换实现中断返回。&lt;/p&gt;
&lt;p&gt;　　3、重启动标志RF(Restart Flag)&lt;/p&gt;
&lt;p&gt;　　重启动标志RF用来控制是否接受调试故障。规定：RF=0时，表示”接受”调试故障，否则拒绝之。在成功执行完一条指令后，处理机把RF置为0，当接受到一个非调试故障时，处理机就把它置为1。&lt;/p&gt;
&lt;p&gt;　　4、虚拟8086方式标志VM(Virtual 8086 Mode)&lt;/p&gt;
&lt;p&gt;　　如果该标志的值为1，则表示处理机处于虚拟的8086方式下的工作状态，否则，处理机处于一般保护方式下的工作状态。&lt;/p&gt;
&lt;p&gt;下载：&lt;a href=&#34;http://pan.baidu.com/share/link?shareid=61312&amp;amp;uk=1493685990&#34;&gt;汇编指令助手&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>修改Windows系统软件默认安装路径</title>
      <link>http://blog.leaver.me/2012/05/17/%E4%BF%AE%E6%94%B9windows%E7%B3%BB%E7%BB%9F%E8%BD%AF%E4%BB%B6%E9%BB%98%E8%AE%A4%E5%AE%89%E8%A3%85%E8%B7%AF%E5%BE%84/</link>
      <pubDate>Thu, 17 May 2012 06:02:51 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/05/17/%E4%BF%AE%E6%94%B9windows%E7%B3%BB%E7%BB%9F%E8%BD%AF%E4%BB%B6%E9%BB%98%E8%AE%A4%E5%AE%89%E8%A3%85%E8%B7%AF%E5%BE%84/</guid>
      <description>&lt;p&gt;　　作为一个完全不能容忍windows默认程序都往C:\Program Files\目录里安装的人。每次安装软件的时候，都得手动一个个改到D:\Program Files里。安装软件多了。就hold不住了。&lt;/p&gt;
&lt;p&gt;　　其实可以通过注册表使得所有安装程序默认安装到其他盘的。将下列内容保存到一个文本文件里，命名为Mo.reg。然后运行即可。以后安装的程序就会默认安装到D盘的Program Files目录了。你也可以根据需要自行修改&lt;/p&gt;
&lt;p&gt;　　&lt;pre lang=&#34;c&#34;&gt;&lt;/p&gt;
&lt;p&gt;　　Windows Registry Editor Version 5.00&lt;/p&gt;
&lt;p&gt;　　;修改Windows系统软件默认安装路径&lt;/p&gt;
&lt;p&gt;　　[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion]&lt;/p&gt;
&lt;p&gt;　　&amp;ldquo;ProgramFilesDir&amp;rdquo;=&amp;ldquo;D:\Program Files&amp;rdquo;&lt;/p&gt;
&lt;p&gt;　　&lt;/pre&gt;
效果如下图，安装程序已经默认到D盘了
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/21644_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/a83d479db2c8d3fac56dc0dacca9fca7329d7c61.jpg&#34; title=&#34;w&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;update:已知后遗症，我在这样实践了以后，发现vs2010的.net framework 4将会丢失。也就是说就不能新建.net framework 4项目了，具体不明，可能是我当初把VS一部分安装到D盘的缘故，应该可以通过重新安装vs解决，如果你不想折腾。把注册表改回去就可以了。&lt;/p&gt;</description>
    </item>
    <item>
      <title>windows下vim闪烁问题</title>
      <link>http://blog.leaver.me/2012/05/07/windows%E4%B8%8Bvim%E9%97%AA%E7%83%81%E9%97%AE%E9%A2%98/</link>
      <pubDate>Mon, 07 May 2012 19:21:59 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/05/07/windows%E4%B8%8Bvim%E9%97%AA%E7%83%81%E9%97%AE%E9%A2%98/</guid>
      <description>&lt;p&gt;　　今天打开我的vim才发现，界面隔几秒会闪烁。虽说貌似能够起到防止眼睛疲劳的效果，但我实在是hold不住啊。不行，搜索。。
首先有这个问题的人不多。首先找到了&lt;a href=&#34;http://hi.baidu.com/chrisyue/blog/item/ebc7b8de373c1048cdbf1af9.html&#34;&gt;这篇文章&lt;/a&gt;，但是作者不知道怎么想的。只说了原因，没有给出解决方法。继续搜索关键字cursorcolumn，结果找到了&lt;a href=&#34;http://yyq123.blogspot.com/2012/01/vim-cursor.html&#34;&gt;这篇文章&lt;/a&gt;，按着说明来了一下&lt;/p&gt;
&lt;pre lang=&#34;php&#34;&gt;set cursorline cursorcolumn&lt;/pre&gt;
&lt;p&gt;没效果。依然闪烁。
　　好吧。如果是插件的问题。于是我删掉了所有的插件包括写入的配置。依然不行。于是还是采用排除法，一行行删掉配置文件。最后定位到&lt;/p&gt;
&lt;pre lang=&#34;php&#34;&gt;set guifont=Arial_monospaced_for_SAP:h9:cANSI &lt;/pre&gt;
&lt;p&gt;　　这是设置字体的，不太明白为什么会出现这样的情况。怀疑是字体的原因，于是换个字体，依然闪烁。。好吧。就这样吧。删掉算了。&lt;/p&gt;</description>
    </item>
    <item>
      <title>四种I/O控制方式</title>
      <link>http://blog.leaver.me/2012/05/07/%E5%9B%9B%E7%A7%8Di/o%E6%8E%A7%E5%88%B6%E6%96%B9%E5%BC%8F/</link>
      <pubDate>Mon, 07 May 2012 16:50:48 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/05/07/%E5%9B%9B%E7%A7%8Di/o%E6%8E%A7%E5%88%B6%E6%96%B9%E5%BC%8F/</guid>
      <description>&lt;p&gt;　　基本上原文照搬过来吧。主要是原文排版太乱。不利于传播。
　　随着计算机技术的发展，I/O控制方式也在不断地发展。I/O控制的发展经历了以下四个阶段：&lt;/p&gt;
&lt;p&gt;　　&lt;em&gt;&lt;strong&gt;一.程序I/O控制方式&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;　　在早期的计算机系统中，由于无中断机构，处理机对I/O设备的控制，采取程序I/O方式（Programmed I/O方式）。在程序I/O方式中，由于CPU的高速性和I/O设备的低速性，致使CPU 的绝大部分时间都处于等待I/O设备完成数据I/O的循环测试中，造成对CPU的极大浪费。在该方式中，CPU之所以要不断地测试I/O设备的状态，就是因为在CPU中无中断机构，使 I/O设备无法向CPU报告它已完成了一个字符的输入操作。如下图所示：&lt;/p&gt;
&lt;p&gt;　　图1.&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/21244_o.jpg&#34;&gt;![]}/images/c83bce26670bc565b0fb2eaa4984e5b7575b618a.jpg)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;　　程序I/O方式又称忙&amp;ndash;等待方式，即在处理机向设备控制器发出一条I/O指令启动输入设备、输出数据时，要同时把状态寄存器中的忙/闲标志busy置为1，然后便不断地循环测试busy。当busy=1时，表示输入机尚未输完一个字（符），处理机应继续对busy进行测试；直至busy=0，表明输入机已将输入数据送入控制器的数据寄存器中，于是处理机将数据寄存器中的数据取出，送入内存指定单元中，接着，再启动去读下一个数据，并置busy=1。 △ 此方式造成对CPU的极大浪费。&lt;/p&gt;
&lt;p&gt;　　&lt;em&gt;&lt;strong&gt;二.中断驱动I/O控制方式&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;　　在现代计算机系统中，对I/O设备的控制，广泛采用中断驱动（Interrupt&amp;mdash;Driven）方式。在I/O设备输入每个数据的过程中，由于无须CPU干预，因而可使CPU与I/O设备并行工作。仅当输完一个数据时，才需CPU花费极短的时间去做些中断处理。可见，这样可使CPU和I/O设备都处于忙碌状态，从而提高了整个系统的资源利用率及吞吐量。如下图所示：&lt;/p&gt;
&lt;p&gt;　　图2
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/21245_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/f053eaab91b09f2666fb13152a114677eea8c2da.jpg&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;　　当某进程要启动某个I/O设备工作时，便由CPU向相应的设备控制器发出一条I/O命令，然后立即返回继续执行原来的任务。设备控制器便按照该命令的要求去控制I/O设备。此时，CPU与I/O设备并行操作。　 例如，从终端输入一个字符的时间约为 100ms ， 而将字符送入终端缓冲区的时间小于 0.1ms 。 若采用程序 I/O 方式， CPU 约有 99.9ms 的 时间处于忙 — 等待中。 采用中断驱动方式后， CPU 可利用这 99.9 ms 的时间去做其它事情，而仅用 0.1 ms 的时间来处理由控制器发来的中 断请求 。 可见，中断驱动方式可以成百倍地提高 CPU 的利用率。△ 中断驱动方式可以成百倍地提高CPU的利用率。&lt;/p&gt;
&lt;p&gt;　　&lt;em&gt;&lt;strong&gt;三.直接存储器访问DMA控制方式&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;　　&amp;ndash;&amp;gt;DMA控制方式的引入&lt;/p&gt;
&lt;p&gt;　　虽然中断驱动I/O比程序I/O方式更有效，但它是以字（节）为单位进行I/O的，若将这种方式用于块设备的I/O，显然将会是极其低效的。为了进一步减少CPU对I/O的干预，而引入了直接存储器访问（Direct Memory Access）方式。如下图：&lt;/p&gt;
&lt;p&gt;　　图3&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/21246_o.jpg&#34;&gt;![]}/images/ee3e0c3ca8d998d2a84488f01d3ca4d6e642f217.jpg)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;　　此方式的特点是：
　　数据传输的基本单位是数据块；所传输的数据是从设备直接送入内存的,或者相反；整块数据的传送是在控制器的控制下完成的；&lt;/p&gt;
&lt;p&gt;　　可见，DMA方式较之中断驱动方式，又是成百倍地减少了CPU对I/O的干预，进一步提高了CPU与I/O设备的并行操作程度。&lt;/p&gt;
&lt;p&gt;　　&amp;ndash;&amp;gt;DMA控制器的组成&lt;/p&gt;
&lt;p&gt;　　DMA控制器由三部分组成，如下图：&lt;/p&gt;
&lt;p&gt;　　图4&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/21249_o.jpg&#34;&gt;![]}/images/bbb47eca5cb44fe7cf36bea37349cf6b728e99b5.jpg)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;　　主机与DMA控制器的接口；DMA控制器与块设备的接口；I/O控制逻辑；&lt;/p&gt;
&lt;p&gt;　　为了实现控制器与主机之间成块数据的直接交换，必须在DMA控制器中设四类寄存器，如上图&lt;/p&gt;
&lt;p&gt;　　命令/状态寄存器；内存地址寄存器MAR；数据寄存器DR；数据计数器DC；&lt;/p&gt;
&lt;p&gt;　　&amp;ndash;&amp;gt;DMA工作过程&lt;/p&gt;
&lt;p&gt;　　DMA的工作过程如下图：&lt;/p&gt;
&lt;p&gt;　　图5
　　&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/21247_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/14889b82ecfe048a30247ccbbf82d54d3484bc8e.jpg&#34;&gt;&lt;/a&gt;
　　&lt;em&gt;&lt;strong&gt;四.I/O通道控制方式&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;　　&amp;ndash;&amp;gt;I/O通道控制方式的引入&lt;/p&gt;
&lt;p&gt;　　I/O通道方式是DMA方式的发展，它可进一步减少CPU的干预，即把对一个数据块的读（或写）为单位的干预，减少为对一组数据块的读（或写）及有关的控制和管理为单位的干预。同时，又可实现CPU、通道和I/O设备三者的并行工作，从而更有效的提高了整个系统的资源利用率。&lt;/p&gt;
&lt;p&gt;　　&amp;ndash;&amp;gt;通道程序&lt;/p&gt;
&lt;p&gt;　　通道是通过执行通道程序，并与设备控制器来共同实现对I/O设备的控制的。通道程序是由一系列的通道指令（或称通道命令）所构成。通道指令与一般的机器指令不同，在它的每条指令中包含下列诸信息：&lt;/p&gt;
&lt;p&gt;　　操作码&amp;mdash;-它规定了指令所执行的操作；内存地址;计数&amp;mdash;-表明本条指令所要读（或写）数据的字节数；通道程序结束位P;记录结束标志位R&lt;/p&gt;
&lt;p&gt;　 &lt;strong&gt;有几种I/O控制方式？各有何特点？&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;　　答：I/O控制方式有四种：程序直接控制方式、中断控制方式、DMA方式和通道控制方式。&lt;/p&gt;
&lt;p&gt;　　（1） 程序直接控制方式：优点是控制简单，不需要多少硬件支持。但CPU和外设只能串行工作，且CPU的大部分时间处于循环测试状态，使CPU的利用率大大降低，因此该方式只适用于那些CPU执行速度较慢且外设较少的系统。&lt;/p&gt;
&lt;p&gt;　　（2） 中断处理方式：优点是能实现CPU与外设间的并行操作，CPU的利用率较程序直接控制方式大大提高。由于在一次数据传送过程中CPU通常以字节为单位进行干预，中断次数较多而耗去大量的CPU时间。&lt;/p&gt;
&lt;p&gt;　　（3） DMA方式：与中断方式相比，DMA方式是在一批数据传送完成后中断CPU，从而大大减少CPU进行中断处理的次数，且DMA方式下的数据传送实在DMA控制下完成的。但DMA方式仍有一定的局限，如对外设的管理和某些操作仍由CPU控制，多个DMA控制器的使用也不经济。&lt;/p&gt;
&lt;p&gt;　　（4） 通道控制方式：CPU只需发出I/O指令，通道完成相应的I/O操作，并在操作结束时向CPU发出中断信号；同时一个通道还能控制多台外设。但是通道价格较高，从经济角度出发不宜过多使用。&lt;/p&gt;
&lt;p&gt;参考：
&lt;a href=&#34;http://oa.gdut.edu.cn/os/multimedia/oscai/chapter5/pages/ch52.htm&#34;&gt;http://oa.gdut.edu.cn/os/multimedia/oscai/chapter5/pages/ch52.htm&lt;/a&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>WIN7上网提示711错误解决</title>
      <link>http://blog.leaver.me/2012/04/23/win7%E4%B8%8A%E7%BD%91%E6%8F%90%E7%A4%BA711%E9%94%99%E8%AF%AF%E8%A7%A3%E5%86%B3/</link>
      <pubDate>Mon, 23 Apr 2012 12:27:59 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/04/23/win7%E4%B8%8A%E7%BD%91%E6%8F%90%E7%A4%BA711%E9%94%99%E8%AF%AF%E8%A7%A3%E5%86%B3/</guid>
      <description>&lt;p&gt;　　朋友今天上网突然网络连接出现了这个问题，也就是无法加载远程访问连接服务。Google了一下，第一种方法就是查看如下的服务是否启动，如果没有，自行启动。
服务名称:eventlog 显示名称: Windows Event Log 启动类型:自动
服务名称:TapiSrv 显示名称: Telephony 启动类型:手动
服务名称:SstpSvc 显示名称: Secure Socket Tunneling Protocol Service 启动类型:手动
服务名称:Netman 显示名称: Network Connections 启动类型:手动
服务名称:nsi 显示名称: Network Store Inte***ce Service 启动类型: 自动
服务名称:RasMan 显示名称: Remote Access Connection Manager 启动类型:手动&lt;/p&gt;
&lt;p&gt;　　启动方法：对着我的电脑点右键-》管理-》服务和应用-》服务 找到对应的服务后，右键属性，启动类型就可以了
　　但是如上操作有时并不可以，会提示有些服务不能启动，这种情况下，&lt;/p&gt;
&lt;p&gt;　　用管理员账号登陆，再打开 c:\windows\system32\logfiles 如果看到 wmi文件夹，在wmi文件夹上点右键，点 获取管理员权限 ,后重启即可修复。
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/20868_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/8c81734100537494754fe25960feac29d5d469fc.jpg&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;　　　附上Win7下添加右键获取管理员权限的方法：&lt;/p&gt;
&lt;p&gt;在Win7下经常要用到管理员权限,为了方便可以添加一个右键菜单,方法如下:
新建一个“记事本”文件，复制以下内容：&lt;/p&gt;
&lt;pre lang=&#34;c&#34;&gt;
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\*\shell\runas]
@=&#34;获取管理员权限&#34;
&#34;NoWorkingDirectory&#34;=&#34;&#34;
[HKEY_CLASSES_ROOT\*\shell\runas\command]
@=&#34;cmd.exe /c takeown /f \&#34;%1\&#34; &amp;&amp; icacls \&#34;%1\&#34; /grant administrators:F&#34;
&#34;IsolatedCommand&#34;=&#34;cmd.exe /c takeown /f \&#34;%1\&#34; &amp;&amp; icacls \&#34;%1\&#34; /grant administrators:F&#34;
[HKEY_CLASSES_ROOT\exefile\shell\runas2]
@=&#34;获取管理员权限&#34;
&#34;NoWorkingDirectory&#34;=&#34;&#34;
[HKEY_CLASSES_ROOT\exefile\shell\runas2\command]
@=&#34;cmd.exe /c takeown /f \&#34;%1\&#34; &amp;&amp; icacls \&#34;%1\&#34; /grant administrators:F&#34;
&#34;IsolatedCommand&#34;=&#34;cmd.exe /c takeown /f \&#34;%1\&#34; &amp;&amp; icacls \&#34;%1\&#34; /grant administrators:F&#34;
[HKEY_CLASSES_ROOT\Directory\shell\runas]
@=&#34;获取管理员权限&#34;
&#34;NoWorkingDirectory&#34;=&#34;&#34;
[HKEY_CLASSES_ROOT\Directory\shell\runas\command]
@=&#34;cmd.exe /c takeown /f \&#34;%1\&#34; /r /d y &amp;&amp; icacls \&#34;%1\&#34; /grant administrators:F /t&#34;
&#34;IsolatedCommand&#34;=&#34;cmd.exe /c takeown /f \&#34;%1\&#34; /r /d y &amp;&amp; icacls \&#34;%1\&#34; /grant administrators:F /t&#34;
&lt;/pre&gt;
&lt;p&gt;复制好后选文件-另存为,保存类型选&amp;quot;所有文件&amp;quot;,文件扩展名为reg 然后运行即可。&lt;/p&gt;
&lt;p&gt;Win7下取消右键获取管理员权限方法：&lt;/p&gt;
&lt;pre lang=&#34;c&#34;&gt;
Windows Registry Editor Version 5.00
[-HKEY_CLASSES_ROOT\*\shell\runas]
[-HKEY_CLASSES_ROOT\exefile\shell\runas2]
[-HKEY_CLASSES_ROOT\Directory\shell\runas]
&lt;/pre&gt;
&lt;p&gt;同样的保存上面内容为reg格式文件即可。&lt;/p&gt;</description>
    </item>
    <item>
      <title>操作系统知识点汇总(下)</title>
      <link>http://blog.leaver.me/2012/04/18/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E7%9F%A5%E8%AF%86%E7%82%B9%E6%B1%87%E6%80%BB%E4%B8%8B/</link>
      <pubDate>Wed, 18 Apr 2012 15:09:44 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/04/18/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E7%9F%A5%E8%AF%86%E7%82%B9%E6%B1%87%E6%80%BB%E4%B8%8B/</guid>
      <description>&lt;p&gt;太长了，还是分成两篇。此为下&lt;/p&gt;
&lt;p&gt;同时到达的作业使用短作业优先平均周转时间最短。&lt;/p&gt;
&lt;p&gt;系统调用和一般过程调用的区别：
1.运行状态不同 用户态/和心态
2.进入方式不同 过程调用/访问管中断
3.代码层次不同 用户级/系统级&lt;/p&gt;
&lt;p&gt;周转时间=完成时间-提交时间&lt;/p&gt;
&lt;p&gt;平均带权周转时间=周转时间/执行时间&lt;/p&gt;
&lt;p&gt;存储器分配的三种方式：1.直接分配，2.静态分配（连续），3.动态分配（需要用到重定位）&lt;/p&gt;
&lt;p&gt;地址空间是逻辑地址的集合，内存空间是物理地址的集合&lt;/p&gt;
&lt;p&gt;分区存储管理的策略：
分配策略有：首次适应算法、循环首次适应算法、最佳适应算法、最坏适应算法。
a.首次适应算法的优缺点：保留了高址部分的大空闲区，有利于后到来的大型作业的分配；低址部分不断被划分，留下许多难以利用的、小的空闲区，且每次分区分配查找时都是从低址部分开始，会增加查找时的系统开销。
b.循环首次适应算法的优缺点：使内存中的空闲分区分布得更为均匀，减少了查找时的系统开销；缺乏大的空闲分区，从而导致不能装入大型作业。
c.最佳适应算法的优缺点：每次分配给文件的都是最适合该文件大小的分区；内存中留下许多难以利用的小的空闲区。
d.最坏适应算法的优缺点：给文件分配分区后剩下的的空闲区不至于太小，产生碎片的几率最小，对中小型文件分配分区操作有利；使存储器中缺乏大的空闲区，对大型文件的分区分配不利。&lt;/p&gt;
&lt;p&gt;内部碎片是指分配给作业的存储空间未被使用的部分，外部碎片是指系统中无法利用的小存储块。
页面置换算法：
1.最佳置换算法 永远不需要，最长的时间后才能访问的页面被调出
2.先进先出
3.最近最久未使用 传说中的LRU，最近一段时间内没被访问的页面被调出&lt;/p&gt;
&lt;p&gt;采用分段式不会产生内部碎片，虚拟存储器的最大容量是由计算的地址结构决定的&lt;/p&gt;
&lt;p&gt;页面的大小与可能产生缺页中断的次数成反比&lt;/p&gt;
&lt;p&gt;作业在执行中发生了缺页中断，经操作系统处理后，应让其执行被中断的指令&lt;/p&gt;
&lt;p&gt;段页式存储器管理系统中，内存等分成块，然后程序按照逻辑模块划分成若干段。&lt;/p&gt;
&lt;p&gt;先进先出页面置换算法会产生Belady现象&lt;/p&gt;
&lt;p&gt;回收分区后造成空闲分区-1的原因是有有上邻和下邻空闲分区&lt;/p&gt;
&lt;p&gt;执行过程不能被修改的代码称为可重入代码。。
请求分页存储器管理中，地址变换可能因为地址越界，缺页，访问存在权限错误而产生中断&lt;/p&gt;
&lt;p&gt;交换技术是以CPU时间为代价的&lt;/p&gt;
&lt;p&gt;段页式管理中，作业分段，段内分页，页内分块，每条访问内存的指令需要三步
1.通过段号查段表。。得到页表地址
2.通过页号查页表。。得到物理块号
3.物理块号+页内地址 访问真实地址&lt;/p&gt;
&lt;p&gt;固定分区分配和页式管理会产生内碎片，额可变分区和段式则产生外部碎片。&lt;/p&gt;
&lt;p&gt;输出输入控制方式
①程序I/O控制方式:适用于结构简单，只需少量硬件的电路；
②中断驱动I/O控制方式：适用于高效场合；
③直接存储访问DMA I/O控制方式：适用于无须CPU介入的控制器来控制内存与外设之间的数据交流的场合；
④I/O通道控制方式：适用于以字节为单位的干预，同时实现CPU，通道和I/O设备三者并行操作的场合。&lt;/p&gt;
&lt;p&gt;设备处理程序又称为设备驱动程序，其主要任务是接收来自上层的与设备无关的输入输出请求，进行与设备相关的处理&lt;/p&gt;
&lt;p&gt;通道又称为I/0处理机，用来实现内存与外设之间的信息传输。&lt;/p&gt;
&lt;p&gt;为了使多个进程能够更有效的同时处理输入和输出请求，最好使用缓冲池结构的缓冲技术&lt;/p&gt;
&lt;p&gt;缺页中断属于外部中断，Ctrl+C属于程序性中断&lt;/p&gt;
&lt;p&gt;设备分配时涉及到的主要数据结构设备控制表，控制器控制表，通道控制表，系统设备表&lt;/p&gt;
&lt;p&gt;从资源分配的角度可将I/0分为独享设备，共享设备，虚拟设备&lt;/p&gt;
&lt;p&gt;引入缓冲技术的原因：
1.缓和cpu和I/0之间的速度不匹配的矛盾
2.减少中断cpu的次数
3.提高cpu和I/o之间设备的并行性&lt;/p&gt;
&lt;p&gt;文件系统是指文件，管理文件的软件以及数据结构的总体&lt;/p&gt;
&lt;p&gt;文件系统的目的是为了实现对文件的按名存取。
逻辑文件的两种类型：记录式和流式&lt;/p&gt;
&lt;p&gt;二进制的那个位图表行号=（盘块号-1）/列数。
&lt;strong&gt;转载请注明：http://leaver.me/archives/328.html&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
    <item>
      <title>操作系统知识点汇总(上)</title>
      <link>http://blog.leaver.me/2012/04/18/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E7%9F%A5%E8%AF%86%E7%82%B9%E6%B1%87%E6%80%BB%E4%B8%8A/</link>
      <pubDate>Wed, 18 Apr 2012 14:56:32 +0000</pubDate>
      <guid>http://blog.leaver.me/2012/04/18/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E7%9F%A5%E8%AF%86%E7%82%B9%E6%B1%87%E6%80%BB%E4%B8%8A/</guid>
      <description>&lt;p&gt;这两天为了考试看完了&lt;a href=&#34;http://book.douban.com/subject/1913490/&#34;&gt;操作系统习题与解析&lt;/a&gt; 写了一些笔记，然后今天整理成电子版，，我去。写完发现2500字了都.唉，苦啊。。顺序没有过多整理。也能加深印象，太长了，还是分成两篇。此为上
&lt;a href=&#34;http://leaverimage.b0.upaiyun.com/20732_o.jpg&#34;&gt;&lt;img loading=&#34;lazy&#34; src=&#34;http://blog.leaver.me/images/59b3749d2e8d723c6558ed6c851f50d1af8cf56d.jpg&#34;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;操作系统的发展与形成：1.手工操作阶段，2.脱机输入输出阶段，3.批处理技术，4.多道程序设计技术。&lt;/p&gt;
&lt;p&gt;操作系统的基本类型：1.批处理，2.分时，3.实时。&lt;/p&gt;
&lt;p&gt;操作系统的特征：并发，共享，虚拟性，不确定性&lt;/p&gt;
&lt;p&gt;实时操作系统必须在规定时间内处理完来自外部的事件。。&lt;/p&gt;
&lt;p&gt;现代操作系统的两个基本特征是并发和共享&lt;/p&gt;
&lt;p&gt;内部命令是由系统定义的，常驻内存的处理程序的集合。&lt;/p&gt;
&lt;p&gt;操作系统的结构层次：
裸机-》cpu调度-》内存管理-》设备管理-》文件管理-》作业管理-》命令管理-》用户&lt;/p&gt;
&lt;p&gt;程序顺序执行的特征。顺序性。封闭性，可再现性。&lt;/p&gt;
&lt;p&gt;程序并发执行的特征：间断性，失去封闭性，不可再现性。&lt;/p&gt;
&lt;p&gt;进程的几个基本状态：就绪，执行，阻塞。&lt;/p&gt;
&lt;p&gt;引入进程的目的是使多道程序并发执行，以改善资源利用率，及提高系统吞吐量，而引入线程，则是为了减少并发执行所付出的时空开销，具有更好的并发性。&lt;/p&gt;
&lt;p&gt;每个进程中，访问临界资源的那段程序称之为临界区。&lt;/p&gt;
&lt;p&gt;进程互斥的准则；1.空闲放进，2.忙则等待，3.有限等待，4.让权等待&lt;/p&gt;
&lt;p&gt;管程：局部于管程的共享变量说明了对该数据结构进行操作的一组过程，以及局部与管程的数据设置初始值。&lt;/p&gt;
&lt;p&gt;P，V操作是低级进程通信原语。原语是对进程进行管理和控制的。进程不是指令的集合。&lt;/p&gt;
&lt;p&gt;创建原语的主要工作：向系统申请一个空闲PCB，并为创建进程分配必要的资源，然后初始化PCB，并插入到就绪队列。返回进程的标识号&lt;/p&gt;
&lt;p&gt;一个进程会唤醒，指的是进入就绪状态。&lt;/p&gt;
&lt;p&gt;资源分配的基本单位是进程，CPU分配的基本单位是线程。&lt;/p&gt;
&lt;p&gt;进程的基本特征：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;动态性：进程的实质是程序的一次执行过程，进程是动态产生，动态消亡的。&lt;/li&gt;
&lt;li&gt;并发性：任何进程都可以同其他进程一起并发执行&lt;/li&gt;
&lt;li&gt;独立性：进程是一个能独立运行的基本单位，同时也是系统分配资源和调度的独立单位；&lt;/li&gt;
&lt;li&gt;异步性：由于进程间的相互制约，使进程具有执行的间断性，即进程按各自独立的、不可预知的速度向前推进&lt;/li&gt;
&lt;li&gt;结构特征：进程由程序、数据和进程控制块三部分组成。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;进程之间的关系：同步和互斥&lt;/p&gt;
&lt;p&gt;m个进程访问临界资源，信号量的变化在1- （1-m）之间&lt;/p&gt;
&lt;p&gt;进程是由一个具有一定功能的程序关于某个数据集合的一次运行活动。&lt;/p&gt;
&lt;p&gt;调度的类型：
1.作业调度（也叫；宏观，高级，长程），是从外存调到内存然后进入竞争执行
2.进程调度（也叫：微观，低级，短程），取就绪状态的进程进入执行阶段
3.交换调度（也叫：中级，中程）是将外存中具备执行条件的进程调入内存或者相反&lt;/p&gt;
&lt;p&gt;调度的两种方法：1.剥夺方式，2.非剥夺方式&lt;/p&gt;
&lt;p&gt;进程调度的算法：1.先来先服务，2.最高优先权，3.时间片轮转，4.多级反馈。具体的课本上有。也可以看&lt;a href=&#34;http://www.cnblogs.com/fora/archive/2011/04/05/2006049.html&#34;&gt;此文&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;死锁的原因：1.资源不足。2.推进顺序不当&lt;/p&gt;
&lt;p&gt;形成死锁的必要条件：1.互斥，2.不剥夺。3.部分分配。4.环路等待。&lt;/p&gt;
&lt;p&gt;并非所有不安全状态就为死锁。但反之成立&lt;/p&gt;
&lt;p&gt;银行家算法其实很简单。就是规范化比较麻烦。&lt;a href=&#34;https://zh.wikipedia.org/zh-cn/%E9%93%B6%E8%A1%8C%E5%AE%B6%E7%AE%97%E6%B3%95&#34;&gt;看维基百科吧。&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;破坏资源互斥这个条件来避免死锁是不现实的。&lt;/p&gt;
&lt;p&gt;资源的按序分配
这种算法资源按某种规则系统中的所有资源统一编号（例如打印机为1、磁带机为2、磁盘为3、等等），申请时必须以上升的次序。系统要求申请进程：
1、对它所必须使用的而且属于同一类的所有资源，必须一次申请完；
2、在申请不同类资源时，必须按各类设备的编号依次申请。
这样申请的时候要么没有。要么全部分配，破坏了循环等待的条件&lt;/p&gt;
&lt;p&gt;调度算法中程序的相应比=1+等待时间/估计运行时间
操作系统提供给程序员的接口是系统调用
作业生存期的四个状态：1.提交。2.后备，3.开始，3.完成&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;转载请注明：http://leaver.me/archives/317.html&lt;/strong&gt;&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
