求职人生(转载)

chlchen2000 | 2006/June/18/22:39

第一家公司:
老板:小张今天工作忙不忙?
小张:不忙.〔天真的表情〕
下班时老板对小张说:你明天不用来了.
小张:为什么?〔惊呀的心情〕
老板:因为你不会找事做,所以才会不忙,公司要你何用.
刚入社会天真的心被打破~~~~~~~

第二家公司:
老板:小张今天工作忙不忙?
小张:很忙.
下班时老板对小张说:你明天不用来了.
小张:为什么?〔天呀!~~~~~我又做错了什么了?〕
老板:因为你做事没有系统,所以才会整天忙,公司要你何用.
为什么会这样呢!??~~~~~~~~心中一片冤枉~~~~~

第三家公司:
老板:小张今天工作忙不忙?
小张:还好.
下班时老板对小张说:你明天不用来了.
小张:为什么?[oh! my god][吃惊的表情~~~这~~~这~~~~~]
老板:因为你做事不理性,所以才会什么还好不好的,公司要你何用.
天呀!~~~~~这样还不行.

第四家公司:
老板:小张今天工作忙不忙?
小张:刚忙完.〔有准备的表情〕
下班时老板对小张说:你明天不用来了.
小张:为什么?〔此时心中一片凄凉~~~~~真的快哭出来了〕
老板:因为你做事没有效能[注意:效率与效能是不相同的,不懂去翻企管的书
吧!],不会再检查一下吗,公司要你何用.
F.Q.~~~~此处不留爷自有留爷处!

第五家公司:
老板:小张今天工作忙不忙?
小张:刚忙完,正在做别的.
下班时老板对小张说:你明天不用来了.
小张:为什么?〔眼角终於掉下一滴年轻人的眼泪~~~~〕
老板:因为你做事没有效率,有些事不会一起做吗,公司要你何用.
对~~我是个有志气有抱负的年轻人~~~~~~~合理的是训链,不合理的是磨链

第六家公司:
老板:小张今天工作忙不忙?
小张:我的工作都做完了,正在帮别人做.
下班时老板对小张说:你明天不用来了.
小张:为什么?〔眼神~~~~早呆了~~~但还不到精神错乱的状态唷~~~~~〕
老板:因为你做事没有目标,你不会规划明天要做的事吗?,公司要你何用.
不~~~上帝是爱我的~~~不是有一句信上帝得~~~~~~~~~明日处处是希望~~~~~

第七家公司:
老板:小张今天工作忙不忙?
小张:今天的工作都做完了,明日的时程表也做完了.[充份的心里准备~~~~~~~~~~]
下班时老板对小张说:你明天不用来了.
小张:为什么?〔脑中一片空白~~~~~~〕
老板:因为你做事不和群,你不会帮同事分忧解劳吗?公司要你何用.
小张:喔〔此时己没有知觉~~~只听到心跳的感觉~~~~~(基本上此时血压都会特别
的高~~~请小心~~~~~)~~~~~刚才老板说什么?~~~~没听到~~~~~~~~~〕
回家抱著棉被痛哭一场~~~~~~~~〔为什么非要抱棉被呢?~~~~~还用说就是没有女朋
友啦!~~~~这更是人生最大的悲哀呀!~~~~~~〕~~~~~

第八家公司:
老板:小张今天工作忙不忙?
小张:今日与明日该做的都做了,现在正帮同事.〔非常得意的表情,再来呀~~~~
谁怕谁!〕
下班时老板对小张说:你明天不用来了.
小张:为什么?〔~~~~~~~~~~~~~~〕
老板:公司财务困难所以....〔老板心里想:天呀,你那么强.我的位子还能
保吗!〕
终於认清社会的黑暗~~~~~〔人生是黑白的~~~

第九家公司:
老板:小张今天工作忙不忙?
小张:等一下我正在思考待会再回答你.〔紧张的眼神~~直冒冷汗~~~~~~~〕
下班时老板对小张说:你明天不用来了.
小张:为什么?
老板:你目中无人,我问你话呢,这样以後我们如何相处,公司要你何用.
谁bird你呀~~~~~

第十家公司:
老板:小张今天工作忙不忙?
小张:等一下〔找机会去外头辨一些事~~~~~散人〕.〔害怕的眼神~~~~~脑中充满
著太多的经验~~~〕
下班时老板对小张说:你明天不用来了.
小张:为什么?〔心中早有了免疫系统~~~(难怪杀虫济每次都有新的出来) 安啦
!〕
老板:刚才问你的话还没回答我呢,出去一段时间了,在混吗!公司要你何用.
怪我唷~~~~[~~~~有动作的唷!~~~~]~~~~~

第十一家公司:
老板:小张今天工作忙不忙?
小张:~~~~我~~我~偶~〔舌头早打死结了〕~~~~不~~~~不知道~~~要如何回答~~~你
~~~你呢!〔眼睛早斜了~~吞了一口啖~~~~低头小心慢慢一个字一个字的回答
~~~~~~〕
下班时老板对小张说:你明天不用来了.
小张:为什么.〔注意是句点不是问号〕〔此时小张己经是本能的反应了~~~~~〕
老板:因为你做事忙不忙都不知道,你到底有没有认真做呀!
喂!小刘~~~~~老板的车子是那一辆呀?~~~~~~~~~~

第十二家公司:
老板:小张今天工作忙不忙?
小张:〔装做没听到〕〔未来可能预测九分了~~~~准备打包〕喂!~~~~老王你那有
没有箱子.
下班时老板对小张说:你明天不用来了.
小张:喔!
老板:你做事不机灵,叫你呢!你有没有听到呀!到时无法再外拉更多的客户.公司
要你何用.
小张:谢谢老板多日照顾~~~谢谢!~~~~老板等一下我们出去吃个饭吧!
~~~~~~~~小张终於知道做人处事的道理~~~~~~~~

第十三家公司:
老板此时走过来!
老板:小张今天工作忙不忙?
小张:我准备找工作了.[啊~~~不用废话了~~~~~]
下班时老板对小张说:你明天不用来了.
小张:谢谢!
老板:祝你一路顺风!
天无绝人之路~~~~~路是自己闯出来的!

第十四家公司:〔自己开小吃店〕
客人〔房东的朋友〕:小张今天生意好吗?
小张:很好呀.当然也要看你们多多捧场了.
一个月後
房东:对不起!店不租给你了.
小张:为什么?〔~~~~~~~~~状况自己想吧!~~我想不出来了~~~~~~~]
老板:我要自己开所以..对不起..〔笑话,看你赚那么多还不如我自己开.〕
终於~~~~~看破红尘~~~~眼前是释迦牟尼佛吗?~~~~~~

第十五家公司:云山寺
师父:误世今天早晚课忙不忙呀?
误世〔小张〕:入世~~~误世~~~悟世~~~务释~~~~[後而不语]~~~~
在旁众人:〔什么呀~~~都知道这是答非所问吗?~~~〕
这就凡人有所不知,答话,就是要像龟甲万一样~~~~**没很甜,没很咸**~~~好像在模糊
中,但是又很清楚!反正大家都听不懂,如果你要问,大家会笑你是笨蛋的那一种~~~~
话!(懂吗?我知道你不是笨蛋!)~~~~~所以,你也不会再问下去了~~~因为装聪明是
人的本能!~~~~~~其实~每天我们都可在电视看到有一些政客与学者的[答.问]法~~~都有
这些功力了唷!~~~~~~
十年後
师父[对众人说]:老讷将羽化而去,今衣钵相传与误世.
误世:双目合并〔不语〕

娱乐 :: Comment (0) :: Trackbacks (0)

香港市场的权证小知识(完整入门篇)

chlchen2000 | 2006/June/18/22:11

(转载)
香港市场上存在一种风险极高的投资产品,俗称"窝轮",实际上是英文"WARRANTS"
的译音,我们为投资者简单介绍一下有关其的一些小知识。在这里我们首先了解一下"窝
轮"的定义:其专业的名称应该是"认股证",而新闻媒体上常提到的是备兑认股证和股票
认股证,同时也是香港市场上最为常见的两种,备兑认股证是衍生认股证的其中一种,
而衍生认股证是则是认股证的一种,认股证还包括股票认股证,而它本身则是期权的一
种.
  股票认股证是由上市公司所发行的认股证,例如代号2303的认股证,是由华丰纺织
(364)所发行的,其特点是期限比较长,例如2303的期限为3年。另一个特点是,如果
拥有该认股证的投资者到期要兑换股票的话,由上市公司发行新股以供兑换。
  衍生认股证是由其所代表的"资产"所衍生出来的认股证,这些资产可以是股票、股
