文章略长。。。 Demo下载:Demo.Threading.zip 介绍 本文将通过一些例子来展示.net 中如何实现多线程,涉及到以下四部分。 1 .线程概念 2 .如何实现多线程 3 .如何确保线程安全 4 .死锁
什么是进程 一个进程就是一个可执行文件运行的操作系统上下文环境。它被用来分隔虚拟地址空间,线程,对象句柄(指向类似文件这样的资源的指针),以及环境变量,进程还有一些类似优先级类和最大内存分配的属性。
也就是说: 1 .一个进程就是一个包含资源的内存块。 2 .操作系统执行的一个单独的任务。 3 .一个正在运行的软件 4 .一个进程拥有一个/多个操作系统线程
一般的。一个进程最大可以是4GB的内存空间,这块内存是安全,私有,其他进程是无法访问的。
什么是线程 一个线程就是在一个进程里执行的一条指令流,所有的线程都在一个进程里执行,也就是一个进程可以包含多个线程。线程公用进程的虚拟地址空间。线程是操作系统的调度单元。一个线程的上下文由操作系统进行保存/恢复。 也就是说: 1 .一个线程是进程里的一条指令流。 2 .所有的线程在进程里。一个进程可以有多个线程 3 .一个进程的所有线程使用进程的虚拟地址空间。
什么是多线程 多线程指的是进程同时有多个线程活动。这可以通过时间片的线程模拟或是多cpu上的超线程来实现。可以提高性能。 多线程-为什么或是为什么不? 为什么多线程 1 .保持UI响应。 2 .提高性能(对于cpu密集型和I/O密集型的进程) 为什么不多线程 1 .过度使用降低性能 2 .代码复杂,增加设计时间,潜在的bug
线程池 线程池为你的程序提供了一个由操作系统管理的机制。在线程池里的都是后台线程。一个线程池线程在程序的前台线程都退出后,也会推出。每个进程一个线程池。默认情况下。每个处理器会为进程分配25个线程。但是可以通过SetMaxThreads 方法来改变。
.net 中的线程 在.net 中,线程可以通过下面6个方法来实现。 1 .Thread线程类 2 .Delegates委托 3 .Background Worker 4 .ThreadPool 线程池 5 .Task任务类 6 .Parallel并行类
下面的几部分里。我将逐一展示实现方法。
简而言之,多线程就是通过使程序同时运行多个任务来最大化计算机能力,同时能够保持UI响应。下图是一个例子的图示。
代码 提供的源码是一个简单的WinForm程序。模拟了.net中委托,线程类和Background Worker三种方法。 程序异步执行一个繁重的操作,这样UI就不会无响应。三个方法都是模拟的。
这个“繁重”的操作 真实的开发中,这个繁重的操作从轮询数据库到流媒体操作都可以。基本上可以是任何事情。源码里面是向一个字符串追加值。String是不能变的。追加的时候,新的字符串变量会被创建,旧的会被丢弃,这是由CLR处理的。如果做很多次这个操作,是很耗资源的。这也是为什么我们使用Stringbuilder.Append 来代替这个操作。通过调整界面中的次数。可以通知追加的次数。
后面我们有一个Utility泪,有一个LoadData() 方法。类里面也有一个和LoadData() 有着同样签名的委托
同步调用 当点击Get Data Sync按钮的时候。操作和UI在同一个线程里,因此阻塞了UI线程。因此。UI线程会未响应
异步调用 使用委托(异步编程模型)
如果你选择了“Delegates”单选按钮,那么LoadData()方法就会通过使用委托来异步调用。首先通过utility.LoadData(). 的地址初始化delLoadData 类型,然后调用委托的BeginInvoke()方法。在.net的世界里。任何一个有着BeginXXX和EndXXX名字的方法都是异步的。比如delegate.Invoke()将会在同一个线程里调用方法。而delegate.BeginInvoke()则会另开一个线程调用。 BeginInvoke()有三个参数 1 .传递给Utility.LoadData()方法的参数 2 .回调方法的地址 3 .对象的状态
回调 一旦我们开了一个线程执行一些操作,我们就想知道操作正在发生些什么,换句话说。我们需要当操作完成的时候我们能够收到通知。有三种方法可以知道一个操作是否完成。 1 .回调 2 .轮询 3 .等待直到完成 在我的源码里,我们使用回调方法来捕获线程的完成。回调只需要在调用BeginInvoke的时候把回到函数的名字传递进去。这会告诉线程当你做完工作以后调用这个回调方法就好了。
一旦一个独立线程里的一个方法启动。你也许关心也许不关心方法的返回值,如果一个方法没有返回值,那么可以叫做“触发然后忘记的调用”,这种情况下就不需要回调函数了。这里callback直接传入null就可以了。
在我们的例子中,我们需要一个回调方法,因此,哦们需要传递回调方法的名字到参数里。这里我们的回调方法的名字就叫做CallBack(),纯属巧合。
回调方法的签名都是void MethodName(IAsyncResult asyncResult). IAsyncResult包含了关于线程的一些必要的信息,返回的数据可以像下面这样提取。
而轮询的方法(本例没有使用)则是像这样
等待直到完成,如名所示,就是等待直到完成。
更新UI 既然我们已经捕获了操作结束,并且取回了LoadData()的结果。我们需要用结果来更新UI,但是有个问题。文本框需要在UI线程里更新,结果在回调里取到了。回调和他启动的时候是一个线程(他是由新开的线程启动的)。因为UI线程和回调不是同一个线程。换句话说。文本框不能像下面这样更新。
回调里执行这一行将会导致一个跨线程的系统异常。我们需要在后台线程和Ui线程之前构建一个桥。来更新文本框的值。可以通过使用Invoke()或是BeginInvoke()方法。 我定义了一个方法来更新UI
对上面的方法定义一个委托
如下调用BeginInvoke()方法。
需要注意的是一旦一个线程通过委托启动。它就不能取消,暂停,或是终止,我们无法控制那个线程。
使用Thread线程类 同样的操作可以是哟哦那个Thread类来完成。这个类的优点是你可以对操作有更多的控制,比如暂停/取消操作,类在System.Threading命名空间里。 我们有一个私有的方法LoadData(),他是Utility.LoadData()方法的一个包装。
这样做是因为 Utility.LoadData() 需要一个参数。而我们需要一个ThreadStart委托,这个委托没有参数。
这个委托没有参数,为了防止我们需要传递参数,我们可以使用有参的ThreadStart委托,不幸的是,这个委托只能把object作为参数,而我们需要一个字符串所以需要类型转换。
是的。Thread泪可以对线程有更多的控制。中断。终止,获取线程状态。 使用BackgroundWorker 这个类是一个组件,可以使得线程使用更简单,这个BackgroundWorker类的主要特点就是可以异步的报告进度,这就可以用来更新状态栏,保持UI可视化的更新进度 为了完成操作,我们需要把下面两个属性设置为true,缺省时false • WorkerReportsProgress • WorkerSupportsCancel
这个类有三个主要的事件DoCount, ProgressChanged, RunWorkerCompleted 初始化的时候需要注册这三个事件
利用反射转换对象list到csv
扒自一工程。。可以学习一下.net中反射的简单用法
增加这个只是两个预定义的实体框架内的属性。
使用PropertyInfo 可以获得名字。数据类型。声明类型,反射类型,读写属性等等。也可以设置或获取属性值。
操作系统的死锁和内存管理
这部分是最后一部分笔记。《现代操作系统》第三版的笔记就这样了。 死锁; 把需要排他性使用的对象称为资源,资源分为可抢占的和不可抢占的。可抢占资源可以从拥有它的进程中抢占而不会具有任何副作用。存储器就是可抢占的。不可抢占资源是指在不引起相关的计算失败的情况下,无法把它从占有她的进程处抢占过来。比如CD刻录机,如果一个进程开始刻盘,突然分配给CD刻录机到另一进程,就会划坏CD盘。死锁会发生在不可抢占资源中 死锁的规范定义:如果一个进程集合中的每个进程都在等待只能由该进程集合中的其他进程才能引发的事件,那么,该进程集合就是死锁的。
死锁的四个必要条件 1.互斥条件。每个资源要么已经分配给一个进程,要么就是可用的。 2.占有和等待条件,已经得到了某个资源的进程可以再请求新的资源。 3.不可抢占条件,已经分配给一个进程的资源不可强制性的被抢占,他只能由占有她的进程显式的释放。 4.环路等待条件。死锁发生时,系统中一定有友两个/多个进程组成的一条回路,该环路中的每个进程都在等待着下一个进程所占有的资源。
死锁处理的四种策略 1.忽略该问题,如果可以忽略。则忽略 2.检测死锁并恢复,让死锁发生,检测他们是否发生,一旦发生。采取行动。 3.仔细对资源进行分配。动态的避免死锁。 4.通过破坏引起的四个必要条件之一。防止死锁发生。
银行家算法就是对每个请求进行检查。检查如果满足这一请求是否会达到安全状态,或是,那么满足这请求,若否。就推迟这一请求的满足。为了看状态是否安全。类似于银行家投资。看自己是否有足够的资源满足客户。如果可以。就认为投资是可以收回的。接着检查最接近最大限额的一个客户。如果所有投资最终都被收回。则该状态安全。
通信死锁:两个/以上的进程发送消息通信。A向B发送请求信息,然后阻塞直到B回复。假设请求信息丢失,A将阻塞等待回复。B则阻塞等待一个向其发送命令的请求。则发生死锁。他不能通过对资源排序/安排调度来避免,因此。采用了超时来中断通信死锁。
活锁:两个进程A和B,A获得1.B获得2.轮询请求对方的。没有进程被阻塞。看起来像是死锁发生了。就叫做活锁。
内存管理 每个linux进程都有一个地址空间,逻辑上有三段组成:代码。数据和堆栈段。代码段包含了形成程序可执行代码的机器指令。通常是只读的。是由编译器把源码转换成机器码形成的。 数据段包含了所有程序变量。字符串。数字和其他数据的存储。由两部分,初始化数据和未初始化数据。后者即为BSS,符号起始块。加载后被初始化为0.数据段可以修改。可以增加数据段的大小。 第三段是栈段。大多数机器里。从虚拟地址空间的顶部/附近开始。并且向下生长。
linux内存由三部分组成。前两部分是内核和内存映射,被钉在内存中。页面从不换粗。内存的其他部分,被划分为页框。每个页框都可以包含一个代码。数据或栈页面。
window如何知道系统配置的细节呢。答案就是windows会挂载一种特殊的文件系统,其为小文件做了优化,到名字空间,也就是注册表。注册表被阻止成了不同的卷,称作储巢。hive。一个叫做system的储巢会在系统启动时。装入内存。这里面包含了驱动什么设备工作。什么软件要初始化。那些变量等等。
recon-ng开源信息探测框架
作者:bystander 博客:http://leaver.me 微博:http://t.qq.com/lazystander 论坛:法客论坛
首发。转载什么的请注明出处。起码给我留个链接啥的嘛。
首先介绍一下。这个工具是国外刚刚发布的。主要用来渗透前的信息探测。使用类似Metasploit 主要有 Auxiliary: 这个模块查询主机信息泄漏页。进行hash反查,模糊名称精确,检查某个email是否密码泄漏,域名解析ip等 Contacts: 这个模块探测和某一公司有关的人员的信息,主要包括 LinkedIn 和Jigsaw 这两个模块。得到的信息可以被Auxiliary模块使用,如果和Social Engineer Toolkit(社会工程学工具集,这个工具已经发布了。是开源的。大家可以看看),一起。效果强大。
Hosts: 这个用来获取站点子域名。。包括使用baidu。Google bing等。。效果相当强大。 Output: 这个模块用来创建输出报表 Pwnedlist: 这个模块不是得shell的。他可通过 Pwnedlist.com 提供的api,如果这个网站被入侵过。那么可以直接获得其他黑客泄漏的帐号密码。。(需要去 Pwnedlist.com 注册)
安装方法: bt下直接
然后有可能提示输入密码,好象是随便输一个用来保护版本控制。。我输的是toor。。 然后就安装好了。输入
然后
首先查看有哪些模块。输入
图一
我以获取子域名为例,通过我前面的介绍你已经知道了hosts模块里的所有模块基本都是干这事的。我用里面的baidu模块来说明。你也可以使用bing等,,
输入命令
图二
刚开始你可能不清楚这个模块的说明。那么继续输入info即可查看模块的详细说明 要开始使用。我们输入
和Metasploit很像把。可以查看要使用需要的配置。
图三
看表,会发现有三行。第一行是标题,第二行是域名设置,第三行是输出。这个current value也就是当前值已经为true。所以不用设置。req的意思是是否必须设置。我们输入 baidu.com就是你的目标了。
就会从百度的结果里提取百度的子域名信息了。要开始。我们输入
图四
更多希望大家发掘吧。我抛砖。求引玉。
操作系统中的输入输出
输入输出 I/O硬件: I/O设备分为两类:块设备和字符设备,块设备吧信息存储在固定大小的块中,每个块有自己的地址,传输以块为单位,每个块都能独立于其他块读写,硬盘,CD-ROM和USB盘都是常见的块设备。字符设备是以字符为单位发送和接收一个字符流,而不考虑任何块结构,字符设备不可寻址,也不寻道,打印机,网络几口,鼠标,以及大多数与磁盘不同的设备都可看作是字符设备。
I/O设备一般由机械部件和电子部件两部分组成,通常分开处理,实现模块化和通用设计,电子部件称作设备控制器/适配器,在个人计算机上,通常以主板上的芯片的形式出现,或者以插入PCI的印刷电路板的形式出现。控制器卡上通常有一个连接器,通向设备本身的电缆可以插入到这个连接器中, 控制器的任务是吧串行的位流转换成字节块,并进行必要的错误校正工作,字节块通常首先在控制器内部的一个缓冲区中按位进行组装,然后再对校验和进行校验并证明字节块没有错误后再将它复制到主存中。
每个控制器都有几个寄存器用来和cpu通信,通过写入这些寄存器,操作系统可以命令设备发送数据等等操作。 1.内存映射io 将所有控制寄存器映射到内存空间中,每个寄存器被分配一个唯一的内存地址,并且不会有内存被分配这一地址,这样的系统称为内存映射I/O,通常位于地址空间的顶端。使用内存映射io,设备控制器只是内存中的变量,c语言可以和其他变量一样寻址,这样,I/O设备驱动程序就可以采用c语言编写。 2.DMA 无论CPU是否具有内存映射I/O,他都需要寻址设备控制器以便和他们交换数据,但浪费eficpu时间,所以经常使用直接存储器存储。可独立于cpu访问地址总线。
没有DMA的时候,首先控制器从磁盘驱动器串行的一位一位的读一个块,直到将整块信息放入控制器的内存缓冲区中,接着,他计算校验和,以保证没有读错误发生,然后控制器产生一个中断,当操作系统开始运行时,它重复地从控制器的缓冲区中一次一个字节/一个字的读取该块的信息,并将其放入内存中。 当有DMA的时候,首先CPU通过设置DMA控制器的寄存器对它进行编程,所以DMA控制器知道将什么数据传送到什么地方,(第1步)DMA控制器还要向磁盘控制器发送一个命令,通知他从磁盘读数据到其内部的缓冲区中,并且对校验和进行检验,如果磁盘控制器中的缓冲区中的数据是有效的的。那么DMA开始 DMA控制器通过在总线上发出一个读请求到磁盘控制器而发起DMA传送(第2步),这一读请求和其他一样,并且磁盘控制器并不关心是来自DMA还是CPU,一般情况下,要写的内存地址在总线的地址线上,所以磁盘控制器从内部缓冲区中读取下一个字的时候,她知道要写的什么地方,写到内存是另一个标准总线周期,(第3步) 当写操作完成时,磁盘控制器在总线上发起一个应答信号到DMA(第4步),于是DMA控制器部增要使用的内存地址,并且步减字节计数,如果字节计数仍然大于0,则从父2-4步。完成后产生中断告诉cpu,操作系统开始工作时,数据已经在内存中了。 中断: 将机器留在一个明确状态的中断称为精确中断,四个特征,1.PC保存在一个已知的地方。2.PC所指向的指令之前的所有指令都已经完全执行。3.PC所指向的指令之后的所有指令都没有执行。4.PC所指向的指令的执行状态是已知的。注意,对于PC所指向的指令以后的指令,并没有禁止他们开始执行,而只是要求在中断发生之前必须撤销他们对寄存器或内存所做的任何修改。 I/O软件: 设计I/O软件时一个关键的点就是设备独立性,意思是我们可以访问任意I/O设备而无需事先指定设备。也就是对于不同的I/O硬件。同一段程序是可以的。
具有标准接口的驱动程序的工作方式如下:对于每一种设备类型,例如磁盘和打印机。操作系统定义一组驱动程序必须支持的函数,对于磁盘而言,这些函数自然的包含读和写,除此之外还包含开启和关闭电源,格式化以及其他与磁盘有关的事情。驱动程序通常包含一张表格,这张表格具有针对这些函数指向驱动程序自身的指针。当驱动程序装载时,操作系统记录下这张函数指针表的地址。所以当操作系统需要调用一个函数时,可以通过表格发出间接调用。这张函数指针表定义了驱动程序与操作系统其他部分之间的接口。
**双缓冲:**当第二个缓冲区正在复制用户空间的时候,第一个缓冲区用来接收新的字符。以这样的方法。两个缓冲区轮流使用。称为双缓冲。
磁盘臂调度算法: 读/写一个磁盘块需要时间:1.寻道时间(将磁盘臂移动到适当的柱面上所需的时间)2.旋转延迟(等待适当扇区旋转到磁头下所需的时间)。3.实际数据传输时间。
一个磁盘子系统具有如下特性:当一个写命令发给它时,磁盘要么正确地写数据,要么什么也不做,让现有的数据完整无缺的留下,这样的系统称为稳定存储器,并且是在软件中实现的。目标是不惜一切代价保持磁盘的一致性。
**时钟:**两种。1种是直接接到电源线上。就可以每个电压周期产生一个终端。现在比较少。另一种是由晶体振荡器,计数器和存储寄存器三个构成。当把一块石英晶体适当的切割并且安装到一定的压力之下时就可以产生非常精确的周期性信号。时钟启动时,存储寄存器的值被复制到计数器中,每一个脉冲使计数器-1,直到为0,产生中断。
操作系统中的文件系统
文件系统 进程,地址空间,文件这些抽象概念均是操作系统中的重要概念,如果理解了这三个概念,就迈上了成为一个操作系统专家的道路。 文件系统存放在磁盘上,多数磁盘划分为一个/多个分区,每个分区有一个独立的文件系统,磁盘的0号扇区称为主引导记录,也就是MBR,用来引导计算机,MBR的结尾就是分区表了。该表给出了每个分区的起始和结束地址。表中的一个分区被标记为活动分区。在计算机被引导时,BIOS读入并执行MBR,MBR做的第一件事就是确定活动分区,读入他的第一个块,称为引导块,并执行之,引导块中的程度将装载该分区中的操作系统,为统一起见,每个分区都从一个启动块开始,即使它不含有一个可以启动的操作系统。 文件的实现: 1.连续分配,每个文件作为一连串连续数据存储在磁盘上。实现简单,读操作性能好,一次就可以了。但不足是删除之后不能移动,因为成本太高,使得空块增多。碎片化严重。更诡异的是对于文件编辑软件,实现无法准确预测大小,如果预测错了。。就跪了。 //研究那些具有清晰和简洁概念的老式系统和思想是很重要的,因为他们可能以一种令人吃惊的方式在未来系统中获得应用。
2.链表分配 为每个文件构造磁盘块链表,一个文件分为N个文件块,N个文件块构成一个链表,存储在物理上的多个地方。顺序读取很方便,但随机读取则相当缓慢,由于指针的存在,每个磁盘块存储数据的字节不再是2的整数次幂,导致系统运行效率降低,因为很多程序都是以2的整数次幂来读写磁盘的。
3.在内存中采用表的链表分配 去除每个文件块在磁盘上的指针字,放入内存的一个表上,就可以解决上一个分配的不足。直观的例子如图。 文件A使用了磁盘块4,7,2,10,12
内存中这样的表格称为文件分配表,也就是FAT了。主要缺点是对于大磁盘的小块,这种表需要的内存占用太大。。不太适用。
4.i节点 记录各个文件包含哪些磁盘块的方法是给每个文件赋予一个称为i节点的数据结构,其中类除了文件属性和文件块的磁盘地址.相对于在内存中采用表的方式,这种机制的优势在于只有对应文件打开时,其i节点才进入内存.
文件系统的一致性检查分为两种:块的一致性检查和文件的一致性检查.构造两张表,一张跟踪块在文件中的出现次数,另一张跟踪该块在空闲表中的出现次数,如果一致,则某一块必然在两个表中1/2中为1,如果某一块没有出现在任何一张表中,则称为块丢失,浪费了磁盘空间.解决方法是让文件系统检验程序把他们加入到空闲表中 如果在空闲表中出现了两次.则重新建议建议空闲表即可. 如果在文件表中出现了两次.则比较麻烦.
文件系统性能 1.高速缓存,最常用,指的是一系列的块,逻辑上属于磁盘.但实际上被保存在内存上.基本算法是检查全部的读请求,查看在高速缓存中是否有所需要的块,如果存在,就读,否则读入高速缓存在复制到其他地方. 2.块提前读,在需要用到块之前,试图提前将其写入高速缓存,从而提高命中率.比如某个文件有n个块,则请求k块的时候,则同时预读k+1块.只适用于顺序读取的文件,对随机读取文件,则没有效果/反效果. 3.减少磁盘臂运动 把所有可能顺序读取的块放在一起,当然最好是放在同一个柱面上,从而减少磁盘臂的移动次数.
操作系统中的页面置换算法
页面调度算法总结; 最好的两种算法是老化算法和工作集时钟算法,分别基于LRU和工作集。具有良好的页面调度性能。
C# 基础知识系列文章索引
清理GR的加星标项目。分享来自博客园 zhili 的C#基础系列文章。
C#基础知识系列终于告了一个段落了, 本系列中主要和大家介绍了C#1.0到C# 4.0中一些重要的特性,刚开始写这个专题的初衷主要是我觉得掌握了C#这些基础知识之后,对于其他任何的一门语言都是差不多的,这样可以提高朋友们对其他语言的掌握,以及可以让大家更加迅速地掌握.NET的新特性, 并且相信这个系列对于找工作的朋友也是很有帮助的,因为很多公司面试都很看重基础知识是否扎实,是否对C#有一个全面的认识和理解,所以很多公司面试都会问到一些C#基础概念的问题,例如,经常面试会问:你是如何理解委托的,如何理解匿名函数等问题。
然而这个系列中并没有介绍COM互操作性的内容以及.Net 4.5中的一些新特性,所以后面将会对这两个方面的内容进行补充,由于这个系列托的太久了(大概也有3个月吧),所以就先告一段落的,后面将会带来.NET互操作性系列的介绍。下面就为这个系列文章做一个索引,方便大家收藏和查找。
C#基础知识系列索引
C#1.0
1. 深入解析委托——C#中为什么要引入委托
2. 委托本质论
3. 如何用委托包装多个方法——委托链
4. 事件揭秘
5. 当点击按钮时触发Click事件背后发生的事情
C# 2.0
6. 泛型基础篇——为什么引入泛型
7. 泛型深入理解(一)
8. 泛型深入理解(二)
9. 深入理解泛型可变性
10. 全面解析可空类型
11. 匿名方法解析
12. 迭代器
C# 3.0
13. 全面解析对象集合初始化器、匿名类型和隐式类型
14. 深入理解Lambda表达式
15. 全面解析扩展方法
16. Linq介绍
C# 4.0
17. 深入理解动态类型
从C#的所有特性可以看出,C#中提出的每个新特性都是建立在原来特性的基础上,并且是对原来特性的一个改进, 做这么多的改进主要是为了方便开发人员更好地使用C#来编写程序,是让我们写更少的代码来实现我们的程序,把一些额外的工作交给编译器去帮我们做,也就是很多人说微软很喜欢搞语法糖的意思(语法糖即让编译器帮我们做一些额外的事情,减少开发人员所考虑的事情,使开发人员放更多的精力放在系统的业务逻辑上面。),大家从C# 3中提出的特性中可以很好的看出这点(指的是玩语法糖),C#3中几乎大部分特性都是C#提供的语法糖,从CLR层面来说(指的是增加新的IL指令),C# 3并没有更新什么,C# 4中提出的动态类型又是建立在表达式树的基础上,包括Linq也是建立在表达式树的基础上,所以每个特性都是层层递进的一个关系。相信C#后面提出的新特性将会更加方便我们开发程序,感觉所有语言的一个统一的思想都是——写更少的代码,却可以做更多的事情。但是我们不能仅仅停住于知道怎么使用它,我们还应该深入研究它的背后的故事,知道新特性是如何实现的和原理。用一句说就是——我们要知其然之气所以然,学习知识应该抱着刨根问底的态度去学习,相信这样的学习方式也可以让大家不感到心虚,写出的程序将会更加自信。
现代操作系统的调度
这几天在读《现代操作系统》,想起当时学这门课的时候,并没有感觉那么爽,现在通读这本书,知识的过渡性和结构性令我叹服。感受操作系统的魅力吧。
批处理系统中的调度: 1.先来先服务
2.最短作业优先 只有在所有的作业都可以同时运行(也即同时到达)的情况下,最短作业优先算法才是最优化的。
3.最短剩余时间优先-最短作业优先的抢占式版本。调度算法总是选择剩余时间最短的那个进程运行,注意,运行时间必须提前掌握,当一个新的作业到达时,其整个时间同当前进程的剩余时间做比较,如果更少。就运行新进程。可以使新的短作业获得良好的服务。
交互式系统的调度 1.轮转调度。 最古老,最简单,最公平切使用最广,每个进程被分配一个时间片。如果进程在时间片结束之前阻塞或结束,则CPU立即切换。调度程序只是维护一张可运行进程列表,当进程用完它的时间片后,就被移到队列的末尾。时间片太短会导致进程切换过多,降低CPU效率,设置的太长又引起对短的交互请求的响应时间变长。通常20-50ms算合理。
2.优先级调度 为了防止高优先级进程无休止的运行下去,可以在一个时钟中断里降低当前进程的优先级,如果这导致该进程的优先级低于次高优先级的进程,则切换或者也可以赋予每个进程一个时间片。可以和轮转调度一起工作,设置每个优先级上有多个进程。优先运行高优先级,并未高优先级上的进程按照轮转换着运行,如果高优先级没了。就进入到较低优先级。。。问题是如果不偶尔对优先级进行调整,则可能发生饥饿现象。
3.多级队列 CTSS的设计者发现为CPU密集型进程设置较长的时间片比频繁的分给他们很短的时间片更为高效(减少了交换次数),但长时间的进程又会影响响应时间,方法是设立优先级类,最高优先级类里的进程运行1个时间片。次高运行2个。以此类推。当一个进程用完分配的时间片后,被移动到下一类。大致算法都是用于讨好交互用户和进程,而不惜牺牲后台进程 //故事:可以采用只要终端上有Enter键按下,就将该终端上的进程移到最高优先级类。假设当前进程急需交互,但是。一个人发现了。大家都开始用。。。理论和实际差异太大。。哈哈
4.最短进程优先 这个很好立即,但难点在于如何找出最短的那个。一种方法是根据过去的行为推测。假设每个命令执行时间为T0,下一次运行时间为T1,则可以根据aT0+(1-a)T1来估计时间。。a被用来决定尽快忘掉老的运行时间还是记住它。这种算法成为老化算法。通常选a=1/2
5.保证调度 就是保证每个用户获得cpu的1/n,系统需要跟踪进程的cpu时间,他实际获得如果多于应该获得的。则转向实际获得小于应该获得的。
6.彩票调度 保证调度很难实现,而彩票调度算法是向进程提供各种系统资源的彩票。一旦需要做出一项调度决策时,就随机抽出一张彩票。谁获得谁就上。比如视频服务器,可以为不同的帧速率提供不同的彩票。然后分配cpu
7.公平分享调度 这个就考虑到了进程的所有者。需要我们定义公平的含义。是保证每个用户只占用的时间相等还是其他了。
实时系统的调度: 可以分为硬实时和软实时,前者必须满足绝对的截止时间,后者则可以容忍一些。用户级线程系统是不知道的。用户级和内核级的差异主要在性能,用户级需少量的机器指令,而内核级需要很多的。过程。采用轮转和优先级调度更常见一些。
//操作系统的大神们太强大了。哲学家进餐问题居然可以通过拿起左边叉子以后,检测右边是否可用,如果不可用,则等待一个随机的时间。这种方案是可行的。在极少的情况下不可用。。
不要变成你讨厌的人,面目可憎
本文来自xjp的碎碎念,我很喜欢的一个博主。博客已被伟大的GFW屏蔽。和文章的主题类似,我有时候会在G+上会纠正一些人的谣言,并且给出澄清,可是,往往效果不大。我的态度很简单,你要反对一样东西,请你不要是那样的东西。或用那样的东西去反对。不要为任何主义所迷惑,你要做好一个人。
今天看到一篇来自《新京报》的报道,称时事评论员@周筱赟爆料称,根据铁道部的两份采购合同显示,推测铁道部12306订票网站实际投入已经超过5亿元,而不是之前曾披露的3.2亿元。
首先我很赞同周筱赟所做的事情,在国内目前民众获取信息渠道有限的情况下,有这样的热心人士去披露政府部门行政行为中值得讨论的部分,对于整个社会的公正与透明都有极大的推动作用。
但我注意的是另一群人,他们典型的回复是:
1、花5个多亿做成这么垃圾的网站,铁道部公然贪污多少钱?臭不要脸的!二逼的网站和系统归功于傻逼造就!
2、卧槽,里面有4.5亿是贪污款吧
3、习总说反腐,最大的蛀虫在这里,敢反否?
4、3亿建站为什么这些年一直没有工商部去追查12306的贪污问题。你懂我懂大家懂。
5、中央纪委、监察部和各级纪检监察机关要加大检查监督力度,执好纪、问好责、把好关。
6、太极集团是做医药的呀,怎么也搞起软件来了。我想说,有没经验都不要紧,要紧的是有钱。咱就撒都能做!
7、五亿······· 用了个500的模版 月薪5000水平的制作团队
8、三億各單位部門宣傳費,一億三公支出,五千萬采購合同草擬費用,四千萬給媒體掩口費, 九百九十萬信息產業部備案費用,最後十萬才是網站制作費用… 這五億基本上都使對了地方,沒有錯啊! 其它的评论都是诸如此类,某一些理性的评论都被深埋其中。
我不是铁道部、太极的任何一方,我不能拍着胸脯说这些问题一定不存在,但真正让我恐惧的是,有大量网友没有认真去研究文章的内容与事实,只是单纯下意识地做出了判断,然后开喷。
我们仔细去看我们讨厌的那些五毛与政府宣传部门,他们的日常做法都是:
1、戴帽子
2、站在道德高度,说正确的废话
3、自说自话,完全不管别人在说什么
4、预设立场
5、我永远是对的,反对我的都是错的
6、你们站在人民的对立面 然后有一个微博网友在评论里跟我说,他只需要一万元就能够搞定12306的网站外包开发。听到这样的话,我不由地一阵颤抖,如果这话来自一名所谓的业内人士,那我真的不知道应该怎么说了。
引用某网友的评论:
从专业角度来说,投入不算多,只是透明度不够,民众才疑惑!全国各地还需要再多些大型机房,才能满足高峰期分流排队和并发操作! 我的看法是,不否认铁道部的开发、架构设计存在一定问题,如果没有实际的大型系统设计经验的团队,可能会造成很多理论与实际脱节问题,事实上今年的12306已经比去年好太多了,他们也在吸取教训。当然,我也赞成他们向互联网公司取经,吸收现有经验。
建议大家不要单纯喷,5亿这个数字可能略高,但比起数千万的静态网站好多了,至于具体审计是国家审计局的事情,我支持惩处贪腐。做一个覆盖数千万用户,承受刷票插件5秒一次的并发,服务器、带宽、配套都是成本。而售票数字化几乎是必经之路,铁道部走出这一步是好的,买不到票有基础运力的问题,跟网络售票无关。
不要一叶障目,买不到票人人都会烦心,诚然铁道部是一个不错的发泄口,但如果只是为了喷而喷。借用我之前的一句话,铁道部如何做你们才满意?