进程调度的功能 记录系统中的所有进程的状态、优先级数和资源的需求情况 确定调度算法,决定将CPU分配给哪个进程多少时间 分配处理机给进程,进行CPU现场的保护和移交 调度的层次 一个作业从提交开始直到完成,往往要经历以下三级调度,如图所示。 作业调度。又称高级调度,.其主要任务是按一定的原则从外存上处于后备状态的作业中挑选一个(或多个)作业,给它(们)分配内存、输入/输出设备等必要的资源,并建立相应的进程,以使它(们)获得竞争处理机的权利。简言之,就是内存与辅存之间的调度。对于每个作业只调入一次、调出一次。 多道批处理系统中大多配有作业调度,而其他系统中通常不需要配置作业调度。作业调度的执行频率较低,通常为几分钟一次。 中级调度。又称内存调度。引入中级调度是为了提高内存利用率和系统吞吐量。为此,应使那些暂时不能运行的进程,调至外存等待,把此时的进程状态称为挂起状态。当它们已具备运行条件且内存又稍有空闲时,由中级调度来决定,把外存上的那些已具备运行条件的就绪进程,再重新调入内存,并修改其状态为就绪状态,挂在就绪队列上等待。 进程调度。又称为低 继续阅读 >>


杜肖孟 17/05/03 21:11:07
信号量S的物理含义 S>0:表示有S个资源可用;S=0表示无资源可用;S<0绝对值表示等待队列或链表中的进程个数。信号量的初值应大于等于0。 PV原语小结 通过操作信号量来处理进程间的同步与互斥的问题。其核心就是一段不可分割不可中断的程序。 信号量是由操作系统来维护的,用户进程只能通过初始化和两个标准原语(P、V原语)来访问,它们在执行时是不可中断的。初始化可指定一个非负整数,即空闲资源总数。 P原语:P是荷兰语Proberen(测试)的首字母。为阻塞原语,负责把当前进程由运行状态转换为阻塞状态,直到另外一个进程唤醒它。操作为:申请一个空闲资源(把信号量减1),则若成功,则退出;若失败,则该进程被阻塞; V原语:V是荷兰语Verhogen(增加)的首字母。为唤醒原语,负责把一个被阻塞的进程唤醒,它有一个参数表,存放着等待被唤醒的进程信息。操作为:释放一个被占用的资源(把信号量加1),如果发现有被阻塞的进程,则选择一个唤醒之。 P(S):表示申请一个资源,S减 1;若 减1 后仍S> 继续阅读 >>


杜肖孟 17/05/02 21:22:06
指针、迭代器与const的关系 1. 如果关键字出现在星号左边,表示被指物是常量;如果出现在星号右边,表示指针自身是常量;如果出现在星号两边,表示被指物和指针两者都是常量。如果被指物是常量,把 const 写在类型之前或者类型之后、星号之前是一样的。 2. 迭代器的作用就像 T* 指针,const 在迭代器前,迭代器不能改变,即声明一个 T* const 指针;const 在迭代器变量前,迭代器所指变量不能变,即声明一个 const T* 指针,需要用 const_iterator。 vector<int> vec; const vector<int>::iterator iter = vec.begin(); //iter就像个T* const *iter = 10; //right ++iter; //iter不能变 vector<int>::const_iterator cIter = vec.begin(); //cIter 继续阅读 >>