票指数、黄金、外汇等等。而上述的股票认股证一般是只代表一个公司的股票,而衍生
认股证所代表的股票可以是一个公司的股票,也可以是同时代表多个公司的股票,如955
4,只代表中石化(386)一家的股票,而9394(石化摩根0406购)则同时代表着石化行
业中的中石化、上海石化、中石油及仪征化纤,所以它也称作一篮子。

  衍生认股证;指数的衍生认股证包括的"资产"有恒生指数、H股指数、红筹指数,甚
至包括道琼斯指数在内的国际市场指数等等;外汇的衍生认股证代表的资产是外汇的汇
率。衍生认股证是由持有该相关资产的第三者发行,并非由相关的上市公司本身发行,
一般都是国际性投资银行发行(一般称其为发行商)。所以如果投资者需要兑换股票的
话,那只能是旧股的转移,而不涉及到上市公司发行新股。而衍生认股证分为两类(见
图),包括非备兑认股证和备兑认股证,而现在市场上的主流是备兑认股证(简称备兑
证),而两者的区别是:非备兑认股证是指发行商手上没有足够的相关"资产"供认股证
持有者兑换,而备兑认股证则相反。
  一、备兑认股证的分类:
  就持有人的权利而言,备兑认股证分为认购证和认沽证:
  认购证(CALL WARRANTS):赋予持有人一个权利但非责任,以行使价在特定期限内
购买一定数量的相关资产。如果备兑证的投资者看好相关资产的后市走向,则会购入其
相关资产的认购证。
  认沽证(PUT WARRANTS):赋予持有人一个权利但非责任,以行使价在特定期限内
出售一定数量的相关资产。如果备兑证的投资者看空相关资产的后市走向,则会购入其
相关资产的认沽证。
  按行使的时间性而言,备兑认股证分为美式认股证和欧式认股证:
  美式认股证:持有人在股证上市日至到期日期间任何时间均可行使其权利。
  欧式认股证:持有人只有在股证到期日才能行使其权利。
  事实上在香港市场上主要流行的是欧式认股证。
  二、如何获取某个备兑证的相关资料:
  (一)备兑证的简称所代表的相关资料
  我们在报纸和财经网站上经常看到某个备兑证的简称,投资者可以从中看到该备兑
证的一些资料。

  我们举9197为例,其简称是华能法巴五零一购(@EC):华能:指其代表的相关资产
是华能国际(902)法巴:指其发行商是BNP百富勤五零一:指该认股证的到期日是2005年1
月,但具体的到期日并不能反映在简称上,而9197的具体到期日期是2005年1月28日,可
以从网站上的该证的基本资料中查到。
  购:指该认股证的性质是认购证,如果是认沽证的话则以"沽"为代表。
  @:代表的是该认股证以现金结算的方式,即是投资者如果在到期日前没有卖出此认
股证的话,发行商将以现金的方式将差价支付给投资者。如果把@换成*的话,则代表以
相关资产的现货结算;如果换成是$的话则代表是可以以现金或现货结算。而事实上现在
流行的是以现金结算,大多数的股证的简称都含有@。
  E: 代表该认股证是欧式备兑证,是英文"EUROPEAN"的简称 C: 代表该认股证的性质
是认购证,是英文"CALL"的简称,与"购"的意思一样;如果是认沽证的话则以"P"为代表

  (二)一些认股证的常见名词:我们从一般的财经网站经常会接触到一些认股证的
常见名词,这对于了解该认股证的价值有非常重要的参考价值:

  1. 到期日与结算价:认股证的简称只交代认股证的到期的月份,并没有交代具体
的日子,所以光看其简称有可能产生一个月左右的误差,所以要真正了解认股证的剩余
时间,必须要了解具体的到期日,同时投资者必须要清楚一点,认股证的最后交易日不
是到期日,而连同最后到期日在内,共有四个交易日不再进行交易。
  那由此而引起一个问题是,认股证的相关资产的结算价如何计算。如属股票认股证
,结算价为相关股票在认股证到期日前5个交易日的平均收市价(到期日之收市价并不计
算在内);如属指数认股证,结算价是根据联交所公布之 EAS 为准。EAS 是恒生指数于
即月期指到期日当天的5分钟平均价。
  2. 兑换比率:是指每一单位(股)认股证能换取多少单位的相关资产,如果显示
是"0.1"的话,即10个认股证的单位换一个单位的相关资产。在使用计算认股证的相关公
式时,往往用显示的倒数作为兑换比率,也就是说如果资料上显示"0.1",计算时就默认
为10,以下的相关公式就是这种情况。
  3. 溢价:认购证的溢价=(认股证现价×兑换比率+行使价-相关资产现价)/相
关资产现价×100%认沽证的溢价=(认股证现价×兑换比率-行使价+相关资产现价)
/相关资产现价×100%由于在股市的交易进行当中,相关资产的现价和认股证的现价总
是在变动,所以溢价的显示也会在经常跳动。对于选择认股证时,溢价越小,赢的机会
就越大,当然我们还得考虑其他的因素。
  4. 杠杆比率:杠杆比率=相关资产现价/(认股证现价×兑换比率)对于选择认股
证时,杠杆比率越大,赢的机会就越大,当然我们还得综合考虑其他的因素。
  5. 引申波幅:引申波幅是揭示认股证价值的重要指标,一般的欧式认股证是用B-S
模型﹙Black and Scholes model﹚进行计算的,由于计算的公式比较复杂,并不是此文
所介绍的范围,况且一般的投资者都能从有关资料上获取此项数值,就没有必要自己动
手计算。
  我们所要说明的是引申波幅对衡量认股证价值的重要性,引申波幅越大,认股证的
价值就越小,认股证价格的回落的机会就越大,反之亦然。但是我们应该明白到引申波
幅并不是认股证价值的决定性因素。
  6. 对冲值(比率):对冲比率指相关资产的价格变动及认股证价格变动的比例关
系。显示发行商要为对冲认股证风险而需买入或卖出相关资产的数量。它的数值介乎0到
1之间。
  如果对冲比率越接近1,说明有关的认股证越价内;如果对冲比率越接近0,说明有
关的认股证越价外;如果对冲比率越接近0.5,说明有关的认股证越接近等价。
  由于发行商要根据此指标去决定买入或卖出相关资产以供投资者兑换,所以有关认
股证的投资者可以根据这个指标估计出发行商已经买入或卖出相关资产的数量,从而了
解对手(发行商)的底牌。此项指标是投资认股证非常重要的衡量指标,其计算也引申
波幅一样比较复杂,同样可以从一般的资料上获取有关数值。
  7. 有效杠杆比率前面我们说过,杠杆比率越大,从理论上而言,该认股证越值得
购买,但是这个指标有一定的误导性,而有效杠杆比率则更为客观反映该认股证的价值
。比如说一些极度价外的认股证往往拥有很大的杠杆比率,但是根本没有行使的
  机会。
  有效杠杆比率= 杠杆比率×对冲比率
  认股证的价值评估:
  (1) 认股证理论价值 = 内在价值 + 时间价值
  首先我们看一下内在价值,在此之前必须要了解一下一个重要的概念――"等价比率
"。
  "等价比率"是衡量认股证价值一个最为基本的指标,其反映认股证的三种价值状态
:价内(in the money)、价外(out of the money)与等价(at the money)。
  等价比率=相关资产市价/股证所代表的相关资产行使价
  就认购证而言,如果等价比率大于1,表示该认股证处于"价内";如果等价比率小于
1,则表示认股证处于"价外"。对于认沽证而言,则是相反。如果等于1,无论是认沽还
是认购,都表示"等价"。
  认股证只有在价内时时,才能具有"内在价值",内在价值是一个大于或等于零的数
值,即使认股证"价外",其内在价值也不可能是负数。所以认股证的内在价值为零时,
其价值只会剩下时间价值,所以也能理解到为什么即将到期的而有处于等价或价外的认
股证的价格会非常低。
  (2) 响认股证价格的几种因素
  1. 相关资产价格的变动
  如相关资产价格呈上升趋势,认购证的价格也将会上升,反之亦然;相关资产价格
呈上升趋势,认沽证的价格将会下跌,反之亦然。
  2. 尚余时间
  正如上述一样,认股证的尚余时间越长,其时间价值越大,也就是说认股证的价格
越高,无论对于认购和认沽都是一样的。但是这仅是理论上而言,对于我们主要介绍的
欧式认股证,由于只有到期日才能执行,其到时候的相关资产的价格可高可低,这也是
一个风险的因素,大家必须要注意到这点。
  3. 相关资产的波幅
  波幅是测量相关资产风险的标准方法。波幅越大,相关资产的风险越大,因此认股
