posted @ 2009-03-12 21:35 gussing 阅读(645) 评论(0) 编辑
摘要: 先讲个题外话,不知是出于炫耀的目的还是什么恶趣味作怪,程序员给自己的项目起名字时喜欢玩一些“递归”的小把戏,比如GNU的全称是GNU is Not Unix,再比如WINE的全称是WINE Is Not Emulator。这种小玩笑在开源界很常见,但是微软以及跟着微软混的人则很少这么干,MSND这种严肃古板的产品文档上更是不太可能出现。MDL却是个例外,我们来看看MSDN是怎么描述MDL的:MDL An MDL structure is a partially-opaque structure that represents a memory descriptor list (MDL). MD阅读全文
posted @ 2013-01-02 01:43 gussing 阅读(2169) 评论(0) 编辑
摘要: 本次我们来聊两个不常见的锁类型:Resource与Fast Mutexes。这两种锁只有在内核态可用,并且微软的design guide里也并未提及,但它们在有些场景下却非常好用。我们学操作系统或者数据结构的时候一定接触过一种锁类型叫做读写锁,在读写锁的保护下,一个资源可以被很多线程读取,却只能被一个线程写。如果你有针对多线程环境好好考虑过你的设计,那么这种单线程写多线程读的模型多半已经很熟悉了。读写锁特别适合这种场景,Resource便是内核态的读写锁。而Fast Mutexes的出现主要为了解决性能问题,我们上回说过Mutex内部会保留一个count域,同一个线程获取了多少次锁,它就必须释阅读全文
posted @ 2012-12-31 14:43 gussing 阅读(2739) 评论(0) 编辑
摘要: 就跟上回讲的一样,动不动就使用spin lock是非常不合适的行为,我们应该尽量使用别的同步机制。NT内核提供了一族统称为dispatcher lock的锁,它们各有各的特点,适应不同的应用场景,了解它们的特性可以帮助你找到最适合自己的同步机制,避免spin lock的滥用。 表征dispatcher loco的数据结构拥有一个公共的头叫做DISPATCHER_HEADER,凡是有这个结构的锁都可以通过KeWaitForSingleObject(或者KeWaitForMultipleObjects)进入临界区。NT内核诞生的那段时间正好是面向对象概念大行其道的时候,所以NT的设计也融入了很多面阅读全文
posted @ 2012-12-30 19:20 gussing 阅读(1644) 评论(2) 编辑
摘要: 这篇文章基本上就是把WDK文档复述了一下,算不上原创,各位将就着看吧。在用户态的世界很多程序员(特别是*NIX界的人)不喜欢用多线程,认为这东西大大增加了程序的复杂度的同时带来的好处却不多,他们宁愿用进程来分割任务。当然这是一种很好的设计原则,我个人也持一模一样的观点。但是自从多核被炒热之后这部分内容越来越受关注,你假装问题不存在已经不可能了,借用冠希哥的日歪普歌词说就是:就算忘记你们不可能看不见。而在内核态的世界多线程的传统由来已久,因为内核部分的地址空间多半是共享的,即使是多进程架构在反映在内核部分也就是不同的线程,并且操作硬件的过程中不被重入也是基本要求。如果你开发过驱动或者玩过内核,那阅读全文
posted @ 2012-06-11 13:35 gussing 阅读(827) 评论(0) 编辑
摘要: IRP这个话题太大,基本上这是一个框,什么都能往里面装。我也不知道我漏掉了多少内容,总之呢,想到哪儿就说到哪儿吧。IRP_MN_REMOVE_DEVICE和IRP_MN_SURPRISE_REMOVAL一个PnP设备被删除时有两个事件会发生,一个是IRP_MN_SURPRISE_REMOVAL,另一个是IRP_MN_REMOVE_DEVICE。看名字就知道这两个事件都是告诉程序员设备已经不在了让他赶紧做点善后工作。我知道你的第一反应时什么:为什么要有两个事件呢,清理资源难道不是清理一次就够了吗?这事就说来话长了,windows跟linux有个很大的不同点就是,linux删除文件的时候不会管这个阅读全文
posted @ 2012-06-10 04:05 gussing 阅读(1891) 评论(0) 编辑
摘要: plang的现状:1. 有一些内置类型(int, double, char, string, 数组)2. 有lambda和函数3. 函数和lambda是first class4. 数组可以用区间表示,比如[1..10] ['a' .. 'z']5. 生成MSIL中间码,后边不管6. scope的实现有个bug7. 能算素数表8. 简单的尾递归优化截个图留念:defun filter(f, x){ var a = Car(x); var b = Cdr(x); if a == [] then [] else if f(a) then [a] + filter(f,阅读全文
posted @ 2012-05-18 20:25 gussing 阅读(302) 评论(0) 编辑
摘要: 1. 丘奇数lambda演算是图灵等价的,用lambda可以模拟自然数,其中最常见的是邱奇数: 0 = λf.λx.x 1 = λf.λx.f x 2 = λf.λx.f (f x) 3 = λf.λx.f (f (f x))简单点说,就是用函数f在x上作用了几次来表示该数字为几。λf.λx.f x作用了一次,所以该数为1;λf.λx.f (f x)作用了两次,所以该数为2,;以此类推。在plang里,lambda的定义完全照搬上面的形式,只做两处修改:1. 参数可以有多个,包含在括号内,比如λf.λx.f x表示成\(f,x).f x 2. 作用次数明写在函数后,比如...阅读全文
posted @ 2012-03-25 03:16 gussing 阅读(1701) 评论(6) 编辑
摘要: bash和gcc都能运行了,离“可用的系统”又进了一步。今天整理了下代码,放到了google code 上,有兴趣的都可以下载下来看。要是有谁对这也感兴趣,可以在下面留言,一起来玩。如果把讨论范围缩小到x86平台,那么linux和windows的区别,至少在用户态层面的区别,比我们想象的要小很多,所以事实上如果你真想干的话,在windows上实现各类*nix特性并没有想象中那么困难。反过来说,在*nix上实现windows特性也完全能做到。这不是随口一说,前者有cygwin, coLinux,后者有wine,都是成熟的项目。我这个东西跟cygwin的区别前面已经说过很多次了,跟coLinux的阅读全文
posted @ 2011-09-04 02:24 gussing 阅读(3885) 评论(9) 编辑
摘要: 在大约一年前提到过,我想做这样一件事:打通windows上的int 80中断,让原生的linux程序也可以在windows上跑。中间因为公司项目紧,再加上idt的一个小问题困惑了我很久,所以搁置了一段时间。最近觉得周末实在闲的慌又把这项目捡起来了,并且在某次抽烟的时候突然想到“每个处理器都有自己的idt表”这一小常识,idt的问题也就很顺利的解决了。接下来的事情就变得很顺了,按照原定计划先把所有的系统调用转到用户态然后从cygwin1.dll里再过一遍,大约熬了两天夜,一个小小的demo就完成了。代码参考了很多的开源项目,比如cygwin, glibc, linux kernel, 还有一个死阅读全文
posted @ 2011-08-25 15:43 gussing 阅读(3577) 评论(5) 编辑
摘要: 上回我们留下一个未解的问题,就是当一个IRP的CancelRoutine没有被设置时,CancelIo操作会失败,系统中有可能会留下永远都不会被complete的IRP。在Threaded IRP和non-threaded IRP一节中我们有谈到irp分为线程相关和非线程相关两种。倘若一个永远不complete的irp是非线程相关的,情况会稍微好一点,顶多系统中泄露了一个资源。倘若该irp是线程相关的,那事情就大了。thread IRP由IoManager生成并保留在线程的IRP队列里,负责处理该IRP的驱动在收到下层驱动的Complete事件后不会主动收回IRP的资源而是继续complete阅读全文
posted @ 2011-03-28 01:09 gussing 阅读(1821) 评论(0) 编辑