杜肖孟 17/04/30 18:04:51
预处理器、编译器、汇编、链接 预处理器(cpp) C/C++的预处理器是最低端的一种—–词法预处理器,主要是进行文本替换、宏展开、删除注释、把头文件内容包含进来这类简单工作。 gcc -E选项可得到预处理后的结果,预处理结果会显示到屏幕上,如果需要保存,则得需要重定向,扩展名为 .i; C/C++预处理不做任何语法检查,不仅是因为它不具备语法检查功能,也因为预处理命令不属于C/C++语句(这也是定义宏时不要加分号的原因),语法检查是编译器要做的事情; 预处理之后,得到的仅仅是真正的源代码,输出一个hello world都有好几百行代码; GCC确实很强大,如果是用VC这种IDE,恐怕就不能看到预处理后的结果。 编译器(ccl) 将文本文件 .i 翻译成文本文件.s,得到汇编语言程序(把高级语言翻译为机器语言),该种语言程序中的每条语句都以一种标准的文本格式确切的描述了一条低级机器语言指令。 gcc -S 选项可以得到编译后的汇编代码,扩展名为 .s; 汇编语言为不同高级语言的不同编译器提供了通用的输出语言,比如,C编译器和Fortra 继续阅读 >>


杜肖孟 17/04/30 12:28:46
视C++为一个语言联邦 今天的C++已经是个多重范型编程语言,同时支持过程形式、面向对象形式、函数形式、范型形式、元编程形式。为了理解C++,必须认识其主要的次语言,总共有四个: 1. C。C++以C为基础,语句、预处理、内置数据类型等来自C,但C没有模板、没有重载…… 2. Object-Oriented C++。面向对象C++,class、封装、继承、多态、虚函数等 3. Template C++。C++范型编程 4. STL。标准模板库,对containers、iterators、algorithms以及function objects的规约有极佳的紧密配合与协调 尽量以const,enum,inline 替换 #define 现在我们写这样一个宏定义 #define Aspect 1.653 #define 不是语言的一部分,是预处理阶段完成的,没有到编译器,因此 #define定义的记号名称也就没有进入符号表(symbol table)。当我们因为运用#define定义的常量而发生编译错误时,那么会很浪费时间来追踪它。解决方法是 继续阅读 >>


杜肖孟 17/04/29 16:23:27
声明 今年的免试题按照关卡顺序依次是由小组15级成员何攀、楚东方、宫展京、杜肖孟、王一妃同学精心准备的(鼓掌),每个人总结了一下自己负责关卡的解法,我这里整理了一下,给出一套完整的免试题详解,免试题通过方法不唯一哦,想分享的可以留言。文末附上小组前几年的免试题详解,感兴趣的同学可以参考着玩一下。Let’s go! 第一关 免试题链接:点此进入 ,进去之后会有如下页面映入眼帘: 首先,我们看到的是一段代码(运行结果是 11,代表着我们小组成立 11 周年)和一段关于 π 的视频,在欣赏完这曲美妙的钢琴曲后发现并没有什么其他的信息了,然后我们应该想到查看网页源代码(Ctrl+u 或 F12),然后会发现在网页源代码里有一个压缩包文件,如下图: 把这个压缩文件 XiyouLinuxGroup.zip 下载下来后,发现这个压缩包是加密的,然后我们应该想到这个密码肯定隐藏在这个网页的某个地方,这时候应该想起网页上的那段代码和视频,那这个代码的运行结果 11 与关于 π 的视频和那个压缩包的密码有什么联系呢?我们都知道 π 是一个无限不循环小数,所以密码 继续阅读 >>


杜肖孟 17/04/28 20:46:50
最近在看 UNIX 网络编程并研究了一下 Redis 的实现,感觉 Redis 的源代码十分适合阅读和分析,其中 I/O 多路复用(mutiplexing)部分的实现非常干净和优雅,在这里想对这部分的内容进行简单的整理。 几种 I/O 模型 为什么 Redis 中要使用 I/O 多路复用这种技术呢? 首先,Redis 是跑在单线程中的,所有的操作都是按照顺序线性执行的,但是由于读写操作等待用户输入或输出都是阻塞的,所以 I/O 操作在一般情况下往往不能直接返回,这会导致某一文件的 I/O 阻塞导致整个进程无法对其它客户提供服务,而 I/O 多路复用就是为了解决这个问题而出现的。 Blocking I/O 先来看一下传统的阻塞 I/O 模型到底是如何工作的:当使用 read 或者 write 对某一个文件描述符(File Descriptor 以下简称 FD)进行读写时,如果当前 FD 不可读或不可写,整个 Redis 服务就不会对其它的操作作出响应,导致整个服务不可用。 这也就是传统意义上的,也就是我们在编程中使用最多的阻塞模型: 阻塞模 继续阅读 >>