证价格会越高。
  4.无风险利率
  在香港无风险利率一般指的是HIBOR(银行同业拆息),是投资者承担的机会成本。
  无风险利率对于认股证的影响是双面的。
  当无风险利率上升时,相关资产的价格理论上是趋跌的,从而认购证的价格下跌,
而认沽证的价格上升。
  但是从另一个角度看,由于投资认股证是一种杠杆式的投资,由于利率上升,购买
相关资产的机会成本增加,致使一些较为稳健的投资者将摆放更多的资金去收取利息,
反而会将少量的资金去购买认购证,令认购证的买方力量加强,而认购证的价格会因此
而上升;认沽证的价格则因为无风险利率的上升而下跌。
  发行商发行认股证时,得调动资金购入相关资产。如借货成本(即利率)增加,成
本将反映于较高的认股证价格。同样道理,利率增加,认沽证价格将会下跌。
  所以总体而言,无风险利率上升,认购证的价格趋升,而认沽证的价格趋跌。
  5. 认股证有效期间的现金股息收益
  由于认股证的持有人一般而言不能象相关资产的持有人会得到现金股息,所以从理
论上而言,现金股息越高反而越不利于认购证的价格,认沽证则相反。但是由于发行商
在发行相关的认股证时的定价已经将相关资产期间可能的派息计算在内,如果派息符合
预期,对认股证的价格应该影响不大。从市场的实际操作来看,如果派息较预期高,由
于相关资产的投资者对其未来的前景较看好,相关资产的价格升幅可能会超过其多派的
现金息,因此而有利于认购证的价格,认沽证则相反;而如果现金股息比预期少,虽然
从理论上而言有利于认购证,但是相关资产的投资者可能会看淡其未来的前景,相关资
产的跌幅有可能会大于少派的部分,而认沽证因此而受益,但认购证则相反。总的而言
,我们认为股息的影响是双面的。

杂记 :: Comment (0) :: Trackbacks (0)

认股权证小知识

chlchen2000 | 2006/April/08/13:11

认股权证的定义 

  认股权证是在西方近年来兴起的金融衍生工具之一,即指由股份有限公司发行的、
能够按照特定的价格在特定的时间内购买一定数量该公司普通股票的选择权凭证,其实
质是一种普通股票的看涨期权。

  认股权证的要素

  认股期限

  认股期限是指认股权证的有效期。在有效期内,认股权证的持有人可以随时认购股
份;超过有效期,认股权自动失效。认股期限的长短因不同国家、不同地区以及不同市
场而差异很大,主要根据投资者和股票发行公司的要求而定。一般来说,认股期限多为3
-10年。认股期限越长,其认股价格就越高。

  认股价格

  认股权证在发行时,发行公司即要确定其认股价格。认股价格的确定一般以认股权
证发行时,发行公司的股票价格为基础,或者以公司股价的轻微溢价发行。如果出现公
司股份增加或减少等情况,就要对认股权证的认股价格进行调整。有的公司甚至这样约
定:当公司股票市价过度明显上扬时,其发行的认股权证的认股价格可以按预定公式自
动上调。这样做的目的在于保护认股权证持有人的利益,进而保护公司的权益。

  认股数量

  认股数量是指认股权证认购股份的数量,它可以用两种方式约定:一是确定每一单
位认股权证可以认购多少公司发行的普通股;二是确定每一单位认股权证可以认购多少
金额的普通股。

  赎回权

  发行认股权证的股份有限公司大都制定了赎回权条款,即规定在特定情况下,公司
有权赎回其发行的认股权证。

  认股价格的调整

  通常情况下,认股权证按既定的认股价格运行。但在诸如送股、配股等特定情况下
,认股权证的发行公司就必须对认股价格进行调整。收购权益

  在对认股权证进行的约定中,往往还有这样的条款,即如果有购买者对某家上市公
司提出了收购要约,那么收购方还要对这家上市公司已经发行在外的认股权证提出收购
要约。这样一来,认股权证的持有者便能立即实施认股并接受收购要约中应有的利益。

  认股权证的发行

  认股权证一般采取两种方式发行。最常用的一种方式是,在新发行优先股份或公司
债券时对优先股或公司债的投资者发行认股权证,因投资者对认股权证无须支付认购款
项,从而可增强公司优先股份或债券对投资者的吸引力。

  另一种发行方式为单独发行,是发行公司对老股东的一种回报。其具体做法是按老
股东的持股数量以一定比例对其发放。

  认股权证的交易

  认股权证的交易既可以在交易所内进行,也可以在场外交易市场上进行,其具体交
易方式与股票类似。以认股权证换取普通股的成本价,即“行使价”计算公式如下:

  行使价=(认股权证的市价×每手认股权证的数目)/每手认股权证可换的普通股
数目+认股价

  认股权证的价值

  认股权证的价值有内在价值和投机价值两方面。

  认股权证的内在价值=(公司发行的普通股的市场价格-认股权证的认购价格)×
换股比率

  认股权证的内在价值在很大程度上取决于普通股的市价。如果普通股的市价高于认
股价格,则认股权证的内在价值就可能大于零;如果普通股的市价等于认股价格,则认
股权证的内在价值就可能等于零。但认股权证的内在价值不会小于零,因为认股权证本
身还具有投机价值。如果普通股的现行市价低于认股价格,这只应看作是一种暂时现象
,它并不意味着股价会永远低于认股价格。只要认股权证没有到期,股价就仍有超越认
股价的机会。

杂记 :: Comment (0) :: Trackbacks (0)

分析 Linux 内核链表

chlchen2000 | 2006/April/08/13:11

一、 链表数据结构简介
链表是一种常用的组织有序数据的数据结构,它通过指针将一系列数据节点连接成一条数据链,是线性表的一种重要实现方式。相对于数组,链表具有更好的动态性,建立链表时无需预先知道数据总量,可以随机分配空间,可以高效地在链表中的任意位置实时插入或删除数据。链表的开销主要是访问的顺序性和组织链的空间损失。

通常链表数据结构至少应包含两个域:数据域和指针域,数据域用于存储数据,指针域用于建立与下一个节点的联系。按照指针域的组织以及各个节点之间的联系形式,链表又可以分为单链表、双链表、循环链表等多种类型,下面分别给出这几类常见链表类型的示意图:
1. 单链表

图 1 单链表


单链表是最简单的一类链表,它的特点是仅有一个指针域指向后继节点(next),因此,对单链表的遍历只能从头至尾(通常是 NULL 空指针)顺序进行。
2. 双链表

图 2 双链表


通过设计前驱和后继两个指针域,双链表可以从两个方向遍历,这是它区别于单链表的地方。如果打乱前驱、后继的依赖关系,就可以构成"二叉树";如果再让首节点的前驱指向链表尾节点、尾节点的后继指向首节点(如图2中虚线部分),就构成了循环链表;如果设计更多的指针域,就可以构成各种复杂的树状数据结构。

3. 循环链表
循环链表的特点是尾节点的后继指向首节点。前面已经给出了双循环链表的示意图,它的特点是从任意一个节点出发,沿两个方向的任何一个,都能找到链表中的任意一个数据。如果去掉前驱指针,就是单循环链表。

在Linux内核中使用了大量的链表结构来组织数据,包括设备列表以及各种功能模块中的数据组织。这些链表大多采用在[include/linux/list.h]实现的一个相当精彩的链表数据结构。本文的后继部分就将通过示例详细介绍这一数据结构的组织和使用。

二、 Linux 2.6 内核链表数据结构的实现
尽管这里使用2.6内核作为讲解的基础,但实际上 2.4 内核中的链表结构和 2.6 并没有什么区别。不同之处在于 2.6 扩充了两种链表数据结构:链表的读拷贝更新(rcu)和 HASH 链表(hlist)。这两种扩展都是基于最基本的 list 结构,因此,本文主要介绍基本链表结构,然后再简要介绍一下 rcu 和 hlist。

链表数据结构的定义很简单(节选自 [include/linux/list.h],以下所有代码,除非加以说明,其余均取自该文件):

 
struct list_head {
struct list_head *next, *prev;
};


list_head 结构包含两个指向 list_head 结构的指针 prev 和 next,由此可见,内核的链表具备双链表功能,实际上,通常它都组织成双循环链表。

和第一节介绍的双链表结构模型不同,这里的 list_head 没有数据域。在 Linux 内核链表中,不是在链表结构中包含数据,而是在数据结构中包含链表节点。

