Mark's profileMark's spacePhotosBlogLists Tools Help

Blog


    June 12

    linux进程管理及作业控制(一)  

    进程管理及作业控制(一)  

    Linux是一个多任务的操作系统,系统上同时运行着多个进程,正在执行的一个或多个相关进程称为一个作业。使用作业控制,用户可以同时运行多个作业,并在需要时在作业之间进行切换。本章详细介绍进程管理及作业控制的命令,包括启动进程、查看进程、调度作业的命令。

    进程及作业的概念

    Linux是一个多用户多任务的操作系统。多用户是指多个用户可以在同一时间使用计算机系统;多任务是指Linux可以同时执行几个任务,它可以在还未执行完一个任务时又执行另一项任务。

    操作系统管理多个用户的请求和多个任务。大多数系统都只有一个CPU和一个主存,但一个系统可能有多个二级存储磁盘和多个输入/输出设备。操作系统管理这些资源并在多个用户间共享资源,当您提出一个请求时,给您造成一种假象,好象系统只被您独自占用。而实际上操作系统监控着一个等待执行的任务队列,这些任务包括用户作业、操作系统任务、邮件和打印作业等。操作系统根据每个任务的优先级为每个任务分配合适的时间片,每个时间片大约都有零点几秒,虽然看起来很短,但实际上已经足够计算机完成成千上万的指令集。每个任务都会被系统运行一段时间,然后挂起,系统转而处理其他任务;过一段时间以后再回来处理这个任务,直到某个任务完成,从任务队列中去除。

    Linux系统上所有运行的东西都可以称之为一个进程。每个用户任务、每个系统管理守护进程,都可以称之为进程。Linux用分时管理方法使所有的任务共同分享系统资源。我们讨论进程的时候,不会去关心这些进程究竟是如何分配的,或者是内核如何管理分配时间片的,我们所关心的是如何去控制这些进程,让它们能够很好地为用户服务。

    进程的一个比较正式的定义是:在自身的虚拟地址空间运行的一个单独的程序。进程与程序是有区别的,进程不是程序,虽然它由程序产生。程序只是一个静态的指令集合,不占系统的运行资源;而进程是一个随时都可能发生变化的、动态的、使用系统运行资源的程序。而且一个程序可以启动多个进程。

    Linux操作系统包括三种不同类型的进程,每种进程都有自己的特点和属性。

     

    *

    交互进程——由一个shell启动的进程。交互进程既可以在前台运行,也可以在后台运行。
    *

    批处理进程——这种进程和终端没有联系,是一个进程序列。
    *

    监控进程(也称守护进程)——Linux系统启动时启动的进程,并在后台运行。

    上述三种进程各有各的作用,使用场合也有所不同。

    进程和作业的概念也有区别。一个正在执行的进程称为一个作业,而且作业可以包含一个或多个进程,尤其是当使用了管道和重定向命令。例如“nroff -man ps.1|grep kill|more”这个作业就同时启动了三个进程。

    作业控制指的是控制正在运行的进程的行为。比如,用户可以挂起一个进程,等一会儿再继续执行该进程。shell将记录所有启动的进程情况,在每个进程过程中,用户可以任意地挂起进程或重新启动进程。作业控制是许多shell(包括bash和tcsh)的一个特性,使用户能在多个独立作业间进行切换。

    一般而言,进程与作业控制相关联时,才被称为作业。

    在大多数情况下,用户在同一时间只运行一个作业,即它们最后向shell键入的命令。但是使用作业控制,用户可以同时运行多个作业,并在需要时在这些作业间进行切换。这会有什么用途呢?例如,当用户编辑一个文本文件,并需要中止编辑做其他事情时,利用作业控制,用户可以让编辑器暂时挂起,返回shell提示符开始做其他的事情。其他事情做完以后,用户可以重新启动挂起的编辑器,返回到刚才中止的地方,就象用户从来没有离开编辑器一样。这只是一个例子,作业控制还有许多其他实际的用途。

    启动进程

    键入需要运行的程序的程序名,执行一个程序,其实也就是启动了一个进程。在Linux系统中每个进程都具有一个进程号,用于系统识别和调度进程。启动一个进程有两个主要途径:手工启动和调度启动,后者是事先进行设置,根据用户要求自行启动。

    手工启动

    由用户输入命令,直接启动一个进程便是手工启动进程。但手工启动进程又可以分为很多种,根据启动的进程类型不同、性质不同,实际结果也不一样,下面分别介绍。

    1. 前台启动

    这或许是手工启动一个进程的最常用的方式。一般地,用户键入一个命令“ls –l”,这就已经启动了一个进程,而且是一个前台的进程。这时候系统其实已经处于一个多进程状态。或许有些用户会疑惑:我只启动了一个进程而已。但实际上有许多运行在后台的、系统启动时就已经自动启动的进程正在悄悄运行着。还有的用户在键入“ls –l”命令以后赶紧使用“ps –x”查看,却没有看到ls进程,也觉得很奇怪。其实这是因为ls这个进程结束太快,使用ps查看时该进程已经执行结束了。如果启动一个比较耗时的进程:

    find / -name fox.jpg

    然后再把该进程挂起,使用ps查看,就会看到一个find进程在里面。

     

     

    2. 后台启动

    直接从后台手工启动一个进程用得比较少一些,除非是该进程甚为耗时,且用户也不急着需要结果的时候。假设用户要启动一个需要长时间运行的格式化文本文件的进程。为了不使整个shell在格式化过程中都处于“瘫痪”状态,从后台启动这个进程是明智的选择。

    [例1]

    $ troff –me notes > note_form &

    [1] 4513

    $

    由上例可见,从后台启动进程其实就是在命令结尾加上一个&号。键入命令以后,出现一个数字,这个数字就是该进程的编号,也称为PID,然后就出现了提示符。用户可以继续其他工作。

    上面介绍了前、后台启动的两种情况。实际上这两种启动方式有个共同的特点,就是新进程都是由当前shell这个进程产生的。也就是说,是shell创建了新进程,于是就称这种关系为进程间的父子关系。这里shell是父进程,而新进程是子进程。一个父进程可以有多个子进程,一般地,子进程结束后才能继续父进程;当然如果是从后台启动,那就不用等待子进程结束了。

    一种比较特殊的情况是在使用管道符的时候。例如:

    nroff -man ps.1|grep kill|more

    这时候实际上是同时启动了三个进程。请注意是同时启动的,所有放在管道两边的进程都将被同时启动,它们都是当前shell的子程序,互相之间可以称为兄弟进程。

    以上介绍的是手工启动进程的一些内容,作为一名系统管理员,很多时候都需要把事情安排好以后让其自动运行。因为管理员不是机器,也有离开的时候,所以有些必须要做的工作而恰好管理员不能亲自操作,这时候就需要使用调度启动进程了。

    调度启动

    有时候需要对系统进行一些比较费时而且占用资源的维护工作,这些工作适合在深夜进行,这时候用户就可以事先进行调度安排,指定任务运行的时间或者场合,到时候系统会自动完成这一切工作。

    要使用自动启动进程的功能,就需要掌握以下几个启动命令。

    at命令

    用户使用at命令在指定时刻执行指定的命令序列。也就是说,该命令至少需要指定一个命令、一个执行时间才可以正常运行。at命令可以只指定时间,也可以时间和日期一起指定。需要注意的是,指定时间有个系统判别问题。比如说:用户现在指定了一个执行时间:凌晨3:20,而发出at命令的时间是头天晚上的20:00,那么究竟是在哪一天执行该命令呢?如果用户在3:20以前仍然在工作,那么该命令将在这个时候完成;如果用户3:20以前就退出了工作状态,那么该命令将在第二天凌晨才得到执行。下面是at命令的语法格式:

    at [-V] [-q 队列] [-f 文件名] [-mldbv] 时间

    at -c 作业 [作业...]

    at允许使用一套相当复杂的指定时间的方法,实际上是将POSIX.2标准扩展了。它可以接受在当天的hh:mm(小时:分钟)式的时间指定。如果该时间已经过去,那么就放在第二天执行。当然也可以使用midnight(深夜),noon(中午),teatime(饮茶时间,一般是下午4点)等比较模糊的词语来指定时间。用户还可以采用12小时计时制,即在时间后面加上AM(上午)或者PM(下午)来说明是上午还是下午。

    也可以指定命令执行的具体日期,指定格式为month day(月 日)或者mm/dd/yy(月/日/年)或者dd.mm.yy(日.月.年)。指定的日期必须跟在指定时间的后面。

    上面介绍的都是绝对计时法,其实还可以使用相对计时法,这对于安排不久就要执行的命令是很有好处的。指定格式为:now + count time-units ,now就是当前时间,time-units是时间单位,这里可以是 minutes(分钟)、hours(小时)、days(天)、weeks(星期)。count是时间的数量,究竟是几天,还是几小时,等等。

    还有一种计时方法就是直接使用today(今天)、tomorrow(明天)来指定完成命令的时间。下面通过一些例子来说明具体用法。

    [例2] 指定在今天下午5:30执行某命令。假设现在时间是中午12:30,1999年2月24日,其命令格式如下:

    at 5:30pm

    at 17:30

    at 17:30 today

    at now + 5 hours

    at now + 300 minutes

    at 17:30 24.2.99

    at 17:30 2/24/99

    at 17:30 Feb 24

     

    以上这些命令表达的意义是完全一样的,所以在安排时间的时候完全可以根据个人喜好和具体情况自由选择。一般采用绝对时间的24小时计时法可以避免由于用户自己的疏忽造成计时错误的情况发生,例如上例可以写成:

    at 17:30 2/24/99

    这样非常清楚,而且别人也看得懂。

    对于at命令来说,需要定时执行的命令是从标准输入或者使用-f选项指定的文件中读取并执行的。如果at命令是从一个使用su命令切换到用户shell中执行的,那么当前用户被认为是执行用户,所有的错误和输出结果都会送给这个用户。但是如果有邮件送出的话,收到邮件的将是原来的用户,也就是登录时shell的所有者。

    [例3]

    $ at -f work 4pm + 3 days

    在三天后下午4点执行文件work中的作业。

    $ at -f work 10am Jul 31

    在7月31日上午10点执行文件work中的作业。

    在任何情况下,超级用户都可以使用这个命令。对于其他用户来说,是否可以使用就取决于两个文件:/etc/at.allow和/etc/at.deny。如果/etc/at.allow文件存在的话,那么只有在其中列出的用户才可以使用at命令;如果该文件不存在,那么将检查/etc/at.deny文件是否存在,在这个文件中列出的用户均不能使用该命令。如果两个文件都不存在,那么只有超级用户可以使用该命令;空的/etc/at.deny文件意味着所有的用户都可以使用该命令,这也是默认状态。

    下面对命令中的参数进行说明。

    -V 将标准版本号打印到标准错误中。

    -q queue 使用指定的队列。队列名称是由单个字母组成,合法的队列名可以由a-z或者A-Z。a队列是at命令的默认队列。

    -m 作业结束后发送邮件给执行at命令的用户。

    -f file 使用该选项将使命令从指定的file读取,而不是从标准输入读取。

    -l atq命令的一个别名。该命令用于查看安排的作业序列,它将列出用户排在队列中的作业,如果是超级用户,则列出队列中的所有工作。

    命令的语法格式如下:

    atq [-V] [-q 队列] [-v]

    -d atrm 命令的一个别名。该命令用于删除指定要执行的命令序列,语法格式如下:

    atrm [-V] 作业 [作业...]

    -c 将命令行上所列的作业送到标准输出。

    [例4] 找出系统中所有以txt为后缀名的文件,并且进行打印。打印结束后给用户foxy发出邮件通知取件。指定时间为十二月二十五日凌晨两点。

    首先键入:

    $ at 2:00 12/25/99

    然后系统出现at>提示符,等待用户输入进一步的信息,也就是需要执行的命令序列:

    at> find / -name “*.txt”|lpr

    at> echo “foxy:All texts have been printed.You can take them over.Good day!River” |mail -s ”job done” foxy

    输入完每一行指令然后回车,所有指令序列输入完毕后,使用<Ctrl+d>组合键结束at命令的输入。这时候屏幕将出现如下信息:

    warning:command will be executed using /bin/sh.

    job 1 at 1999-12-25 02:00

    提醒用户将使用哪个shell来执行该命令序列。

    实际上如果命令序列较长或者经常被执行的时候,一般都采用将该序列写到一个文件中,然后将文件作为at命令的输入来处理。这样不容易出错。

     

    [例5] 上面的例子可以修改如下:

    将命令序列写入到文件/tmp/printjob,语句为:

    $ at -f /tmp/printjob 2:00 12/25/99

    这样一来,at命令将使用文件中的命令序列,屏幕显示如下:

    Warning:command will be executed using /bin/sh.

    job 2 at 1999-12-25 02:00

    当然也可以采用以下命令:

    $ at< /tmp/printjob 2:00 12/25/99

    来完成同样的任务。也就是使用输入重定向的办法将文件定向为命令输入。

    batch命令

    batch 用低优先级运行作业,该命令几乎和at命令的功能完全相同,唯一的区别在于,at命令是在指定时间,很精确的时刻执行指定命令;而batch却是在系统负载较低,资源比较空闲的时候执行命令。该命令适合于执行占用资源较多的命令。

    batch命令的语法格式也和at命令十分相似,即

    batch [-V] [-q 队列] [-f 文件名] [-mv] [时间]

    具体的参数解释请参考at命令。一般地说,不用为batch命令指定时间参数,因为batch本身的特点就是由系统决定执行任务的时间,如果用户再指定一个时间,就失去了本来的意义。

    [例6] 使用例4,键入:

    $ batch

    at> find / -name *.txt|lpr

    at> echo “foxy:All texts have been printed.You can take them over.Good day!River” |mail -s ”job done” foxy

    现在这个命令就会在合适的时间进行了,进行完后会发回一个信息。

    仍然使用<Ctrl+d>组合键来结束命令输入。而且batch和at命令都将自动转入后台,所以启动的时候也不需要加上&符号。

    cron命令

    前面介绍的两条命令都会在一定时间内完成一定任务,但是要注意它们都只能执行一次。也就是说,当指定了运行命令后,系统在指定时间完成任务,一切就结束了。但是在很多时候需要不断重复一些命令,比如:某公司每周一自动向员工报告头一周公司的活动情况,这时候就需要使用cron命令来完成任务了。

    实际上,cron命令是不应该手工启动的。cron命令在系统启动时就由一个shell脚本自动启动,进入后台(所以不需要使用&符号)。一般的用户没有运行该命令的权限,虽然超级用户可以手工启动cron,不过还是建议将其放到shell脚本中由系统自行启动。

    首先cron命令会搜索/var/spool/cron目录,寻找以/etc/passwd文件中的用户名命名的crontab文件,被找到的这种文件将载入内存。例如一个用户名为foxy的用户,它所对应的crontab文件就应该是/var/spool/cron/foxy。也就是说,以该用户命名的crontab文件存放在/var/spool/cron目录下面。cron命令还将搜索/etc/crontab文件,这个文件是用不同的格式写成的。

    cron启动以后,它将首先检查是否有用户设置了crontab文件,如果没有就转入“休眠”状态,释放系统资源。所以该后台进程占用资源极少。它每分钟“醒”过来一次,查看当前是否有需要运行的命令。命令执行结束后,任何输出都将作为邮件发送给crontab的所有者,或者是/etc/crontab文件中MAILTO环境变量中指定的用户。

    上面简单介绍了一些cron的工作原理,但是cron命令的执行不需要用户干涉;需要用户修改的是crontab中要执行的命令序列,所以下面介绍crontab命令。

    crontab命令

    crontab命令用于安装、删除或者列出用于驱动cron后台进程的表格。也就是说,用户把需要执行的命令序列放到crontab文件中以获得执行。每个用户都可以有自己的crontab文件。下面就来看看如何创建一个crontab文件。

    在/var/spool/cron下的crontab文件不可以直接创建或者直接修改。crontab文件是通过crontab命令得到的。现在假设有个用户名为foxy,需要创建自己的一个crontab文件。首先可以使用任何文本编辑器建立一个新文件,然后向其中写入需要运行的命令和要定期执行的时间。

    然后存盘退出。假设该文件为/tmp/test.cron。再后就是使用crontab命令来安装这个文件,使之成为该用户的crontab文件。键入:

    crontab test.cron

    这样一个crontab 文件就建立好了。可以转到/var/spool/cron目录下面查看,发现多了一个foxy文件。这个文件就是所需的crontab 文件。用more命令查看该文件的内容可以发现文件头有三行信息:

    #DO NOT EDIT THIS FILE -edit the master and reinstall.

    #(test.cron installed on Mon Feb 22 14:20:20 1999)

    #(cron version --$Id:crontab.c,v 2.13 1994/01/17 03:20:37 vivie Exp $)

    大概意思是:

    #切勿编辑此文件——如果需要改变请编辑源文件然后重新安装。

    #test.cron文件安装时间:14:20:20 02/22/1999

    如果需要改变其中的命令内容时,还是需要重新编辑原来的文件,然后再使用crontab命令安装。

    可以使用crontab命令的用户是有限制的。如果/etc/cron.allow文件存在,那么只有其中列出的用户才能使用该命令;如果该文件不存在但cron.deny文件存在,那么只有未列在该文件中的用户才能使用crontab命令;如果两个文件都不存在,那就取决于一些参数的设置,可能是只允许超级用户使用该命令,也可能是所有用户都可以使用该命令。

    crontab命令的语法格式如下:

    crontab [-u user] file

    crontab [-u user]{-l|-r|-e}

     

    第一种格式用于安装一个新的crontab 文件,安装来源就是file所指的文件,如果使用“-”符号作为文件名,那就意味着使用标准输入作为安装来源。

    -u 如果使用该选项,也就是指定了是哪个具体用户的crontab 文件将被修改。如果不指定该选项,crontab 将默认是操作者本人的crontab ,也就是执行该crontab 命令的用户的crontab 文件将被修改。但是请注意,如果使用了su命令再使用crontab 命令很可能就会出现混乱的情况。所以如果是使用了su命令,最好使用-u选项来指定究竟是哪个用户的crontab文件。

    -l 在标准输出上显示当前的crontab。

    -r 删除当前的crontab文件。

    -e 使用VISUAL或者EDITOR环境变量所指的编辑器编辑当前的crontab文件。当结束编辑离开时,编辑后的文件将自动安装。

    [例7]

    # crontab -l #列出用户目前的crontab。

    10 6 * * * date

    0 */2 * * * date

    0 23-7/2,8 * * * date

    #

    在crontab文件中如何输入需要执行的命令和时间。该文件中每行都包括六个域,其中前五个域是指定命令被执行的时间,最后一个域是要被执行的命令。每个域之间使用空格或者制表符分隔。格式如下:

    minute hour day-of-month month-of-year day-of-week commands

    第一项是分钟,第二项是小时,第三项是一个月的第几天,第四项是一年的第几个月,第五项是一周的星期几,第六项是要执行的命令。这些项都不能为空,必须填入。如果用户不需要指定其中的几项,那么可以使用*代替。因为*是统配符,可以代替任何字符,所以就可以认为是任何时间,也就是该项被忽略了。在表4-1中给出了每项的合法范围。

     

    表4-1 指定时间的合法范围

    时间

    合法值

    minute

    00-59

    hour

    00-23,其中00点就是晚上12点

    day-of-month

    01-31

    month-of-year

    01-12

    day-of-week

    0-6,其中周日是0

     

    这样用户就可以往crontab 文件中写入无限多的行以完成无限多的命令。命令域中可以写入所有可以在命令行写入的命令和符号,其他所有时间域都支持列举,也就是域中可以写入很多的时间值,只要满足这些时间值中的任何一个都执行命令,每两个时间值中间使用逗号分隔。

    [例8]

    5,15,25,35,45,55 16,17,18 * * * command

    这就是表示任意天任意月,其实就是每天的下午4点、5点、6点的5 min、15 min、25 min、35 min、45 min、55 min时执行命令。

    [例9] 在每周一,三,五的下午3:00系统进入维护状态,重新启动系统。那么在crontab 文件中就应该写入如下字段:

    00 15 * * 1,3,5 shutdown -r +5

    然后将该文件存盘为foxy.cron,再键入crontab foxy.cron安装该文件。

    [例10] 每小时的10分,40分执行用户目录下的innd/bbslin这个指令:

    10,40 * * * * innd/bbslink

    [例11] 每小时的1分执行用户目录下的bin/account这个指令:

    1 * * * * bin/account

    [例12] 每天早晨三点二十分执行用户目录下如下所示的两个指令(每个指令以;分隔):

    20 3 * * * (/bin/rm -f expire.ls logins.bad;bin/expire>expire.1st)

    [例13] 每年的一月和四月,4号到9号的3点12分和3点55分执行/bin/rm -f expire.1st这个指令,并把结果添加在mm.txt这个文件之后(mm.txt文件位于用户自己的目录位置)。

    12,55 3 4-9 1,4 * /bin/rm -f expire.1st>>mm.txt

    [例14] 我们来看一个超级用户的crontab文件:

    #Run the ‘atrun’ program every minutes

    #This runs anything that’s due to run from ‘at’.See man ‘at’ or ‘atrun’.

    0,5,10,15,20,25,30,35,40,45,50,55 * * * * /usr/lib/atrun

    40 7 * * * updatedb

    8,10,22,30,39,46,54,58 * * * * /bin/sync

    进程的挂起及恢复命令bg、fg

    作业控制允许将进程挂起并可以在需要时恢复进程的运行,被挂起的作业恢复后将从中止处开始继续运行。只要在键盘上按<ctrl+z>,即可挂起当前的前台作业。

    [例15]

    $ cat > text.file

    <ctrl+z>

    [1] + stopped cat > text.file

    $ jobs

    [1]+ stopped cat > text.file

    在键盘上按<ctrl+z>后,将挂起当前执行的命令cat。使用jobs命令可以显示shell的作业清单,包括具体的作业、作业号以及作业当前所处的状态。

    恢复进程执行时,有两种选择:用fg命令将挂起的作业放回到前台执行;用bg命令将挂起的作业放到后台执行。

    [例16] 用户正在使用Emacs,突然需要查看系统进程情况。就首先使用<Ctrl+z>组合键将Emacs进程挂起,然后使用bg命令将其在后台启动,这样就得到了前台的操作控制权,接着键入“ps –x”查看进程情况。查看完毕后,使用fg命令将Emacs带回前台运行即可。其命令格式为:

    <Ctrl+z>

    $ bg emacs

    $ ps –x

    $ fg emacs

    默认情况下,fg和bg命令对最近停止的作业进行操作。如果希望恢复其他作业的运行,可以在命令中指定要恢复作业的作业号来恢复该作业。例如:

    $ fg 1

    cat > text.file

    灵活使用上述命令,将给自己带来很大的方便。






    用java调用linux的操作系统命令

    import   java.io.BufferedInputStream;  
      import   java.io.IOException;  
       
      public   class   ExecLs   {  
       
      static   public   void   main(String[]   args)   {  
      String   cmd   =   "ls"  
       
      try   {  
      Process   ps   =   Runtime.getRuntime().exec(cmds);  
      System.out.print(loadStream(ps.getInputStream()));  
      System.err.print(loadStream(ps.getErrorStream()));  
      }   catch(IOException   ioe)   {  
      ioe.printStackTrace();  
      }  
      }  
       
      //   read   an   input-stream   into   a   String  
      static   String   loadStream(InputStream   in)   throws   IOException   {  
      int   ptr   =   0;  
      in   =   new   BufferedInputStream(in);  
      StringBuffer   buffer   =   new   StringBuffer();  
      while(   (ptr   =   in.read())   !=   -1   )   {  
      buffer.append((char)ptr);  
      }  
      return   buffer.toString();  
      }  
       
      }
    May 14

    有关raw socket的一些知识

    有关raw socket的一些知识 众所周知,通过socket编程,我们能够实现机器之间的通信.在TCP/IP协议簇(PF_INET)中,可以建立面向连接的SOCK_STREAM类型的socket,非连接的SOCK_DGRAM类型的socket.事实上,在所有的网络程序中,也是这两种socket用的最为广泛.除此之外,还有一些不常用的socket类型,它们却是在某些网络通信中担当重要的角色.这里要讲的就是这么一种socket,称之为raw socket.raw socket的作用主要在三个方面: 1.通过raw socket来接受发向本机的ICMP,IGMP协议包,或者用来发送这些协议包. 2.接受发向本机的但TCP/IP栈不能够处理的IP包. 3.用来发送一些自己制定源地址特殊作用的IP包(自己写IP头,TCP头等等) 我们知道,平时我们想看一看网络是否通达,就用ping命令测试一些.ping 命令用的是ICMP协议.因此,我们不能够通过建立一个SOCK_STREAM或SOCK_DGRAM来发送这个包,只能够自己亲自来构建ICMP包来发送.这是一种情况.另一种情况是:现在许多操作系统在实现网络部分的时候,通常只实现了常用的几种协议, 如tcp,udp,icmp等,但象其它的如ospf,ggp等协议,操作系统往往没有实现,如果自己有必要编写位于其上的应用,就必须借助raw socket来实现,这是因为操作 系统遇到自己不能够处理的数据包(ip头中的protocol所指定的上层协议不能处理).就将这个包交给raw socket.而最后一种使用raw socket的目的主要是用来构建一些特殊的协议头,比如我们想对某台机器进行denial of service类型的攻击,但是有不想留下痕迹,让别人知道IP包的来源,这时候就可以使用rawsocket来发送这些伪造源地址信息的包,这其实也是这种攻击所采用的主要技术手段.当然了,我说的是HACKER行为,之所以想要处理这些特殊的IP包,通常也是为了诊断网络的目的. raw socket的建立是通过如下方式的: sockfd = socket(PF_INET, SOCK_RAW, protocol); 第一个参数就不必讲了,第二个参数说明建立的是一个raw socket,第三个参数倒是需要详细解说一下.这里分三种情况: 1.参数protocol用来指明所要接收的协议包,如果是象IPPROTO_TCP(6)这种非0,非255的协议,则内核碰到ip头中 protocol域和创建socket所使用参数protocol相同的IP包,就会交给这个rawsocket来处理.因此,一般说来,要想接收什么样的数据包,就应该在参数protocol里来指定相应的协议.当内核向此raw socket交付数据包的时候,是包括整个IP头的,并且已经是重组好的IP包. 如下: --------------------------------------------------------------- |ip header|tcp header(or x header)| data | --------------------------------------------------------------- 用recvfrom收到的数据包括一个IP头,一个相应的协议头,然后是数据(数据也可以为空,就看实际情况了). 但当我们发送IP包的时候,却不用亲自处理IP包头,只需要填充参数protocol所指定的相应的协议头即可.也就是说,用sendto的时候,我们提供给它的缓冲区数据是从IP包头的第一个字节开始,如下,只需要构造这么一个缓冲区就可以了. -------------------------------------------------------------- |tcp header(or udp header or x header)| data | -------------------------------------------------------------- 如果想自己也想亲自处理IP头,则需要IP_HDRINCL的socket选项.如下: int flag = 1; setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &flag, sizeof(int)); 这样,发送时所要提供的缓冲区有成如下形式: --------------------------------------------------------------- |ip header|tcp header(or x header)| data | --------------------------------------------------------------- 但是,即时是这种情况,在我们发送IP包的时候.也不是填充ip头的所有字段,而是应该将ip头的id(identification)字段设置为0,表示让内核来处理这个字段.同时,内核还帮你完成ip头的校验和的计算,并随后填充check字段. 2.如果protocol是IPPROTO_RAW(255),这时候,这个socket只能用来发送IP包,而不能接收任何数据.发送的数据需要自己填充IP包头,并且自己计算校验和. 3.对于protocol为0(IPPROTO_IP)的raw socket. 在linux和sco unix上是不允许建立的.我没有再试过其他操作系统,谁能给我一个答案:) 对于raw socket,只有root权限才能够创建. 这里对raw socket总结一下: 当内核接收到IP包的时候,首先检查ip包的protocol域,当存在与此域匹配的raw socket时,就将包先传给此raw socket,然后交给相应的上层协议处理.交给raw socket的数据是包括IP头并且已经重组完成后的.当使用raw socket发送包的时候,如果raw socket创建时的protocol不是0或255,并且没有设置IP_HDRINCL选项,则发送的数据不包括IP头.如果此选项置位,则需要自己构件IP头.如果创建protocol为255的raw socket,此rawsocket只能用来发送包括IP头,自己构建IP包. 附录: IP头结构: struct iphdr |-------|--------|---------------|-------------------------------| |version| ihl | tos | tot_len | |-------|--------|---------------|-------------------------------| | id | | frag_off | |----------------|---------------|-------------------------------| | ttl | protocol | check | |----------------|---------------|-------------------------------| | saddr | |----------------------------------------------------------------| | daddr | |----------------------------------------------------------------| 参考书籍: Unix Network Programming (Volume 1 SECOND EDITION P655-P702)
    April 04

    nesC Module

    Module 问题
    ledi 发表于 2006-5-16 19:29:00

    接口PeriodicReaderC:
    module PeriodicReaderC {
    provides interface StdControl;
    uses interface Timer<TMilli>;
    uses interface Read<uint16_t>;
    }
    implementation {
    uint16_t lastVal = 0;
    command error_t StdControl.start() {
    return call Timer.startPeriodic(1024);
    }
    command error_t StdControl.stop() {
    return call Timer.stop();
    }
    event void Timer.fired() {
    call Read.read();
    }
    event void Read.readDone(error_t err, uint16_t val) {
    if (err == SUCCESS) {
    lastVal = val;
    }
    }
    }
    知识点:在provides中提供的命令与使用的event的必须在implementation中实现。
    问题:1 在此接口中command error_t StdControl.start()
            与return call Timer.startPeriodic(1024)的关系是如何确定的?
          2 error_t的数据类型定义的具体含义是什么??

    March 20

    BNF范式和EBNF范式

    BNF范式和EBNF范式

    关键字: BNF 范式
    1、什么是BNF范式,什么又是EBNF范式?(在学习中经常会碰到用BNF范式描述的规则,老是忘记每个符号确切的作用,现在把他们一一罗列如下,亲手记录的东西应该能记住吧。。。-__-|||)
    答:巴科斯范式及其扩展(BNF & Augmented BNF)
    1)巴科斯范式:巴科斯范式(BNF: Backus-Naur Form 的缩写)是由 John Backus 和 Peter Naur 首先引入的用来描述计算机语言语法的符号集。现在,几乎每一位新编程语言书籍的作者都使用巴科斯范式来定义编程语言的语法规则。
    2)巴科斯范式的内容:
    在双引号中的字("word")代表着这些字符本身。而double_quote用来代表双引号。
    在双引号外的字(有可能有下划线)代表着语法部分。
    < > : 内包含的为必选项。
    [ ] : 内包含的为可选项。
    { } : 内包含的为可重复0至无数次的项。
    | : 表示在其左右两边任选一项,相当于"OR"的意思。
    ::= : 是“被定义为”的意思
    3)扩展的巴科斯范式(Augmented BNF):RFC2234 定义了扩展的巴科斯范式(ABNF)。近年来在Internet的定义中ABNF被广泛使用。ABNF做了更多的改进,比如说,在ABNF中,尖括号不再需要。
    4)EBNF的基本内容:
    "..." : 术语符号
    [...] : 选项:最多出现一次
    {...} : 重复项: 任意次数,包括 0 次
    (...) : 分组
    | : 并列选项,只能选一个
    斜体字: 参数,在其它地方有解释

    例子BNF应用较多,以下给出一个简单例子,这是用BNF来定义的Java语言中的For语句的实例:
    FOR_STATEMENT ::=
    "for" "(" ( variable_declaration |
    ( expression ";" ) | ";" )
    [ expression ] ";"
    [ expression ] ";"
    ")" statement
    August 26

    java的转义字符

    \n 回车(\u000a)
    \t 水平制表符(\u0009)
    \b 空格(\u0008)
    \r 换行(\u000d)
    \f 换页(\u000c)
    \' 单引号(\u0027)
    \" 双引号(\u0022)
    \\ 反斜杠(\u005c)
    \ddd 三位八进制
    \udddd 四位十六进制

    上周发现还有其它需要转义的字符,例如

     String sName = "Java转义字符(补遗)";
     sName = sName.replaceFirst("(补遗)","");
     out.println(sName);

     如果你以为会输出“Java转义字符”,那你就错了,事实上输出“Java转义字符()”,我也很奇怪,以为是中英文括号的问题,可是并不是,我不确定是否转义问题,解决方法是

     sName = sName.replaceFirst("\\(补遗\\)",""); 

    April 23

    MRTG流量监控

    MRTG (Multi Router Traffic Grapher)是一款监控网络流量负载的免费软件,目前利用MRTG已经开发出了各式各样的统计系统:
    1.系统资源负载统计,例如:磁盘空间、CPU负载、内存用量等等
    2.Server流量统计,例如:Mail、DNS、Web、BBS、IRC等等
    3.网络设备流量统计,例如:防火墙、路由器、交换机等等
    4.另类统计,例如:Modem流量、Login人数、联机游戏人数等等。
    MRTG是利用SNMP协议去查询指定有SNMP协议的设备,定时统计其设备的流量或负载,再将统计结果绘成统计图,从统计图上能很容易、直观地就能查出流量或负载。以思科2950为例来说明一下本软件的使用过程:

    一、2950端的配置
    2950端需要将SNMP功能打开(一般网络设备出厂设置是打开SNMP的),并做相应的设置,具体如下:
    telnet 10.10.100.13
    123# conf t
    \\进入特权配置模式
    123(config)# snmp-server community 5haolou RO(此处不是零)
    \\设置SNMP的团体名为5haolou
    123(config)# snmp-server trap-source FastEthernet0/1
    \\以Fa0/1端口为监控源,如果不输,将以设备自身的ROUTER ID作为监控源
    123(config)# snmp-server contact
    qufeng13_2003@126.com
    \\设置管理者的邮箱地址
    123(config)# snmp-server host 10.10.100.201 5haolou
    \\设置管理机的IP地址为10.10.100.201,并设置团体名5haolou
    123(config)# snmp-server enable traps
    \\启动监控
    123#copy run start
    \\保存设置
    至此已经完成在2950设备上的所有配置。

    二、监控端的配置
    需要使用的软件:
    1.Perl
    2.MRTG
    3.微软的工具软件 :INSTSRV.exe
    SRVANY.exe
    软件安装步骤:
    1.Perl的安装
    Perl的安装比较简单,目前使用的一般是Active Perl for windows,现在最新的版本是5.8.0,它需要使用者先安装IIS或者APACHE等常用的Web服务器平台。在linux/unix操作系统中Perl是系统自带的。
    安装Perl的过程其实很简单的,打开PERL的安装文件,点下一步,然后同意软件使用权的协议,下一个画面会让您确认是否使用PPM3发送个人信息至ASPN,不要选它,直接按下一步。然后就是下一步直通车,直至Perl安装成功,重新启动计算机生效。
    注意:本文安装路径选择d:\perl。
    安装完毕的检查方法:
    我的电脑右键单击——管理——服务和应用程序——Internet信息服务管理(IIS)——网站右键单击——属性——主目录——配置,调出下图,查看有没有.pl,.plx扩展名,如果有就说明perl安装成功了。

    2.MRTG的安装
    Mrtg在windows下的安装很简单,只需要将mrtg.***直接解压到某个盘就好了,比如解压到:d:\mrtg
    同时还要建立一个目录来存放我们要生成的文件,如:d:\mrtgwww,同时将d:\mrtg\images的所有文件复制到d:\wwwmrtg下。
    接下来我们就可以做mrtg的配置了。
    开始——运行——cmd进入dos窗口进行相关配置。

    ①、配置文件的生成(由cfgmaker来生成)
    首先进入到目录d:\mrtg\bin(mrtg解压后的目录),执行如下命令:
    D:\mrtg\bin>perl cfgmaker 5haolou@10.10.100.13 --global “workdir: d:\wwwmrtg” --output mrtg5haolou.cfg

    5haolou是SNMP的通信密码,一般是交换机的出厂设置是public,10.10.100.13是被监控设备的IP,生成的文件默认路径为D:\mrtg\bin(一定要注意那些地方有空格,那些地方没有)。
    安装完毕的检查方法:
    输入以下命令:
    D:\mrtg\bin>perl mrtg mrtg.cfg
    会出现警告,不用管,连续运行三次就不会出现了。

    ②、配置文件的修改(mrtg5haolou.cfg)

    其中的第4,5行是新加进去的语句,保证能够自动更新(interval后的5表示每5分钟刷新一次,可根据实际情况进行修改,另外,如果不加RunAsDaemon:yes这个参数,PERL执行MRTG后会自然中止,切记)。
    将第12行前面的#符号去掉,如果没有此行就加入,使显示以bits为单位
    加入language: GB2312,使显示界面为汉语
    然后保存关闭即可。(注意:修改之前一定要备份文件,防止出现意外)

    ③运行如下命令:
    D:\mrtg\bin>perl mrtg mrtg5haolou.cfg
    如果出现以下语句就表明mrtg工作正常:
    Daemoning mrtg…
    Do not close this window,or mrtg will die
    就是告诉你不要关闭这个窗口,否则mrtg就无法工作.

    ④添加服务MRTG为一项随机启动服务
    由于MRTG是用perl编写的,所以不能直接添加为windows的服务,需要以下两个小程序:Instsrv.exe和srvany.exe,可以用google直接搜索下载到。将Instsrv.exe和srvany.exe放到d:\mrtg\bin目录(为了方便起见),执行如下命令:
    d:\mrtg\bin>instsrv MRTG d:\mrtg\bin\srvany.exe
    会出现添加服务成功的提示。
    接下来需要修改注册表的内容:
    HKEY_LOCAL_MACHINE——system——currentcontrolset——service——MRTG
    为其新建一个名为parameters的项
    在该项下添加以下键值(字符串)
    Application 值为: d:\perl\bin\perl.exe(perl的安装目录)
    AppDirectory 值为: d:\mrtg\bin
    AppParameters 值为: mrtg mrtg5haolou.cfg
    添加完以后就可以把MRTG服务启动了。
    启动方法:在控制面板\管理工具\服务中,找到MRTG服务,启用服务,MRTG即可全天监视指定设备的网络信息了。

    ⑤建立MRTG统计网页(使用indexmaker)
    d:\mrtg\bin>perl indexmaker mrtg5haolou.cfg >D:\wwwmrtg\index.htm
    这样就生成了统计的网页D:\wwwmrtg\index.htm。
    可以通过修改mrtg5haolou.cfg中每个端口的Title、PageTop信息来指定每个端口流量信息页面的标题,可以修改mrtg5haolou.cfg中其他的一些信息,也可以修改index.htm文件来改变页面的显示,当然你每次修改之前最好备份一下mrtg5haolou.cfg文件。

    3、为了使系统在每次开机后,能自动运行该命令,我们还需要在启动里面加入以下快捷方式。
    ①在桌面击右键,选择快捷方式。
    ②输入快捷方式的运行命令行为 start /D d:\mrtg\bin wperl mrtg --logging=mrtg5haolou.log mrtg5haolou.cfg。
    ③输入一个好记的文件名,如“mrtg流量监控”。
    ④运行后,查看bin目录中有没有mrtg5haolou.cfg_l文件,如果有就是执行成功了。

    至此,如果在IIS中为index.htm添加一个联接,MRTG就可以正常运行了,并且会给我们提供每5分钟流量图,每日流量图,每周流量图,每月流量图,每年流量图。

    March 26

    两个存储过程,敝帚自珍

    create   proc   p_writefile  
      @filename   varchar(1000),--要操作的文本文件名  
      @text   varchar(8000) --要写入的内容  
      as  
      declare   @err   int,@src   varchar(255),@desc   varchar(255)  
      declare   @obj   int  
       
      exec   @err=sp_oacreate   'Scripting.FileSystemObject',@obj   out  
      if   @err<>0   goto   lberr  
       
      exec   @err=sp_oamethod   @obj,'OpenTextFile',@obj   out,@filename,8,1  
      if   @err<>0   goto   lberr  
       
      exec   @err=sp_oamethod   @obj,'WriteLine',null,@text  
      if   @err<>0   goto   lberr  
       
      exec   @err=sp_oadestroy   @obj  
      return  
       
      lberr:  
      exec   sp_oageterrorinfo   0,@src   out,@desc   out  
      select   cast(@err   as   varbinary(4))   as   错误号  
      ,@src   as   错误源,@desc   as   错误描述  
     
    GO
     
     
     

    create proc p_getxiaozhangfile
    as
    --删除旧文件
    exec master.dbo.xp_cmdshell 'del d:\xiaozhangfile\cmdfile\xiaozhangfile.txt'
    exec master.dbo.xp_cmdshell 'del d:\xiaozhangfile\cmdfile\xiaozhangfile.bat'
    --昨天的日期字符串
    declare @yyyymmdd varchar(50)
    declare @int_yyyy int
    declare @int_mm int
    declare @int_dd int
    declare @char_yyyy varchar(50)
    declare @char_mm varchar(50)
    declare @char_dd varchar(50)
    declare @yesterday datetime
    set @yesterday=dateadd(dd,-1,getdate())
    set @int_yyyy=year(@yesterday)
    set @int_mm=month(@yesterday)
    set @int_dd=day(@yesterday)
    set @char_yyyy=cast(@int_yyyy as varchar(50))
    if @int_mm<10
    set @char_mm='0'+cast(@int_mm as varchar(50))
    else
    set @char_mm=cast(@int_mm as varchar(50))

    if @int_dd<10
    set @char_dd='0'+cast(@int_dd as varchar(50))
    else
    set @char_dd=cast(@int_dd as varchar(50))
    set @yyyymmdd=@char_yyyy+@char_mm+@char_dd
    --select @yyyymmdd
    --生成FTP.txt文件
    declare @getftpfile varchar(50)
    set @getftpfile='get pyxz'+@yyyymmdd+'.txt'
    exec p_writefile 'd:\xiaozhangfile\cmdfile\xiaozhangfile.txt',帐号'
    exec p_writefile 'd:\xiaozhangfile\cmdfile\xiaozhangfile.txt','密码'
    exec p_writefile 'd:\xiaozhangfile\cmdfile\xiaozhangfile.txt','cd /home/bill4/tuxapp/myFile'
    exec p_writefile 'd:\xiaozhangfile\cmdfile\xiaozhangfile.txt','lcd d:\xiaozhangfile\downloadfile'
    exec p_writefile 'd:\xiaozhangfile\cmdfile\xiaozhangfile.txt',@getftpfile
    exec p_writefile 'd:\xiaozhangfile\cmdfile\xiaozhangfile.txt','bye'
    --生成FTP.BAT文件
    exec p_writefile 'd:\xiaozhangfile\cmdfile\xiaozhangfile.bat','ftp -s:d:\xiaozhangfile\cmdfile\xiaozhangfile.txt 132.97.10.36'
    --覆盖目标文件
    declare @copyfile varchar(100)
    set @copyfile='copy d:\xiaozhangfile\downloadfile\pyxz'+@yyyymmdd+'.txt d:\xiaozhangfile\targetfile\pyxz.txt'
    exec p_writefile 'd:\xiaozhangfile\cmdfile\xiaozhangfile.bat','del d:\xiaozhangfile\targetfile\pyxz.txt'
    exec p_writefile 'd:\xiaozhangfile\cmdfile\xiaozhangfile.bat', @copyfile
    exec master.dbo.xp_cmdshell 'd:\xiaozhangfile\cmdfile\xiaozhangfile.bat'
    --删除表
    delete from pyxz
    --插入新数据
    insert into pyxz (xz_date,tel,branch,busi_id,clien_type,total,xz_total,yf_total,jf_date,o_paymode,n_paymode,xz_no)
    SELECT ltrim(rtrim(xz_date)),ltrim(rtrim(tel)),ltrim(rtrim(branch)),ltrim(rtrim(busi_id)),ltrim(rtrim(clien_type)),
    cast(total as decimal(18,2)),cast(xz_total as decimal(18,2)),cast(yf_total as decimal(18,2)),ltrim(rtrim(jf_date)),
    ltrim(rtrim(o_paymode)),ltrim(rtrim(n_paymode)),ltrim(rtrim(xz_no))
    FROM OpenDataSource( 'Microsoft.Jet.OLEDB.4.0','Data Source="d:\xiaozhangfile\targetfile";Extended Properties=Text')...pyxz#txt
    --把新数据插入到历史记录表
    delete from pyxz_his where xz_date in (select xz_date from pyxz)
    insert into pyxz_his(xz_date,tel,branch,busi_id,clien_type,total,xz_total,yf_total,jf_date,o_paymode,n_paymode,xz_no)
    select xz_date,tel,branch,busi_id,clien_type,total,xz_total,yf_total,jf_date,o_paymode,n_paymode,xz_no from pyxz

    GO
    March 12

    use of Schema.ini File

    Schema.ini File (Text File Driver)


     

    When the Text driver is used, the format of the text file is determined by using a schema information file. The schema information file, which is always named Schema.ini and always kept in the same directory as the text data source, provides the IISAM with information about the general format of the file, the column name and data type information, and a number of other data characteristics. A Schema.ini file is always required for accessing fixed-length data; you should use a Schema.ini file when your text table contains DateTime, Currency, or Decimal data or any time you want more control over the handling of the data in the table.

    Note   The Text ISAM will obtain initial values from the registry, not from Schema.ini. The same default file format applies to all new text data tables. All files created by the CREATE TABLE statement inherit those same default format values, which are set by selecting file format values in the Define Text Format dialog box with <default> chosen in the Tables list. If the values in the registry are different from the values in Schema.ini, the values in the registry will be overwritten by the values from Schema.ini.

    Understanding Schema.ini Files

    Schema.ini files provide schema information about the records in a text file. Each Schema.ini entry specifies one of five characteristics of the table:

    • The text file name
    • The file format
    • The field names, widths, and types
    • The character set
    • Special data type conversions

    The following sections discuss these characteristics.

    Specifying the File Name

    The first entry in Schema.ini is always the name of the text source file enclosed in square brackets. The following example illustrates the entry for the file Sample.txt:

    [Sample.txt]

    Specifying the File Format

    The Format option in Schema.ini specifies the format of the text file. The Text IISAM can read the format automatically from most character-delimited files. You can use any single character as a delimiter in the file except the double quotation mark ("). The Format setting in Schema.ini overrides the setting in the Windows Registry on a file-by-file basis. The following table lists the valid values for the Format option.

    Format specifier Table format Schema.ini Format statement
    Tab Delimited Fields in the file are delimited by tabs. Format=TabDelimited
    CSV Delimited Fields in the file are delimited by commas (comma-separated values). Format=CSVDelimited
    Custom Delimited Fields in the file are delimited by any character you choose to input into the dialog box. All except the double quote (") are allowed, including blank. Format=Delimited(custom character)

    -or-

    With no delimiter specified:

    Format=Delimited( )

    Fixed Length Fields in the file are of a fixed length. Format=FixedLength

    Specifying the Fields

    You can specify field names in a character-delimited text file in two ways:

    • Include the field names in the first row of the table and set ColNameHeader to True.
    • Specify each column by number and designate the column name and data type.

    You must specify each column by number and designate the column name, data type, and width for fixed-length files.

    Note   The ColNameHeader setting in Schema.ini overrides the FirstRowHasNames setting in the Windows Registry on a file-by-file basis.

    The data types of the fields can also be determined. Use the MaxScanRows option to indicate how many rows should be scanned when determining the column types. If you set MaxScanRows to 0, the entire file is scanned. The MaxScanRows setting in Schema.ini overrides the setting in the Windows Registry on a file-by-file basis.

    The following entry indicates that Microsoft Jet should use the data in the first row of the table to determine field names and should examine the entire file to determine the data types used:

    ColNameHeader=True
    MaxScanRows=0

    The next entry designates fields in a table by using the column number (Coln) option, which is optional for character-delimited files and required for fixed-length files. The example shows the Schema.ini entries for two fields, a 10-character CustomerNumber text field and a 30-character CustomerName text field:

    Col1=CustomerNumber Text Width 10
    Col2=CustomerName Text Width 30

    The syntax of Coln is:

    Coln=ColumnName type [Width #]

    The following table describes each part of the Coln entry.

    Parameter Description
    ColumnName The text name of the column. If the column name contains embedded spaces, you must enclose it in double quotation marks.
    type Data types are:

    Microsoft Jet data types
    Bit
    Byte
    Short
    Long
    Currency
    Single
    Double
    DateTime
    Text
    Memo

    ODBC data types
    Char (same as Text)
    Float (same as Double)
    Integer (same as Short)
    LongChar (same as Memo)
    Date date format

    Width The literal string value Width. Indicates that the following number designates the width of the column (optional for character-delimited files; required for fixed-length files).
    # The integer value that designates the width of the column (required if Width is specified).

    Selecting a Character Set

    You can select from two character sets: ANSI and OEM. The CharacterSet setting in Schema.ini overrides the setting in the Windows Registry on a file-by-file basis. The following example shows the Schema.ini entry that sets the character set to ANSI:

    CharacterSet=ANSI

    Specifying Data Type Formats and Conversions

    The Schema.ini file contains a number of options that you can use to specify how data is converted or displayed. The following table lists each of these options.

    Option Description
    DateTimeFormat Can be set to a format string indicating dates and times. You should specify this entry if all date/time fields in the import/export are handled with the same format. All Microsoft Jet formats except A.M. and P.M. are supported. In the absence of a format string, the Windows Control Panel short date picture and time options are used.
    DecimalSymbol Can be set to any single character that is used to separate the integer from the fractional part of a number.
    NumberDigits Indicates the number of decimal digits in the fractional portion of a number.
    NumberLeadingZeros Specifies whether a decimal value less than 1 and greater than –1 should contain leading zeros; this value can either be False (no leading zeros) or True.
    CurrencySymbol Indicates the currency symbol to be used for currency values in the text file. Examples include the dollar sign ($) and Dm.
    CurrencyPosFormat Can be set to any of the following values:
    • Currency symbol prefix with no separation ($1)
    • Currency symbol suffix with no separation (1$)
    • Currency symbol prefix with one character separation ($ 1)
    • Currency symbol suffix with one character separation (1 $)
    CurrencyDigits Specifies the number of digits used for the fractional part of a currency amount.
    CurrencyNegFormat Can be one of the following values:
    • ($1)
    • –$1
    • $–1
    • $1–
    • (1$)
    • –1$
    • 1–$
    • 1$–
    • –1 $
    • –$ 1
    • 1 $–
    • $ 1–
    • $ –1
    • 1– $
    • ($ 1)
    • (1 $)

    This example shows the dollar sign, but you should replace it with the appropriate CurrencySymbol value in the actual program.

    CurrencyThousandSymbol Indicates the single-character symbol to be used for separating currency values in the text file by thousands.
    CurrencyDecimalSymbol Can be set to any single character that is used to separate the whole from the fractional part of a currency amount.

    Note   If you omit an entry, the default value in the Windows Control Panel is used.

    October 25

    转帖:[大话IT]程序员三部曲之二——不作35岁的程序员

    程序员三部曲之二——不作35岁的程序员
      在中国,程序员不能超过35岁,似乎已经是不争的事实,软件开发工作就是青春饭,顶多靠毕业这十年的时间,超过这个年龄,要不成功跃身成为管理者,要不转行进入其他领域,好像再没有更好的选择,即使偶有继续坚持作开发的,也被看成另类一族。老外却不是这样,40,50岁仍然作开发工作的大有人在,甚至很多牛人,包括获得康柏最佳软件奖的Robber,仍在埋头作着他所喜欢的编码工作,为何如此差异。我仔细想了一下,特别是这一年参加了太多的技术培训,基本有了一些结论。
       首先,国内软件开发工作的性质决定这一切,我们所作的产品开发,真正技术含量并不高,高等院校毕业的学生,经过几年的培训和实践,基本都能掌握这些技能,而我们现有产品开发设计水平有限,对于软件开发的理解还仅限于编码,完成功能这些基本的需求,产品进度是第一驱动力,特别是一些小公司,把快速开发出产品作为最高目标,软件设计质量差,很少考虑可维护性,可扩展性这些重要的软件质量属性,仅仅追求功能和进度,产品以最快的速度完成设计,编码,少有测试甚至没有测试,就直接交付给客户,在客户那里暴露出各种各样的问题出来,开发人员就开始不断得为客户解决这样那样的问题,软件做到最后,很多人都会陷入自己不断挖掘出来的“陷阱”里走不出来,步入在复杂的系统中查找BUG,解决BUG,增加功能,引入新的BUG,再解决BUG,这样永无休止的恶性循环中,从事的都是一些低级开发工作,对于软件开发的理解无法上升到更高的层次,每天都疲于救火和拼命打补丁,软件维护成本居高不小,即使最终摆脱了这样的厄运——项目结束,下一次软件开发又是同样过程的重复,这些无休止的低级开发和维护工作,会耗光一个人所有的激情和精力,随着年龄的增大,热情和体力都在衰减,而这些工作,只要毕业生经过培训,同样可以胜任,有着廉价的,并且充满热情的毕业生作竞争,身心疲惫的老程序员必然面对更大的竞争压力,做到最后,连他们自己都会失去对软件开发的兴趣,甚至会产生厌倦的情绪,对于这样的快速开发模式,十年开发经验和五年开发经验有很大区别吗?干吗不使用更经济便宜的开发人员。
       另一个原因,是我们中国人一向的官本位思想,开发人员始终处于一种很尴尬的境界,听起来从事的是高级技术工作,说起来也是“以人为本”,但是,有多少企业管理者真正重视和认可开发人员的,哪怕是硕士,博士,这些开发人员在“大官,小官”面前,都只是普通劳动者而已。程序员是一个没有未来的行业,哪怕资历再深,能力在强,也还是一个劳动者而已,只有当上领导,走上管理才是最终的出路,否则,薪水上不去,地位上不去,只能面对被淘汰的命运。
      
      实际不然,之所以出现这种问题,是国内对软件开发的一种错误理解。如果软件开发仅仅是代码编写,查找BUG,可以说,那实在是一些低级的软件行为,做了十年的开发人员,确实不见得比作了3年的人更强多少,反正是简单重复的工作,工作3年的一样可以作,而且有更大的热情和精力。但是,应该跳出这个怪圈,走向更高的领域,对软件开发重新进行认识。要明白,软件开发要融入工程化的思想,要有高度的设计能力,关注更多的软件运行属性和设计质量属性,同样的系统,不同的软件人员会做出完全不同的软件,正规,高效的开发团队要比游击队开发团队不只高出几十倍。软件开发,不仅仅关注功能,性能,更应该去研究可维护性,可扩展性等质量属性,不仅仅只关注代码,而更要上升为设计,复用等。软件开发不仅仅是写出C语言的代码,单元测试,同行评审,培训与学习,这同样是开发人员基本的素质,也是提高软件质量的最基本手段。举例来说,单元测试做好了,就可以让开发效率大大提高,也能让软件的维护成本降下来。把开发人员解放出来。同行评审可以让开发人员之间更多的交流和沟通,在设计,编码阶段严格控制软件质量,培训则是提高自身技术水平,从理论上提升自己的最好方法。先前这些主要的质量行为都被忽略了,而这恰恰是走出低级开发的最好途径。同时,还有更高层次的设计开发,软件重构,模块化,系统构架,搭建统一软件平台,度量软件质量等等,有了重构,就会写出可读性好,可维护性好的软件,甚至因此提高自己的软件设计能力,减少出错的几率;模块化,让软件最大程度的实现复用,提高软件开发效率和开发质量。软件构架设计,从技术层次上最早决定了软件的命运,而这里又有太多的技术,设计模式,软件规划等,让软件开发从编码上升到设计的层次,搭建统一软件平台,是大产品,系列化开发的必然之路,对于软件质量的度量,会让我们的软件开发变得更加透明,清晰,让我们更清楚的把握到软件开发过程,从各个环节去控制软件质量,而不是仅仅凭着感性的认识到了最后才去补救。
       以上这些知识,一个人,哪怕勤奋学习一辈子,也不可能完全具备所有的技能。35岁算什么,做到70岁都不晚。当然,你需要真正的热爱它,并且不断得学习和进修。所以说,软件开发人员,要作的事情太多了,软件实在是一个浩大的脑力工程,甚至会让人觉得这是一个投入/产出比最低的行业,因为要学习的知识实在太多了,每时每刻都要处于不断的学习和更新当中,呵呵,既然选择了,既然喜欢了,就投入进去,享乐于此了。最重要的是,我们自己能并且愿意去认识到这一点,跳出低级开发的怪圈,走向更高的层次
       同时,要意识到,一个资深开发人员的作用绝不亚于一个管理人员,高明的企业应该给予相同的待遇,要把培养和储备高级技术人才作为高科技企业的重点发展方向,这样才能让企业在人才领域得到不断积累,资深开发人员才会带出高效的开发团队,从而开发出高质量,高效率的软件,让企业在不断激烈的竞争中取胜。要明白,不是每个人都适合或者乐于转向管理的,很多人就是适合做开发工作,他们可以走得更深入,成为专家,应该充分发挥出他们的能力,让整个团队高效运作起来。
       所以说,开发人员,决不只是35岁,只要你愿意,可以作一生的开发,从中获得更多的快乐。
      
    April 25

    强帖共赏:什么是打工,什么是创业——IBM的面试内容

     
        

    面试官)您自己怎么规划自己的职业呢?
    应聘者)我现在因为马上就要面临毕业嘛,因为本科也学计算机,我觉得将来就是希望一开始就进入一个以IT为主的公司,就象IBM、Intel这些主要是搞IT的,这样的话对自己的能力也是一种锻炼嘛,最好进入一个相对是较大的公司。


    面试官)以后不会想去做经理,去做管理什么的?
    应聘者)一开始不会,一开始我肯定是从……我想过个几年我可能会。


    面试官)会不会想要去创业?现在非常流行。
    应聘者)创业我也想过,我和同学也经常讨论,万一说这种大公司进不去,我想一毕业就去创业,难度比较大。


    面试官)其实创业的难度不是很大,创业的关键问题是在于你愿意不愿意做那样的工作和你愿意不愿意去接受创业里面的一些东西,这个非常重要。
    应聘者)我觉得这是一种积累的过程。


    面试官)很多人都说创业是一种积累的过程,创业需要机会,创业需要好的点子,还有人说要有人脉的关系,还要有很多管理的能力……人们都说得玄而又玄,但其实讲穿了,创业其实是很简单的,举例来讲,河南的生梨卖到上海价格可以翻一倍,但是很多人不愿意去做这 种事情,为什么?你去贩卖生梨干什么?对不对?很多人不愿意放下身段改变自己的兴趣爱好。去马路边开一个馄饨摊子挺赚钱,但是不是人人都愿意去做这种事情哦。创业其实并不难。


    应聘者)如果要从头起步,那种传统的买卖可能不难,但是我觉得毕竟学了七年的IT更希望是从事IT,这一领域要比别的门槛高一些。
    面试官)虽然高,但是它和卖馄饨、卖生梨非常相通的一点就是有没有给别人带来帮助,这是整个创业里面核心的一个问题。也就是说我们卖馄饨和卖电脑没有什么两样,它们都要解决人们生活或工作的需要。编程序和卖生梨,或者提供快递服务也没有什么两样,但关键的 一点是你有没有帮助到有需求的顾客,有没有给顾客带来价值。


    应聘者)关键是……最开始我觉得关键要让客户相信你会给他带来利益。
    面试官)哪怕一开始你给顾客白做,证明你的能力,证明你的效益。其实你如果帮不到你的顾客,还去收顾客的钱,那跟抢劫也没有什么两样,对不对?我帮不到你,但是我帮你辛辛苦苦编了五天,给钱吧!那顾客说,我要你干什么?有没有想过一个问题,我想听听你是怎 么回答。如果哪天你已经很有钱,你已经没有经济上的压力,或者是说你并不用因为经济上的原因被迫地去做什么事情,你完全可以自由地选择自己喜欢做的事情去做,那时候你会去做什么?


    应聘者)那时候我就会去想…… 或者是……
    面试官)您有没有什么明确的目标或者是什么事情仅仅是因为经济上的困扰而不能去做的?


    应聘者)我比较感兴趣去做……我不知道你是指事业上的还是说生活方面的?
    面试官)有什么两样吗?


    应聘者)事业可能说……事业方面你会更专注于某个领域,将来你有钱了你肯定会去……
    比如说,你自己去创业,做自己感兴趣的事情,开一家IT公司。
    面试官)您说您有钱了会去开一家IT公司,为什么一定要自己做老板呢?


    应聘者)因为……首先你自己做老板的话,你自己感兴趣的东西你可以去做,就像前面所说的那样。
    面试官)是不是在公司打工时就会被分派自己不感兴趣的事情呢?


    应聘者)打工的时候很有可能被分去做自己不喜欢的事情。
    面试官)您怎么知道创业了您就不会被顾客逼着去做你不喜欢的事情呢?

    应聘者)前提不是说不会被生活所困扰吗?
    面试官)是,您已经不会被生活所困扰了,为什么在打工时还会被人逼着做你不喜欢的事情呢?


    应聘者)就是……您的前提是说,首先我很有钱了,我就打算搞个IT公司。
    面试官)为什么要去做老板,为什么不去打工?去做职业经理人?为什么要去自己开公司?


    应聘者)因为打工做经理,总觉得好像是属于那种上下级的关系……
    面试官)不喜欢上下级的关系?


    应聘者)不是说不喜欢……
    面试官)那为什么上下级的关系对您是一种困扰呢?


    应聘者)不是困扰,就是我更有钱,我更希望自己控制自己去做感兴趣的事情。就是说在公司里边可能,当然就是说,与IT相关的事情我会去做,但就是说……毕竟是自由度没有自己开公司这么大。
    面试官)您已经被您的兴趣所控制,被您的欲望所控制了。


    应聘者)被兴趣控制了,我觉得并不是一件坏事,而且是一件好事。
    面试官)那你为什么就不能在公司中非常有兴趣地为领导服务呢?


    应聘者)我为领导服务那是肯定的。就是说,可能有的时候你会被领导分派一些你并不喜欢的事情。
    面试官)公司一开始往往会被市场逼迫去做你并不喜欢的事情,这两者没有什么差异。

    应聘者)如果开公司,我觉得还是要做自己感兴趣的那一块。一开始可能会为市场所左右,但我觉得慢慢地你做好了的话,只专注于你感兴趣的那一块,然后你在这一块里有所建树,或者是打出名气或者知名度,那么就比较容易了。


    面试官)想象一下,象我一样在某一家公司工作,打工就是一种创业。我不知道您是否赞同这种观念,象您可能没有打过工,所以并不知道创业和打工有什么差异。比如说,我是 Frank,我在IBM公司工作,相当于我开了一个一个人的公司,就叫Frank工作室好 了,我这家公司就我一个人。我的顾客只有一个,目前只有一个,就是IBM, IBM购买我的服务,她把付给我这家公司服务费称作薪资。当然周围还有很多与我竞争的同事,就象我开公司也会有许多同领域竞争的公司一样,做跟我一样的工作的公司。


    应聘者)您的意思就是说,工作也是一种创业?我一开始因为没有工作过,我的想法就是创业就是做老板。
    面试官)你已经做老板了,你不觉得你已经是自己那个公司的老板了吗?


    应聘者)因为我没有在很大的公司工作过,所以没有这种思想。
    面试官)公司的大和小没有关系。


    应聘者)大公司和小公司还是有点区别的。小公司,它项目不多,业务领域不多,可能局限于老板让你做什么,你就做什么。
    面试官)领导就是你的顾客,顾客让你做哪一块,你没有选择。你自己开公司也是一样的。


    应聘者)不是,就是说,你们IBM……就是那种大公司可能会考虑你的兴趣爱好所在吧,能够把你分派到你感兴趣的工作岗位上。在小公司工作更有一种被强迫的感觉。
    面试官)即使开一家自己的公司,刚开始的时候几乎都是被强迫,想象一下这些问题:资金不够,场地要费用,员工期望高薪高福利,竞争对手的压制,被市场变化弄得晕头转向,你想要赚钱,难道你就没有被强迫的感觉吗?工作一开始也被强迫,为什么?因为你要经济独 立,你要养活自己,你要尽快摆脱父母的抚养。你要买房子,你要谈恋爱,你要结婚,你要生孩子,总而言之,你要钱。你要工作去赚钱,是不是要被强迫?所以无论自己开公司还是打工一开始都会被强迫,我看不出一开始自己开公司和去打工有什么根本的差异。如果你工 作二十年,你还是领导强迫你去做工作,或者你开公司二十年,你还没有找到自己的定位,无论打工和开公司,你都是失败者。懂我的意思?我看不出你为什么一定要做老板。除非你有什么明确的理由能说服我,你为什么要做老板。你已经决定自己的命运了,你开了一个一 个人的公司,现在你的问题是如何把它经营好,创出自己的品牌,拓展自己的服务领域和从被迫转变成自己主动选择自己的工作。


    应聘者)我觉得你如果自己开公司,步入正轨之后吧……
    面试官)你想想你的工作步入正轨以后……


    应聘者)步入正轨无论怎样还是在给别人打工……
    面试官)开公司无论如何也是在为别人打工,因为你必须要卖服务或者商品给顾客,任何付你钱的人,你都要为他服务,你可以不赚钱,你决定不赚钱,你就可以不用为他打工。Okey,你在单位里也一样。我不要你的工资,你就可以决定不用为他服务。


    应聘者)可能我的观念与你有些不太一样,我总觉得开公司命运是掌握在我自己手里。面试官)可是你今天已经开公司了,没人在控制你的命运, right?没人决定你要去找什么样的工作,没人决定你一定要去开公司还是要去打工。命运今天已经掌握在你的手里。即使你决定去打工,仍然你会决定打什么工,是不是继续做下去,是不是干自己喜欢的东西,要去学习什么,要去追求什么。你已经掌握了你的命运, right?


    应聘者)工作的时候,你没有完全掌握你的命运,你必须先把工作做完。
    面试官)创业也一样,开公司也一样。你必须要把自己的工作做完,顾客才愿意付钱给你。然后你才能去考虑其它的业务。


    应聘者)这个还是有点区别的。
    面试官)告诉我区别在哪里。


    应聘者)你给别人打工,你首先领导给你的任务你先要做完,然后才有空你去做你自己感兴趣的事情。
    面试官)开公司也一样,顾客交待的任务做完了,你才有空去拓展自己公司的领域。


    应聘者)做公司的话,首先一开始肯定是这样的,被市场所左右。
    面试官)打工也一样,一开始一定被人分派做事情,等到你慢慢到达一个位置,想想我们以前的总裁郭士纳,他也是一个打工者,谁分派工作给他?他自己要决定怎么做。IBM公司的总裁周伟焜先生,我相信他会决定怎样经营中国公司,虽然他是一个打工者。

    应聘者)……这个打工者就是说,已经有自己可以控制的一块领域了。
    面试官)为什么不去做这样的人呢?我的意思是说,打工可以做到这么高的成就,难道比自己开公司还差劲吗?


    应聘者)不是,打工你要做到这么高的成就,你肯定得通过十几年、二十几年慢慢地干出来。
    面试官)难道你认为创业一定能够一下子成功吗也?今天许多多人想的都是如何获得暴利,希望一夜暴富,开公司,总是想着如何快速地去骗取顾客的钱吗?


    应聘者)因为前提是我已经不会被生活所困扰。首先我们必须有诚信,不能骗顾客一笔钱,却没有提供服务,那样子这家公司肯定完蛋。所以说,你一开始不一定很赚钱,但你一,要去学习什么,要去追求什么。你已经掌握了你的命运,right?


    应聘者)工作的时候,你没有完全掌握你的命运,你必须先把工作做完。
    面试官)创业也一样,开公司也一样。你必须要把自己的工作做完,顾客才愿意付钱给你。然后你才能去考虑其它的业务。


    应聘者)这个还是有点区别的。
    面试官)告诉我区别在哪里。


    应聘者)你给别人打工,你首先领导给你的任务你先要做完,然后才有空你去做你自己感兴趣的事情。
    面试官)开公司也一样,顾客交待的任务做完了,你才有空去拓展自己公司的领域。


    应聘者)做公司的话,首先一开始肯定是这样的,被市场所左右。
    面试官)打工也一样,一开始一定被人分派做事情,等到你慢慢到达一个位置,想想我们以前的总裁郭士纳,他也是一个打工者,谁分派工作给他?他自己要决定怎么做。IBM公司的总裁周伟焜先生,我相信他会决定怎样经营中国公司,虽然他是一个打工者。


    应聘者)……这个打工者就是说,已经有自己可以控制的一块领域了。
    面试官)为什么不去做这样的人呢?我的意思是说,打工可以做到这么高的成就,难道比自己开公司还差劲吗?


    应聘者)不是,打工你要做到这么高的成就,你肯定得通过十几年、二十几年慢慢地干出来。
    面试官)难道你认为创业一定能够一下子成功吗也?今天许多多人想的都是如何获得暴利,希望一夜暴富,开公司,总是想着如何快速地去骗取顾客的钱吗?


    应聘者)因为前提是我已经不会被生活所困扰。首先我们必须有诚信,不能骗顾客一笔钱,却没有提供服务,那样子这家公司肯定完蛋。所以说,你一开始不一定很赚钱,但你一面试官)从我自己的理念,打工和创业只有两个本质的差异。一个叫做有机会去创造一个职位。 也就是说,你喜欢做什么事情,但你发现目前去寻求工作你找不到,或者别人不接受你去做你喜欢的事情,怎么办?自己创造一个工作,创造一个机会,自己做公司,我自己做首席什么官,这是第一个本质的差异,这是目前比较流行的想法。第二个差异,是自我价值的检验 。例如说,我认定我的价值是十万元人民币一个月,但是找遍了许多职位都没有人愿意发这样的薪资给我,因为我不能让人家相信,我应该拿这样的薪资,怎么办?自己开公司,自己证明这一点。我都想象不出还有什么所谓更自由啦,不用看上级脸色的差异。我都看不出还 有什么其它的差异。你所讲的差异根本就不存在。


    应聘者)我说还是存在的吧。
    面试官)为什么?


    应聘者)就是说,你开公司你有权利选择顾客。
    面试官)你也有权利选择你的上级。这是我作为过来人可以与你分享的。你是不是有权利选择你的顾客跟你的生存状态有关系,当你这个公司已经不介意这个顾客的时候,你才有机会去选择。但这个顾客是否选择你,将要决定到你公司的生死存亡的时候,你没得选择。如果 是打工,当你自己有充分的地位和生存能力的时候,你也可以不介意上级,离开当前的工作,你根本不用去介意。只有当这个工作对你很关键的时候,你要介意。这跟你公司的生存状态或你自己的生存状态有关系。


    应聘者)但我炒了他,我又得继续寻找我的工作。
    面试官)你本来就在寻找你的工作,决定做什么工作,别人强迫你吗?你的兴趣所在是由你自己决定的,你决定去做什么工作,腿长在你脚上,难道还有什么原因一定去做自己不感兴趣的事情吗?只是一开始的时候由于经济上或者某种原因,又或者,你很喜欢一个漂亮MM ,与她在同一家公司工作,可以使你更容易追求到她,象唐伯虎追秋香一样。无论怎么样,你总是应该决定自己去做什么样的工作,谈不上被迫。如果生活状况很好,不需要去做自己不感兴趣的事情;或者公司生存很好,可以决定自己服务哪些顾客,不服务哪些顾客。你所 讲的差异是不成立的。在IBM 公司工作有四个层次,这四个层次决定了你的人品高下。第一层次就是“尽职尽责做好本职工作”,领导分派什么,就要做好什么,保证质量,有责任感,哪怕有时候要加班加点,保证任务成功地完成。这是第一个层次,只能够做到第一个层次的人,今天进入IBM是没有 把握的。第二个层次是什么呢?是主动寻找和承担工作,不要等上司跟你讲做什么,自己要去看,你还能帮领导帮团队做什么,还能够帮助你的顾客做什么。不一定要得到命令该去做什么才去做什么,你自己睁开眼睛开动脑子去想你还能做什么。你来到一家饭店吃饭,如果 服务员还没有等你说“倒茶”,香茶已经沏上了,你手脏了,她的热毛巾已经放在边上了,什么要求,你不用去张嘴,服务员已经都帮你准备好了,你满意不满意?如果别人请你帮忙倒杯咖啡,你一定要想要是否加上红糖和牛奶,是不是还要添一把小调羹?不用别人讲,自 己去为别人考虑,自己去做,自己决定去做什么,不要等到别人来分派什么,来给你压力,这叫第二层次。第二层次也不能确保能够进入IBM。因为这种人虽然不是那么多,但是IBM所招聘的人更少!你要去追求更高的层次,就是第三层次。第三层次是什么呢?分享和 规范,什么意思呢?你要帮助你周围的人,周围的同事,让他们能够做得跟你一样好。你将你做得那么好的经验、方法规范化下来,标准化下来,使得人家很容易去做同样的事情,让人家可以做得跟你一样好,这样你可以有机会去做更有挑战的事情。人们说,有个理论叫做 “木桶理论”,什么意思呢?一个木桶里能装的水,是由最短的那根木板决定的,而不是由最长的那根木板决定的。即使一个人在团队中做到最长的那根木板,有什么用,整个团队并不会因为你的提高而获得提高,你的任务是使得整个团队都获得提高。第三层次, Okey,可以加入IBM,但是最厉害的是第四层次,第四层次的人为组织制定战略,为组织指出正确的前进方向,第四层次的人的个人魅力会使得组织中的成员愿意追随,并为之共同奋斗。如果你的能力达到了第四层次,那就不是能不能进入IBM的问题了,而是IB M要求你加入了。在我们做Interview的时候有非常重要的一点,就是通过Interview评估你的潜质未来是否有机会变成我们的领导者,希望加入进来的人不只是一个眼前的程序员,而是通过培养,未来你会带领整个团队,作为我们的技术上或经营上的掌 舵人、领导者,我们把整个团队、整个部门、整个组织托付给你,放在你的肩膀上,你能不能挑得起来。我讲这些的时候,我希望颠覆你原来打工的理念。你目前打工是被迫的,但是是很低层次的。打工和开自己的公司在最高的层次
    是一样的,在最低的层次也是一样的。


    应聘者)IBM把我们招进来,一开始是做程序员的……
    面试官)是做软件工程师的。


    应聘者)但是我一直有个问题,到了三、四十岁不可能每个人都有机会做团队的领导,那个时候并没有那么多这样的职位,怎么办呢?
    面试官)每个人通过若干年的工作以后,人生规划都会自己做相应的调整,重新地审视自己更适合去做什么。很多人很可能,甚至在工作的头一两年就已经做了调整。你前面所说的“并没有那么多的职位怎么办”,最后有几种方案,第一种,最简单,离开这里,这里没有你 的发展前途,我们自己去寻求变化。第二种,改变自己的目标,其实一直做工程师也不错,尤其是我在IBM看见过一些头发花白的工程师。做工程师也有不同的level,你也可以不断地提升自己到一个很高很高的 level,也可以去做与IT标准和架构相关的东西,或者去做项目管理的东西等等,有很多不同的道路可以走,可以一直做到很资深。第三种,坚持到底,卧薪尝胆,不断磨砺自己的能力,直至机遇来临。


    应聘者)IBM平时是不是有很多员工培训呢?这些员工培训是不是可以选择自己感兴趣的东西呢?
    面试官)你感兴趣的东西是什么呢?不是所有你感兴趣的东西都会在IBM获得培训,你必须要做好这个思想准备。如果你感兴趣例如说中医药,那我们很少有可能会有这个方面的培训。如果你很感兴趣做项目管理,这个是应该有机会的。如果你感兴趣的,和IBM希望你 的发展方向是一致的,则获得培训的机会就较大。原理上,管理层会很希望每个员工有自己的兴趣和喜欢去做的事情,也很希望员工有自己明确的人生目标,这样才有机会可以双赢:员工个人获得个人想要的东西,IBM获得IBM想要的东西。


    应聘者)其实我还是想问一些有关人生规划的问题,我想你在这里工作了这么久,能不能给我一些建议什么的?
    面试官)最重要的建议有几点:要有自己明确的目标,迅速有效地行动,不要随便被某些公司用高薪、高福利诱惑,而丧失了自己的目标和追求。当你获得一家公司高薪和高福利工作的时候,其实你一定要给这家公司更高的回报作为交换。


    应聘者)就是把眼光放远一点,看重将来的发展。
    面试官)当你能创造更多的价值的时候,你一定能获得更高的薪资和福利待遇,而很多的学生一开始会被眼前的高薪和高福利所诱惑。当然,那些比较差的公司需求人才的时候,一定会加码。但是当你拿得多的时候,你一定需要为它创造价值,如果你的创造的价值小于你所 得到的种种利益,这家公司的经营就会有问题,不能持久经营下去。所以有些学生因为某家公司的工资高而去了那家公司,完全忽视了自己是否能够为它创造超过自己薪资待遇的价值。一定要知道,只有公平地交易,才是合理和能够持久的,不要去片面地追求高收入或者高 福利,如果不能使自己在这家公司的价值匹配你所获得的报酬,那就是你在强抢这家公司的财产。


    应聘者)我在网上或者也有很多人告诉我IBM是一个非常人性化的公司。
    面试官)人性化是你对这家公司的看法,但原理上跟你个人的人生目标没有什么关系。你准备去做一个什么样的人,你准备要解决社会上什么样的问题,你自己要去回答这些问题,跟IBM是不是人性化,IBM是不是照顾员工,都没有什么关系。


    应聘者)但是如果在IBM,就能为我们创造更好的发展环境……
    面试官)但是你一定要知道你朝哪边去发展,你是要变成一个社会工作者,或者想变成一个什么样不一定跟IBM有关系的那种职业或者说要去解决的问题不是IBM领域的,比方说,你现在想去徐家汇是你的目标的话,你就不应该乘车去五角场,哪怕去五角场的这辆车子 再豪华再舒适,它也不是你要搭乘的。


    应聘者)关键是要自己的方向上,然后如果它正合适的话,我就会选择它。
    面试官)是。而且往往人生目标也不需要一定要搭乘一辆车子,你可能是说那家公司做了一阵子,掌握了某一些技巧,达到了阶段性的目标之后,还可以再换乘一辆车子,直到达到最终目标,就象先到宛平南路肇嘉浜路,再到徐家汇也可以一样,但是不要绕远路先到五角场 ,那是浪费时间。这个要点是你要知道你要去哪里,然后再决定怎么到达一样。很多人没有目标,所以他们随便搭什么车子都可以,只要不要被晃得掉下来,——很多人都是这样子过的。


    应聘者)其实我觉得既然是搞计算机方面的,如果是能够进入像IBM这样的好公司对我这个方向还是非常非常必要的。
    面试官)了解这种想法,但是如果有更清晰的目标的话可能会帮助你更加快地到达成功。很多人都说好,问题是并不确认好在哪里,有什么关系。比如要学习网络工程,可能某些方面思科会比IBM更好一些,如果是家用软件方面,可能IBM也不是这方面的老大。

    应聘者)但我觉得很难有人那么明确地说,“我现在在这里,我一定要到达那里”这么明确,家用软件或网络工程,我都不能确认这个一定适合我,我就是我不伸手下去做这个东西,我不会知道这个真正适合自己。
    面试官)这是因为自己还没有目标的时候,随便走哪一条道路都谈不上正确或不正确。当你的目标十分明确的时候,你选择的对和错也就明显许多了。


    应聘者)那样是不是还是需要先有一段经历的过程,然后才能够明确目标呢?
    面试官)可以花上一段时间工作例如说一、两年,了解自己真正想要什么,也可以继续念书念研究生,同时思考自己的人生规划。其实如果你已经有明确的目标了,就得抓紧时间实施,选择最短最快最有效率的方法去行动去来。花费时间去学习研究那些相对次要的东西就意 味你就减少时间花费在那些更关键、优先级更高的事情上。举例来讲,如果你想成为一名优秀律师,那法律相关的知识就显得尤其重要,而花费时间去学习计算机,就相对次要了,这就有机会成本的问题,你做了一件事,就没有时间去做另一件事,所以必须要走捷径。有目 标的时候,要赶紧行动。


    应聘者)IBM给我们学生实习机会,是为了什么呢?
    面试官)一个是解决项目中人手短缺的问题,也就是有些时候项目的工作量大到需要额外的人才来弥补人手短缺的问题;另外一个也是希望从实习过程中发现和考验一些学生的能力,将一些优秀的人才优先吸收进IBM。这是实习的两个非常关键的目标。希望你在IBM工 作会找到自己的明确目标,并能从工作中提升自己的价值,和IBM共同成长。
    April 18

    换歌了

    每一次 

    易茗词, 雷蕾曲, 张宏声唱 

    茫茫人海, 终生寻找, 
    一息尚存就别说找不到。 
    希望还 在明天会到 
    历尽艰难就别说经过了。 

    每一次发现都出乎意料, 
    每一个足迹都令人骄傲, 
    每一次微笑都是新感觉, 
    每一次流泪都是头一遭。
    March 30

    琪菲女士的诗词

          琪菲女士今年88岁了,是我母亲的姑母。她年轻时曾经到梅县上师范学校。会弹扬琴,写得一手好字。举止言谈颇为与众不同,很有那种三十年代知识分子的气质,所以叫她琪菲女士:)。
        她的诗词也有味道,颇有点李清照的清婉。当然其中也有写得不好的地方,如古人说“明珠翠羽不能入词”,因为词是虚的东西,切忌用词太实,或者结成团,不化的感觉,但琪菲女士的抖练子中“新愁旧恨”就是这首词中的明珠翠羽。还有不少地方也是说了古人说过N次的熟话。今天网上牛人众多,也许不乏写得比她好的,但毕竟少数,而且她的词有时真的很有气质,这点就不是一班人能做到的了。
     
          抖练子 感怀(做于1965年冬)
       青枫冷,白桐凋,杨柳腰肢旧时娇。再试寒衣宽三寸,新愁旧恨上眉梢。
      
      
       七律 感怀
       东流逝水逐莺飞,廿载萍飘分翠微。
       带泪芙蓉凋玉露,飘零柳絮沾金衣。
       所嗟藕断丝难断,徒羡桃归燕亦归。
       秋水欲穿云漠漠,春愁脉脉立斜晖。
      
       十六字令 (夏雨感怀五首)

      序:夏雨滂沱,晒台顿成泽国,雨点起泡成波,彼起此伏,因此感怀身世
       (一)
       波,绿漪年年映翠螺,孤舟静,风水可奈何!
       (二)
       波,百怨千愁满画舸,悠悠去,幽咽听棹歌。
       (三)
       波,逐浪心潮对素娥,天涯远,红叶滞关河。
       (四)
       波,流水天涯怎奈何,芳菲歇,往事泪痕多。
       (五)
       波,吊月秋蝉冷抱柯,年华逝,夙愿已蹉跎!
      
       浪淘沙 .残秋

       篱菊已阑珊,晓露凝寒。侵肤冷气恨衣单,却羡无知秋粉蝶,醉舞花丛。
       寂寞倚危栏,珠泪懒弹。数尽更筹入梦难,篱边络纬啼秋暮,响彻夜间。
      
      (作者按:以上诗词67年文化大革命全部烧毁,现凭记忆重写)
      
      
       (作者按:1988年10月2日第一次参加樟林校友会,当时平仄诗韵早已忘怀,无意考究,不敢添词牌名)
       江城子 .感怀
       卅年漂泊各西东,思相逢,恰相逢。银鬟白法,旧地驻征蓬。传语故人休惆怅,风霜劫,皆相同。
       前情流水去无踪,会匆匆,离匆匆。友情浓郁,清影映秋风。同窗济济融融喜,聚会乐,贯长空。
      
       一丛花 .校友联欢寄意(1989年10月)

       碧海晴天舞飞鸿,聚欢尾园中。青春难留无再少,白首有幸对金风。旧谊重温,倍胜往昔,冰心一片红。
       相呼相见情意浓,笑语润心衷。喜看旧圃桃李翠,乐赏新潮景象宏。韩江长流,晚霞如锦,斜晖照山峰。
      
       打油诗(1989年1月19日题照片)
       年华虚度七余一,瘦骨棱棱傲石玉。
       沫雨栉风屹立存,吞云吐舞观棋局。
      
      
       浣溪纱 .咏梅(1990年1月)
       莲花峰下寒梅俏,七十春秋熬过了,奇岩陡谷云飘渺。
       雪肌屈曲傲冰封,铁骨纵横凭雪扰,新梯怒茁冲天缴。
    March 16

    发个歌词吧

    春山春水春到花溪浮香已千载 

    雨收云散心枕清波哪里有尘埃

     谁解春水朝夕向东可曾见沧海 

    曾经沧海终于回来故人今可在

     想当时风采

    结四方豪迈

    为平生爱

    何惧繁华去和来

    筑一座凤凰台  

    唱千年感慨 

    但教真情在 

    终不能同黄土埋

    一生一世所牵所爱难了也难改 

    谁能无怨谁能无恨谁能不归来

    向家园青青山水 

    忘功名成败 

    等到来年等到来生等到苍天开

    梦醒时人
    此时东方已白

    ——电视剧《牛子厚与富连成》主题歌

     

        这歌的歌词不错,而且李娜的歌声如说故事般娓娓道来,比她那些慷慨激昂的还耐听。