杜肖孟 17/04/16 16:21:00
我们学习高级进程通信,指用户可直接利用操作系统所提供的一组通信命令高效地传送大量数据的一种通信方式。 进程间通信的几种主要手段:管道、消息队列、共享内存、套接字 管道 管道,指用于连接一个读进程和一个写进程以实现它们之间通信的一个共享文件,只存在于内存中,是一种两个进程间进行单向通信的机制。在创建管道时,系统为管道分配一个页面作为数据缓冲区,通过管道通信的两个进程通过读写这个缓冲区来进程通信,写在缓冲区尾部,从头部读取数据。 局限性: 数据单向传递,即半双工;管道没有名字,只能用于具有亲缘关系的进程间通信;管道的缓冲区大小受限制;管道传送的是无格式的字节流。 管道的创建: int pipe(int fd[2]) //调用成功返回0,且数组中包含两个新的fd,失败返回-1 管道两端分别用fd[0]和fd[1]描述,管道两端的任务固定,fd[0]只能用于读,称为管道读端;fd[1]只能用于写,称为管道写端。 管道一旦创建成功,就可以作为一般的文件来使用,对一般文件进行操作的I/O函数也适用于管道。 管道的读写:如果某进程要读取管道中 继续阅读 >>


杜肖孟 17/04/16 13:42:11
net_speeder??? 同一份数据包发送两份。这样的话在服务器带宽充足情况下,丢包率会平方级降低。 直接优点是降低丢包率,直接缺点是耗费双倍流量。一些延伸影响是更容易触发快速恢复逻辑,避免了丢包时窗口缩减过快。一定程度也能提高网络速度。 安装过程 1:下载源码并解压 wget https://github.com/snooda/net-speeder/archive/master.zip unzip master.zip 2:准备编译环境 debian/ubuntu: #安装libnet-dev: apt-get install libnet1-dev #安装libpcap-dev: apt-get install libpcap0.8-dev centos: #下载epel:https://fedoraproject.org/wiki/EPEL/zh-cn 例:CentOS6 64位: wget http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noa 继续阅读 >>


杜肖孟 17/04/05 14:00:26
进程内存布局 每个进程分配的内存由很多部分组成,通常称为“段”。 1.文本段:包含了进程运行的程序二进制机器语言指令,只读,可共享,因为多个进程可同时运行同一程序; 2.初始化数据段:包含显式初始化的全局变量和静态变量; 3.未初始化数据段:也称为BSS段,包含未进行显示初始化的全局变量和静态变量。为什么分开放呢?主要原因在于程序在磁盘上存储时,没有必要为未经初始化的变量分配存储空间,相反可执行文件只需记录未初始化数据段的位置及所需大小,直到运行时再由程序加载器来分配这一空间。 4.栈段:动态增长和收缩的段,由栈帧组成,系统会为每个当前调用的函数分配一个栈帧,存储函数的局部变量、实参和返回值。动态存储函数之间的关系,以保证被调用函数在返回时恢复到母函数继续执行 5.堆:可在运行时为变量动态进行内存分配的一块区域,并在用完之后归还给堆区。 32位计算机限制了虚拟地址空间为4GB的大小。 栈与系统栈 栈在内存中的存放是高地址是栈底,低地址是栈顶。 内存的栈区实际上指的就是系统栈,系统栈由系统自动维护,它用于实现高级语言中函数的调用。对于类似 继续阅读 >>


杜肖孟 17/03/28 21:28:26