在数据结构课本中,链表的经典定义方式通常是这样的(以单链表为例):

 
struct list_node {
struct list_node *next;
ElemType data;
};


因为 ElemType 的缘故,对每一种数据项类型都需要定义各自的链表结构。有经验的 C++ 程序员应该知道,标准模板库中的 采用的是 C++ Template,利用模板抽象出和数据项类型无关的链表操作接口。

在 Linux 内核链表中,需要用链表组织起来的数据通常会包含一个 struct list_head 成员,例如在 [include/linux/netfilter.h] 中定义了一个 nf_sockopt_ops 结构来描述 Netfilter 为某一协议族准备的 getsockopt/setsockopt 接口,其中就有一个(struct list_head list)成员,各个协议族的 nf_sockopt_ops 结构都通过这个 list 成员组织在一个链表中,表头是定义在 [net/core/netfilter.c] 中的 nf_sockopts(struct list_head)。从下图中我们可以看到,这种通用的链表结构避免了为每个数据项类型定义自己的链表的麻烦。 Linux 的简捷实用、不求完美和标准的风格,在这里体现得相当充分。

图 3 nf_sockopts 链表示意图


三、 链表操作接口

1. 声明和初始化
实际上 Linux 只定义了链表节点,并没有专门定义链表头,那么一个链表结构是如何建立起来的呢?让我们来看看 LIST_HEAD() 这个宏:

 
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name)


当我们用 LIST_HEAD(nf_sockopts) 声明一个名为 nf_sockopts 的链表头时,它的 next、prev 指针都初始化为指向自己,这样,我们就有了一个空链表,因为 Linux 用头指针的 next 是否指向自己来判断链表是否为空:

 
static inline int list_empty(const struct list_head *head)
{
return head->next == head;
}


除了用 LIST_HEAD() 宏在声明的时候初始化一个链表以外,Linux 还提供了一个 INIT_LIST_HEAD 宏用于运行时初始化链表:

 
#define INIT_LIST_HEAD(ptr) do {
(ptr)->next = (ptr); (ptr)->prev = (ptr);
} while (0)


我们用 INIT_LIST_HEAD(&nf_sockopts) 来使用它。

2. 插入/删除/合并
a) 插入

对链表的插入操作有两种:在表头插入和在表尾插入。Linux为此提供了两个接口:

 
static inline void list_add(struct list_head *new, struct list_head *head);
static inline void list_add_tail(struct list_head *new, struct list_head *head);


因为 Linux 链表是循环表,且表头的 next、prev 分别指向链表中的第一个和最末一个节点,所以,list_add 和 list_add_tail 的区别并不大,实际上,Linux 分别用

 
__list_add(new, head, head->next);




 
__list_add(new, head->prev, head);


来实现两个接口,可见,在表头插入是插入在 head 之后,而在表尾插入是插入在 head->prev 之后。

假设有一个新 nf_sockopt_ops 结构变量 new_sockopt 需要添加到 nf_sockopts 链表头,我们应当这样操作:

 
list_add(&new_sockopt.list, &nf_sockopts);


从这里我们看出,nf_sockopts 链表中记录的并不是 new_sockopt 的地址,而是其中的 list 元素的地址。如何通过链表访问到 new_sockopt 呢?下面会有详细介绍。

b) 删除

 
static inline void list_del(struct list_head *entry);


当我们需要删除 nf_sockopts 链表中添加的 new_sockopt 项时,我们这么操作:

 
list_del(&new_sockopt.list);


被剔除下来的 new_sockopt.list,prev、next 指针分别被设为 LIST_POSITION2 和 LIST_POSITION1 两个特殊值,这样设置是为了保证不在链表中的节点项不可访问--对 LIST_POSITION1 和 LIST_POSITION2 的访问都将引起页故障。与之相对应, list_del_init() 函数将节点从链表中解下来之后,调用 LIST_INIT_HEAD() 将节点置为空链状态。

c) 搬移

Linux 提供了将原本属于一个链表的节点移动到另一个链表的操作,并根据插入到新链表的位置分为两类:

 
static inline void list_move(struct list_head *list, struct list_head *head);
static inline void list_move_tail(struct list_head *list, struct list_head *head);


例如 list_move(&new_sockopt.list,&nf_sockopts) 会把 new_sockopt 从它所在的链表上删除,并将其再链入 nf_sockopts 的表头。

d) 合并

除了针对节点的插入、删除操作,Linux 链表还提供了整个链表的插入功能:

 
static inline void list_splice(struct list_head *list, struct list_head *head);


假设当前有两个链表,表头分别是 list1 和 list2(都是 struct list_head 变量),当调用 list_splice(&list1,&list2) 时,只要 list1 非空,list1 链表的内容将被挂接在 list2 链表上,位于 list2 和 list2.next(原 list2 表的第一个节点)之间。新 list2 链表将以原 list1 表的第一个节点为首节点,而尾节点不变。如图(虚箭头为next指针):

图 4 链表合并 list_splice(&list1,&list2)


当 list1 被挂接到 list2 之后,作为原表头指针的 list1 的 next、prev 仍然指向原来的节点,为了避免引起混乱,Linux 提供了一个 list_splice_init() 函数:

 
static inline void list_splice_init(struct list_head *list, struct list_head *head);


该函数在将 list 合并到 head 链表的基础上,调用 INIT_LIST_HEAD(list) 将 list 设置为空链。

3. 遍历
遍历是链表最经常的操作之一,为了方便核心应用遍历链表,Linux 链表将遍历操作抽象成几个宏。在介绍遍历宏之前,我们先看看如何从链表中访问到我们真正需要的数据项。

a) 由链表节点到数据项变量

我们知道,Linux 链表中仅保存了数据项结构中 list_head 成员变量的地址,那么我们如何通过这个 list_head 成员访问到作为它的所有者的节点数据呢?Linux 为此提供了一个 list_entry(ptr,type,member) 宏,其中ptr是指向该数据中 list_head 成员的指针,也就是存储在链表中的地址值,type 是数据项的类型,member 则是数据项类型定义中 list_head 成员的变量名,例如,我们要访问 nf_sockopts 链表中首个 nf_sockopt_ops 变量,则如此调用:

 
list_entry(nf_sockopts->next, struct nf_sockopt_ops, list);


这里 "list" 正是 nf_sockopt_ops 结构中定义的用于链表操作的节点成员变量名。

 
#define list_entry(ptr, type, member) container_of(ptr, type, member)
container_of宏定义在[include/linux/kernel.h]中:
#define container_of(ptr, type, member) ({
const typeof( ((type *)0)->member ) *__mptr = (ptr);
(type *)( (char *)__mptr - offsetof(type,member) );})
offsetof宏定义在[include/linux/stddef.h]中:
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)


size_t 最终定义为 unsigned int(i386)。

这里使用的是一个利用编译器技术的小技巧,即先求得结构成员在与结构中的偏移量,然后根据成员变量的地址反过来得出属主结构变量的地址。

container_of() 和 offsetof() 并不仅用于链表操作,这里最有趣的地方是 ((type *)0)->member,它将0地址强制 "转换" 为 type 结构的指针,再访问到 type 结构中的 member 成员。在 container_of 宏中,它用来给 typeof() 提供参数(typeof() 是 gcc 的扩展,和 sizeof() 类似 ),以获得 member 成员的数据类型;在 offsetof() 中,这个 member 成员的地址实际上就是 type 数据结构中 member 成员相对于结构变量的偏移量。

如果这么说还不好理解的话,不妨看看下面这张图:

图 5 offsetof() 宏的原理


对于给定一个结构,offsetof(type,member) 是一个常量,list_entry() 正是利用这个不变的偏移量来求得链表数据项的变量地址。

b) 遍历宏

在 [net/core/netfilter.c] 的 nf_register_sockopt() 函数中有这么一段话:

 
……
struct list_head *i;
……
list_for_each(i, &nf_sockopts) {
struct nf_sockopt_ops *ops = (struct nf_sockopt_ops *)i;
……
}
……


函数首先定义一个 (struct list_head *) 指针变量i,然后调用 list_for_each(i,&nf_sockopts) 进行遍历。在 [include/linux/list.h] 中, list_for_each() 宏是这么定义的:

 
#define list_for_each(pos, head)
for (pos = (head)->next, prefetch(pos->next); pos != (head);
pos = pos->next, prefetch(pos->next))


它实际上是一个 for 循环,利用传入的 pos 作为循环变量,从表头 head 开始,逐项向后(next 方向)移动 pos,直至又回到 head(prefetch() 可以不考虑,用于预取以提高遍历速度 )。

那么在 nf_register_sockopt() 中实际上就是遍历 nf_sockopts 链表。为什么能直接将获得的 list_head 成员变量地址当成 struct nf_sockopt_ops 数据项变量的地址呢?我们注意到在 struct nf_sockopt_ops 结构中,list是其中的第一项成员,因此,它的地址也就是结构变量的地址。更规范的获得数据变量地址的用法应该是:

 
struct nf_sockopt_ops *ops = list_entry(i, struct nf_sockopt_ops, list);


大多数情况下,遍历链表的时候都需要获得链表节点数据项,也就是说 list_for_each()和list_entry() 总是同时使用。对此 Linux 给出了一个 list_for_each_entry() 宏:

 
#define list_for_each_entry(pos, head, member) ……


与 list_for_each() 不同,这里的pos是数据项结构指针类型,而不是 (struct list_head *)。nf_register_sockopt() 函数可以利用这个宏而设计得更简单:

 
……
struct nf_sockopt_ops *ops;
list_for_each_entry(ops,&nf_sockopts,list){
……
}
……


某些应用需要反向遍历链表,Linux 提供了 list_for_each_prev() 和 list_for_each_entry_reverse() 来完成这一操作,使用方法和上面介绍的 list_for_each()、list_for_each_entry() 完全相同。

如果遍历不是从链表头开始,而是从已知的某个节点 pos 开始,则可以使用 list_for_each_entry_continue(pos,head,member)。有时还会出现这种需求,即经过一系列计算后,如果 pos 有值,则从 pos 开始遍历,如果没有,则从链表头开始,为此,Linux 专门提供了一个 list_prepare_entry(pos,head,member) 宏,将它的返回值作为 list_for_each_entry_continue() 的 pos 参数,就可以满足这一要求。

4. 安全性考虑
在并发执行的环境下,链表操作通常都应该考虑同步安全性问题,为了方便,Linux 将这一操作留给应用自己处理。Linux 链表自己考虑的安全性主要有两个方面:

a) list_empty() 判断

基本的 list_empty() 仅以头指针的 next 是否指向自己来判断链表是否为空,Linux 链表另行提供了一个 list_empty_careful() 宏,它同时判断头指针的 next 和 prev,仅当两者都指向自己时才返回真。这主要是为了应付另一个 cpu 正在处理同一个链表而造成 next、prev 不一致的情况。但代码注释也承认,这一安全保障能力有限:除非其他 cpu 的链表操作只有 list_del_init(),否则仍然不能保证安全,也就是说,还是需要加锁保护。

b) 遍历时节点删除

前面介绍了用于链表遍历的几个宏,它们都是通过移动 pos 指针来达到遍历的目的。但如果遍历的操作中包含删除 pos 指针所指向的节点,pos 指针的移动就会被中断,因为 list_del(pos) 将把 pos 的 next、prev 置成 LIST_POSITION2 和 LIST_POSITION1 的特殊值。

当然,调用者完全可以自己缓存 next 指针使遍历操作能够连贯起来,但为了编程的一致性,Linux 链表仍然提供了两个对应于基本遍历操作的 "_safe" 接口:list_for_each_safe(pos, n, head)、list_for_each_entry_safe(pos, n, head, member),它们要求调用者另外提供一个与 pos 同类型的指针n,在 for 循环中暂存 pos 下一个节点的地址,避免因 pos 节点被释放而造成的断链。

:: Comment (0) :: Trackbacks (1054)

基于IMD的包过滤防火墙原理与实现

chlchen2000 | 2006/April/08/13:11

xiaobai
xiaobai@openfind.com.cn
711网络安全小组 http://www.cpyy.net


一、前言
二、IMD中间层技术介绍
三、passthru例程分析
四、部分演示代码
五、驱动编译与安装
六. 总结



一、前言

前段时间,在安全焦点上看到了TOo2y朋友写的《基于SPI的数据报过滤原理与实现》,很是不错。文章中提到的基于SPI的数据报拦截技术是在用户级的。用户级的拦截有其优势,实现方便、便于移植、通用性强,但是,用户级并不能得到所有的数据报。本文提到的基于IMD的数据报过滤则是属于内核级的,它建立在网络驱动上面。
其实两个月前就想写这篇文章了,可惜这个技术是我一年前做的,好久不用,已经忘的差不多了,所以一直没有写。不过,近来正巧有个课题,牵扯到了中间层驱动。于是,重新拾起丢了有一年的DDK,啃了起来。这期间,真的要非常感谢linxder的帮忙,让我少走了一些弯路,否则,我真的要从头学起了。废话不多说了,切入正题。



二、中间层驱动技术介绍

中间层驱动,英文为NDIS intermediate driver。

1)内核级网络驱动介绍
Microsoft Windows 2000支持三种基本的内核级网络驱动,这三层driver顺序从下到上依次为:
1. Miniport NIC drivers:微端口网卡驱动,位于最底层,直接操纵网卡并且对高层驱动提供接口。
2. Intermediate drivers:IMD中间层驱动,这就是今天的主角,位于1和3之间,具体的作用下面就会介绍。
3. Protocol drivers:高层协议驱动,俗称为TDI(传输驱动程序接口),高于前面两层,直接面向用户级,
为用户提供网络服务,也就是绝大多数程序所用到的网络接口。


2)IMD驱动
IMD中间层,它的实质很简单,最经典的描述莫过于下面的话:

An intermediate driver is typically layered over one or more NDIS NIC drivers and under a transport driver (possibly multilayered) that supports TDI at its upper edge.
An NDIS intermediate driver exports MiniportXxx functions at its upper edge and ProtocolXxx functions at its lower edge.(见DDK文档)

中间层插入网卡和协议层之间,对上面的协议层表现为一个虚拟的微端口网卡结构,而对下面的网卡则表现为一个协议层的结构。所以,无论是网卡接收并上传的数据报,还是上层要下送至网卡发送的数据报,无一例外地要经过中间层。


3)IMD包过滤技术
前面我们已经看到,所有的数据报都要经过中间层,所以,我们可以在中间层加入我们想要过滤的数据报的特征,实现基于中间层驱动的内核级包过滤。

这样做的优势非常明显,首先,在驱动级别上做过滤,无须组包,速度快,效率自然就高;其次,所有的数据报无一例外,只要网卡上传的数据报均可以截获,避免了用户级无法得到所有数据报的缺点。当然,世界上没有完美的事情。IMD包过滤技术也存在其不可避免的缺点,与操作系统版本关系密切,与硬件联系大,可移植性低。我在调试这个驱动的时候,就碰到了无数次蓝屏,无数次重启动,进了几次安全模式,甚至还为此重新安装了一次系统。

正是由于上面的一些问题,现在市面上还没有见到有厂家推出基于IMD的实用型防火墙,大部分都是在实验室中的作品,或许真的是要做到通用性很难吧,不过还是希望能尽快见到这样的产品面世。



三、passthru代码分析

到这里,你或许已经非常想看看到底怎么来实现基于IMD的包过滤防火墙了,不过,你肯定会迟疑,如果让我们自己写整个中间层驱动的话,是不是有些太艰难了啊?况且,我只是个搞网络安全的,我不是专门写驱动的,让我完成一个驱动程序,还要对上层协议伪装成一个网卡,对下层伪装成一个协议层,这不是要命么?

呵呵,其实微软很不错的,在提出这项技术之后,其DDK中附带了一个中间层驱动的例程,就是passthru。passthru实现了一个中间层的基本功能,对下表现为一个协议层的驱动,对上表现为一个虚拟网卡,安装passthru驱动之后,你可以在硬件管理中的网卡中看到一个虚拟网卡。不过,passthru只是插入到网卡和上层协议中间,却未做任何工作,也就是说,passthru只是让所有的数据报原原本本地流经自己而已。我们要想实现中间层包过滤的功能,需要对passthru进行修改。

想想我们要实现的包过滤的功能,我们只需要在中间层接收到数据报的时候进行规则判断就可以了,而在passthru中,接收数据报是用protocol.c文件中的PtReceive和PtReceivePacket这两个函数来实现的。根据微软的解释,微软建议接收包用PtReceivePacket函数,因为可以得到更高的效率,然而,为了向下兼容,也保留了PtReceive函数给老的网卡使用。所以,在一块网卡上,只可能有一个函数在工作,这要取决于你的网卡型号了。巧的是,我的两台机器的网卡应用的函数正巧不一样。同样是IBM的机器,一台P4 1.5G的机器的网卡是Realtek RTL8139(A) PCI Fast Ethernet Adapter,另外一台P4 2.0G的机器的网卡是Intel(R) PRO/100 VE Network Connection,其中Realtek网卡用的是PtReceive来接包,而Intel的网卡是用PtReceivePacket来接包。

现在我们知道了哪个函数负责接收数据报,那么我们就可以对这个函数进行修改了。从兼容和通用性考虑,我们需要对PtReceive和PtReceivePacket函数进行修改,其中加上我们需要判断的规则进行过滤,下面就贴详细的代码了。



四、部分演示代码

我们的目的是在调用接受数据报函数的时候能执行我们的过滤代码,所以,我们要在函数代码中添加我们自己的代码,下面用过滤特定协议类型的数据报来做演示。

首先修改PtReceive,看一下protocol.c文件中函数的代码,代码中用NdisGetReceivedPacket函数得到一个PNDIS_PACKET的结构Packet,数据报内容就存放在这个结构中的链表内。我们定义一个PUCHAR结构的pPacketContent,然后用下面的代码获得整个数据报的内容:

//---------------------------------------------------------
int PacketSize;
PUCHAR pPacketContent;
PUCHAR pBuf;
UINT BufLength;
MDL * pNext;
UINT i;

//把数据包内容从Packet拷贝到pPacketContent

NdisQueryPacket( Packet,NULL,NULL,NULL,&PacketSize);

Status= NdisAllocateMemory( &pPacketContent, 2000, 0,HighestAcceptableMax);
if (Status!=NDIS_STATUS_SUCCESS ) return Status;
NdisZeroMemory (pPacketContent, 2000);

NdisQueryBufferSafe(Packet->Private.Head, &pBuf, &BufLength, 32 );
NdisMoveMemory(pPacketContent, pBuf, BufLength);

i = BufLength;
pNext = Packet->Private.Head;

for(;;)
{
if(pNext == Packet->Private.Tail)
break;
pNext = pNext->Next; //指针后移
if(pNext == NULL)
break;

NdisQueryBufferSafe(pNext,&pBuf,&BufLength,32);
NdisMoveMemory(pPacketContent+i,pBuf,BufLength);
i+=BufLength;
}

//数据拷贝完毕
//---------------------------------------------------------


现在,我们已经在PtReceive函数中得到了数据报的内容,存放在pPacketContent中,数据报的格式你可以去查书。通常,在以太网中,得到的数据报大致是如下结构,以太帧头14个字节,放在pPacketContent[0]到pPacketContent[13]中,其中前六个字节是目的MAC地址,然后六个字节源MAC地址,然后两个字节是协议类型,通常的协议类型有0x08 0x00 ->IP,0x08 0x06 ->ARP,0x08 0x35 ->RARP,所以,可以通过pPacketContent[12]和pPacketContent[13]来判断协议类型。如果是IP包,然后pPacketContent中存放的是IP头,根据IP头的格式,可以得到第23个字节pPacketContent[23]表示传输层协议:1 ->ICMP,2 ->IGMP,6 ->TCP,17 ->UDP,剩下的就是数据报内容了。因为我们只是做演示,所以只要知道这几个标志性的就好了,其他的你可以根据你的需要扩展。我们通过pPacketContent中的内容可以做些规则,比如过滤ICMP包,我们只要比较pPacketContent[12]和pPacketContent[13]还有pPacketContent[23]这三个标志位就可以了,如果不是ICMP包,那么不做任何工作,如果匹配了,那就返回一个NDIS_STATUS_NOT_ACCEPTED,将包丢弃,释放pPacketContent,就可以过滤ICMP包了,下面就是过滤规则的代码。

//---------------------------------------------------------
//规则标志位(1表示过滤,0表示放行,你可以通过改这个数值来配置规则)
UINT ICMP = 1; //ICMP数据报规则
UINT IGMP = 0; //IGMP数据报规则
UINT TCP = 0; //TCP数据报规则
UINT UDP = 0; //UDP数据报规则

//规则判断
if (ICMP == 1)
{
if(((char *)pPacketContent)[12] == 8 &&
((char *)pPacketContent)[13] == 0 &&
((char *)pPacketContent)[23] == 1)
{
DbgPrint("ICMP被拦截! ");
NdisFreeMemory(pPacketContent, 2000, 0);
return NDIS_STATUS_NOT_ACCEPTED;
}
}

if (IGMP == 1)
{
if(((char *)pPacketContent)[12] == 8 &&
((char *)pPacketContent)[13] == 0 &&
((char *)pPacketContent)[23] == 2)
{
DbgPrint("IGMP被拦截! ");
NdisFreeMemory(pPacketContent, 2000, 0);
return NDIS_STATUS_NOT_ACCEPTED;
}
}

if (TCP == 1)
{
if(((char *)pPacketContent)[12] == 8 &&
((char *)pPacketContent)[13] == 0 &&
((char *)pPacketContent)[23] == 6)
{
DbgPrint("TCP被拦截! ");
NdisFreeMemory(pPacketContent, 2000, 0);
return NDIS_STATUS_NOT_ACCEPTED;
}
}

if (UDP == 1)
{
if(((char *)pPacketContent)[12] == 8 &&
((char *)pPacketContent)[13] == 0 &&
((char *)pPacketContent)[23] == 17)
{
DbgPrint("UDP被拦截! ");
NdisFreeMemory(pPacketContent, 2000, 0);
return NDIS_STATUS_NOT_ACCEPTED;
}
}

//规则判断结束
//---------------------------------------------------------


到这里,PtReceive函数已经修改完了,只要调用PtReceive函数接收数据报的时候,就可以执行我们的规则了,下面修改PtReceivePacket函数,其实上面的修改代码内容都是一样的,只不过PtReceivePacket函数跟PtReceive函数不太一样,PtReceivePacket直接在入口参数中就得到了PNDIS_PACKET的结构Packet,存放了数据报的所有内容,所以,直接将上面的代码粘到函数PtReceivePacket的代码中就可以了。到现在,无论是网卡调用哪一个接收函数,都可以执行我们需要的规则。

其实,上面所定义的规则是很简单的,因为只作为演示用,而我的课题嘛,嘿嘿,就不是那么简单了。其实在pPacketContent已经得到了所有的数据报内容,我们可以随意扩展规则。比如,过滤指定IP、指定端口的数据报,至于具体应该设置哪个位置,你只要去找一本介绍数据报结构的书看一下就知道了,呵呵。



五、驱动编译与安装

前面谈了那么多,其实都是在说IMD包过滤的实现和驱动代码,但是,我已经修改了代码,怎么编译和安装呢?

这一部分就解决驱动编译和安装的问题。我们用passthru的代码,对接收数据报的部分做了修改。然后,我们用DDK自带的builder工具来编译。我一般是用开始菜单中DDK程序组中的Free Build Environment,到passthru目录下执行build -cz来编译passthru,得到passthru.sys文件,然后再到NTDDKsrc etworkconfigfilter目录下,执行build -cz来得到sfilter.dll,然后再加上passthru目录下的netsf.inf和netsf_m.inf,一共四个文件。这样,驱动安装所需要的文件就全了。

打开网络属性,添加服务,找到passthru目录下,安装,弹出没有数字签名的警告,不理,继续安装,最后,你会发现,网络属性中增加了一个名为Sample Filter的组件,同时,硬件管理器中的网卡下增加了一个Sample Filter Miniport的设备。如果你已经到了这里,并且系统没有出现蓝屏和死机,那么恭喜你,你已经成功地安装上了中间层驱动,并且已经发挥包过滤作用了。



六. 总结

难得我写了那么多,现在做一个总结吧。上文中的代码,我只是用来做演示的,只用来说明基于IMD的包过滤防火墙原理与实现,其实需要做的工作还有很多,驱动上面碰到的问题会很多,并且常常伴随着的是蓝屏,死机,甚至要重装系统。

你也许会问,那我每次改一下规则难道还要重新再安装一遍驱动么,况且,必须重启动一次,旧的驱动才彻底卸载掉,多麻烦啊。呵呵,其实是中间层驱动是可以跟应用层的程序结合的。首先你要在驱动中指定好规则,应用层的程序通过DeviceIoControl传递指令到驱动中,可以控制驱动的规则标志位。

特别推荐驱动开发网(www.driverdevelop.com)论坛的ndis网络接口开发版,这里是国内水平最高的地方,所有的与驱动有关的问题你都可以在那里得到解决。

最后,附带说一句,调试驱动的时候先做好处理系统后事的准备,对于出现的任何系统问题也好,硬盘问题也好,我不负任何责任,呵呵。

欢迎访问我们团队的站点:711网络安全小组 http://www.cpyy.net

文章推荐 :: Comment (0) :: Trackbacks (173)

今日所感

chlchen2000 | 2006/April/08/13:11

夫君子之行,静以修身,俭以养德。非淡泊无以明志,非宁静无以致远。夫学须静也,才须学也,非学无以广才,非志无以成学。淫慢则不能励精,险躁则不能治性。年与时驰,意与日去,遂成枯落,多不接世,悲守穷庐,将复何及!
----《诸葛亮.诫子书》

我的日记 :: Comment (0) :: Trackbacks (1058)

为了长寿,大家要多看美女,别不好意思哦!

chlchen2000 | 2005/October/21/10:22


研究称男性每天凝望靓女数分钟,寿命延长4至5年。

男性喜欢观看美女,除了是出于男性的本能反应外,其实还有一个好处。根据英国一份医学杂志报道,男性每天凝望漂亮女性几分钟,可以延长平均寿命4至5年。
英国研究人员耗时5年对200名男性进行的一项实验发现,每天都能凝望漂亮女性的男性,血压相对较低,脉搏跳动较慢,心脏疾病也较少,平均寿命可以延长4至5年。
研究显示,男性彬彬有礼地凝视美丽的女性,就好像是欣赏美丽的风景画一样,有助于身心健康。而凝视美丽的女性10分钟,健身效果差不多相当于做了30分钟的有氧运动。
  虽然男性突然见到美女会产生自律神经亢奋,出现脸红心跳、手脚冰冷等现象.但是每天都能见到美女,大脑中的回路控制机制,就会使脑中产生好的情绪记忆,让情绪中枢保持稳定状态,能减低心血管疾病或中风的风险,而这项研究也透露出男性喜欢观赏美女的原因。

娱乐 :: Comment (0) :: Trackbacks (0)

七种流行的暧昧男女关系,你们是属于哪种?

chlchen2000 | 2005/October/16/18:52

男朋友女朋友?不好说;爱人同志?是,又不是;兄弟姐妹?也可以这么说吧……

    其实,连他们自己都不那么清楚彼此的关系。仿佛,他缺不了她,她也离不了他,但其实,各有各的阳光空气和水分……

    一直以多元价值颠覆传统的城市在不断新陈代谢,男女关系也已经越来越多元化,他和她,从情感到身体的关系,越来越暧昧,也越来越无法定义。

    暧昧关系之一:哥哥妹妹(姐姐弟弟)

    暧昧指数:****

    清白指数:***

    招牌口号:“某某是我哥,我们是亲人。”

    “她比我小10岁呢,小妹妹……”

    经典镜头:

    1.每日中午,他所在的公司前台,都会出现一个年轻小女子,笑着提着几个饭盒,说:“哥啊……尝尝我今天做的蛋炒饭,怎么样?”然后笑吟吟地看着他吃完,再帮他收拾,不忘给他细心地擦去下巴上的米粒。他心疼地说:“真不知道你小脑袋瓜里在想什么!”

2.聚会上,他身边美女如云,哥们儿彼此调笑,吃豆腐之事见多不怪。可是,有人跟她讲起荤段子,惹得她满面红晕,他立刻倒立英眉,教训对方说:“不可以欺负她,她是我妹妹。”

    3.她衣着时髦,身边却会经常出现个年轻的小伙子,甜甜地叫她姐姐。其实全无血缘关系。过马路的时候,她都会紧紧地抓着他的手,吃饭的时候,会特地给他送一筷子菜,很多追求她的男人很容易遭受她的白眼,只有这个小“弟弟”,时而像个大人一样保护“姐姐”,时而成了一个让“姐姐”哭笑不得的小淘气。

    关系透析:

    对“哥哥”来说,小妹妹的存在意义是,令他有保护她的欲望,当男性内心的英雄主义需要倾泻的时候,当他感觉无助和寂寞的时候,“小妹妹”的乖巧和柔弱往往比一般的温柔体贴更令他感觉舒服,而她对他的崇拜,更是让他感到格外自信,恰好满足了男人的某种精神征服欲。对“妹妹”来说,她要的十分简单——被疼爱被保护。

    对“姐姐”来说,在没有完美的男朋友之前,“弟弟”是一个很贴心的小跟屁虫,他具备男人和男孩的双重效益,他不会故意和她过不去,她有麻烦的时候,他不会背叛誓言,而当她母性流露的时候,他又成了可爱天真的“小东西”。对“弟弟”来说,“姐姐”往往是值得信赖,充满女性魅力的女人。

    潜在危机:

    现实生活里,大部分的“亲情”关系往往很难演变为真正的爱情关系。此类男女关系中,多的是怜惜和疼爱的成分,少有什么共同语言,更谈不上阅历相当,而且“弟弟妹妹”对“哥哥姐姐”的感情,往往更为沉重和复杂,并且很容易陷入其中难以自拔,一旦“暧昧”过度,一旦“哥哥姐姐”有了情人,“弟弟妹妹”难免会成为绊脚石。

    暧昧关系之二:红颜蓝颜

    暧昧指数:*****

    清白指数:*

    招牌口号:“女人的心和身体是可以分开的,我们之间,就一个纯字。”

    “男人女人之间没有纯洁的友谊?那只怪你没找到红颜知己。”

    “他是我灵魂上的知己,我们彼此了解却又永不占有。”

    经典镜头:

    1.每次和老婆吵架后,他都会夺门而出,跑到她家里哭诉一番,完了会说:“为什么我爱的人不是你?为什么我老婆就不能像你这样善解人意?”她回答:“如果你老婆可以做到我这样,她就不是你老婆了。”

    2.被老板批评后,她十分想不通,女朋友约她去逛街散心都不肯,非要给他电话痛诉一顿,他给她分析事例,剖析人生道理,直说到她重新开朗起来。碰到一些重大选择,她也会找他商量,感觉十分有共同语言。她说:“我男朋友最了解我的身体,你是最了解我的心事的知己。”

    关系透析:

    心情烦闷的时候,遇见各种人生难题的时候,他们就成了“相濡以沫”的鱼,一旦海水返潮,便各自游去。即使双方各自有爱人,有些私房话和知心话也只跟“红颜蓝颜”说。从某种程度上来说,这种男女关系大多是停留在精神层面上的相爱,也可以说,和情人关系相比,他们只缺少肉体交流。

    潜在危机:

    即使是最清白的红颜蓝颜知己,一旦有一方的爱人不够开通懂事,便容易被误会成第三者;其次,毕竟是一男一女,一旦“酒逢知己千杯少”,投入深情过度,难免“宽衣解带”,而一旦破了最后一道防线,这“知己”关系就难再继续。

    暧昧关系之三:网络情人

    暧昧指数:*****

    清白指数:**

    招牌口号:“我爱你,即使永不见你。我可以感觉到你的一切,看不到你,这不是问题。”

    “我们在比特的世界里相爱,离开网络,这份爱就无法生存。”

    经典镜头:

    1.他天天回家吃老婆亲手做的饭菜,然后她在厨房里洗涤的时候,听到房间里传来敲击键盘的声音。那个不用为他打理生活和一切的女人,在网络那一边心安理得地瓜分着她丈夫的感情。而她仍安静地守着她嫁的男人已经失去灵魂的躯壳。

    2.“亲爱的,送你999朵玫瑰。”

    “真的吗?”

    一封贴着玫瑰图的电子邮件“嗖”地到了她的邮箱。

    “让我吻你吧……”

    “嗯,我感觉到了,你温软湿润的嘴唇……”

    “嗯,我特地为你刷过牙呢。”

    关系透析:

    在网上,他们“相爱”,甚至举行婚礼,从来没见过的两个陌生人,文字游戏是彼此的依赖和情趣来源。他们沉溺其中,网络令他们看上去很“完美”。

    与一般的网恋不同,这种网络情人,多半不会见面,只是依赖对对方的想像,制造各种浪漫的气氛和假想。

    与现实生活里的爱情不同,网络情人所付出的成本十分低廉,且不需要承受道德上的压力。

    潜在危机:

    因为彼此爱的,只是自己的想像,和文字制造的迷宫。所以万一,万一见面的话,后果很难想像。美女恐龙也就算了,如果发现对面那个竟然

    暧昧关系之四:异性合住

    暧昧指数:***

    清白指数:***

    招牌口号:“一个人住,负担太重,而且我怕黑,有个男生,也好照应。”

    “她的重要意义体现在每个月除了方便面不知道还能吃什么的时候。”

    “他的重要意义体现在每次保险丝断了,煤气罐没气了的时候……”

    经典镜头:

    1.他管他的房间叫男生宿舍,她管她的房间叫女生宿舍,其他都是公用。下水道坏了,即使他正沉迷于游戏机,也一叫就到。外面暴雨,无法出去吃饭,哄她两句,许诺有钱请她吃大餐,保证一会就有两菜一汤热腾腾地送上来。

    2.晚上要举行party了,她跟他商量道:“可能朋友比较多,我的屋子里放不了那么多人,能不能腾出点空间给我?”他一口答应,说:“下次做好吃的给我就行了,聚会那天我会自动消失,什么时候散会了给我发个短信……”

    关系透析:

    相对女女同租而言,男女合住带来的更多是愉快、信任和放松的感觉。跟办公室里“男女搭配,干活不累”的意义一样,此类新房客关系,充满了另一意义上的情趣感。调查显示,大多数异性合租的女性都认为:男性不会和女性斤斤计较,房间的大小、朝向以及卫生间谁用多了,谁用少了等细节问题都不会在意,女人和女人之间的情况就复杂得多了,严重的甚至会闹到不欢而散,朋友反目。真正的男女合租彼此尊重,保持距离,又可以互相帮助,对双方来说,既体验到了异性的大多优点,又避免了彼此猜疑、独占和斤斤计较的麻烦。

    潜在危机:

    房子本身就已经十分暧昧,单身男女共住一房,即使并非一室,也已经非常非常接近。回家的人,往往会将自己还原到本真,随意的、自由的、散漫的,甚至丑陋的生活细节都暴露在彼此眼前,固然有因生活方式十分接近而发展为相爱的,但毕竟还是一对有距离的男女。合租房子的异性很容易发展成情侣,由合租演化为同居。但是如果因为一时的盲目,或者带着解决个人问题的心态来寻求合住,就有可能被别有用心的人利用,伤了感情,也搅乱了生活。

    暧昧关系之五:性伴侣

    暧昧指数:*****

    清白指数:*

    招牌口号:“只需要陪伴不需要相爱。”

    “心灵的空虚有很多解决的办法,但身体的饥渴,却无可奈何,所以,我需要性伴侣。”

    经典镜头:

    1.周五快下班的时候,她的手机响了,他的声音响起来:“这个周末你方便吗?”她想了想:“我想想看,喔,不行,我有个朋友要从广州过来看我,恐怕你不方便过来。”

    他很干脆,笑笑说:“好吧,祝你周末愉快,想我了就call我。”

    2.每个固定时间,他都会如期至约,接她下班吃顿饭,然后去他的公寓或者她的宿舍,春宵一宿,然后告别。她甚至连他的工作情况都一无所知,惟一能确定的是,他是个不错的性伙伴。

    关系透析:

    怀特.米尔斯在《私情缠绕》中说:“现代人的一个特征是像找寻财富一样地渴望不为人所知的亲密私情,在适当的时间出现和停止。”

    如今的性伴侣的含义里,除了解决生理问题外,更多的是对自己的安慰和对现实的逃避。毕竟都是害怕寂寞,更害怕别人知道他们寂寞的人。我们需要爱,也不可以没有性。大多数时候,性和爱是一样重要的。有个性伙伴,至少有了身体的温暖,可以暂时忘却心灵的孤寂。

    潜在危机:

    罗素早已经一语道破:“爱情能使我们整个的生命更新,正如大旱之后的甘霖对于植物一样。没有爱的性行为,却完全没有这等力量。一刹欢娱过后,剩下的是疲倦,厌恶,以及生命的空虚之感。”

    暧昧关系之六:兼职家长(司机、保镖、保姆……)

    暧昧指数:****

    清白指数:**

    招牌口号:“反正他有车,正好顺路送我而已。”

    “男人请女人吃饭从来都是正常的事情,他愿请,我愿吃,别人看什么看!”

    经典镜头:

    1.他有一辆奥迪;他在一家大公司里身居高位;他有相爱的女朋友。不记得是怎么认识他的,总之,好像从某天晚上他主动送她回家后,从知道彼此的公司在一条线路上后,每天接送她,便成了他的习惯。

    2.每到下班时分,如果男朋友没空,她就会在办公室里大声嚷嚷:“今天谁请我吃饭呀!”然后矛头就对准了其中一个男同事,娇滴滴地哄他,摇着他的肩膀:“还是你请我吧,好吗?”

    关系透析:

    他们的关系多是从工作合作方面发展起来的。很多时候,多是由女性主动,认定被男人照顾是天经地义的,而男人的“英雄主义”心态,又令他们大多时候都倍感荣幸。这种关系中,利用的成分往往比较多。

    潜在危机:

    因为这样的关系是建立在单纯的“互相照顾,互相利用”之上,男女双方往往缺乏共同语言。一旦照顾失败,或者“服务”缺乏周到,容易导致关系恶化。此外,一些绯闻也多出现在这种“兼职家长”身边,也许你只是搭了谁谁的顺风车而已,但别人怎么知道,车的终点是哪里呢?

    暧昧关系之七:约会拍档

    暧昧指数:****

    清白指数:**

    招牌口号:“一个人玩有什么好玩,我不过是给自己找了个玩伴而已。”

    “他知道哪里有最好吃的东西,有最好玩最新奇的玩意,能嗅到这个城市的‘兴奋点’,与其随便找个人陪我,不如找个会玩的。”

    经典镜头:

    1.每到影院公布新一期的大片播放周期,她就会立刻致电给他,让他准备好爆米花和可乐,陪她去看电影,她并不介意是她买票还是他请客,也不介意通宵研究观后感,她觉得,除了他,没有人更适合当这方面的知音了。

    2.每次和论坛上的一帮朋友聚会,他都会叫上她。虽然她从不去这个论坛,也对他们所谈的所谓文化话题缺乏兴趣。他就是喜欢叫上她作陪,一起猜拳喝酒。仿佛她的职责就是,当他在饭桌上谈笑风声的时候,负责大吃大喝捞回本钱似的。

    关系透析:

    他们不是情侣,却常常约会、旅游、喝酒、看电影……是固定的约会搭档。从通俗意义上说,也可以理解成“酒肉朋友”。他们往往在某一个兴趣爱好或者一种行为习惯方面拥有共同的兴趣,并且每次约会都可以兴致勃勃,高兴而来,高兴而去。也属于一个要陪,一个愿陪的姜太公钓鱼模式。

    看来,新新男女关系已经被划分得越来越细,需要按照职责、爱好、具体功能等各方面来划分了。而个中的微妙之处就在于——物以类聚。

    潜在危机:

    如果约会拍档的关系足够稳定、确定,建立在共同的兴趣爱好的基础上的话,可以称之为志同道合。如果只是一方寂寞了需要消遣,而另一个属于纯粹的“n陪”的话,那么这样的关系就有说不清道不明的嫌疑了。或者就是愿陪的那方在暗恋要陪的那方,这无疑是在伤害其中一人的感情,也耗费了另一人的光阴

娱乐 :: Comment (0) :: Trackbacks (1)

Health Tips

chlchen2000 | 2005/October/10/14:31

1. Three half minutes after wake up:
- stay lying on the bed for 1st half minute
- then sit up on the bed for another half minute
- then move your legs to hang on the floor while you are still sitting on the bed for the last half minute

=> give your heart have sufficient warm up time to minimize heart attack & brain vessels venting.

2. Three half hours:
- running in the morning for half hour
- take a nap in the afternoon ( after lunch ) far half hour
- last half hour is slow walking at evening

=> keep exercise

3. Four principals:
- reasonable meal
- adequate exercise
- no smoking & limit alcohol ( one glass of beer is good but more than that would becomes damaging)
- psychological balance

=> lengthen your life by 10 years


4. Soup before meal => fitness
Soup after meal => fatness

5. Keep drinking milk (one glass per day ) with appropriate vitamins ( A, multi B, C etc )
=> milk can be a good supplement of calcium & help avoid bone disease


6. Drink green tea (slow the aging effect => long lives )

7. Eat oat - reduce cholesterol

8. Standard body weight = ( Height in cm -100) x 0.9
=> Height in cm -105

9. Walking is the best exercise
- min 30 minutes per time
- min 3 km per time
- min 5 times / week

10. Max heart beat rate = 170 - your ages

11. 500g vegetation food ( including fruit ) per day

12. one tomato per day => reduce chance of prostate gland cancer by 45%

13. eat only up to 70~80% full i.e. when you leave the table, you still feel a little bit hungry

14. Balanced meal:
30% protein ( prefer fish & soya bean, soya bean is good for near old woman )
70% carbohydrate ( vegetarian food )

娱乐 :: Comment (0) :: Trackbacks (1059)


The second address for this blog:http://www.megaentry.com/1
Power by