免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: compare2000
打印 上一主题 下一主题

DOS命令大全 [复制链接]

论坛徽章:
3
天秤座
日期:2013-12-27 13:44:58射手座
日期:2014-05-22 16:52:43天蝎座
日期:2014-08-13 16:03:21
31 [报告]
发表于 2011-01-23 13:59 |只看该作者
本帖最后由 compare2000 于 2013-12-30 10:43 编辑

11.3        利用dropwatch进行丢包故障定位
Linux自2.6.30开始具有Network Drop Monitor功能;协议栈对于非法数据包会进行丢弃,即便是合法数据包,若超过接收缓存大小也会进行丢弃;但是这些丢弃的数据包无法通过内核日志进行观看;但若内核支持Network Drop Monitor,则可以使用dropwatch进行查看。
Dropwatch就是各种协议释放socket缓冲区时(kfree_skb函数)收集信息。可以应对IP、ARP、ICMP、IGMP、UDP协议的数据包。
因此,即使不使用proc文件系统或者工具针对各个协议收集信息,也可以通过dorpwatch将数据集中到一起进行确认。不需要为了调查潜在的网络性能而改变已有的应用程序。
11.3.1        软件使用
    编译内核时,需要启动Network packet drop alerting service(NET_DROP_MONITOR)并重新编译内核。
执行dropwatch命令,显示dropwatch和提示符后输入start即开始检测丢包情况
Initalizing null lookup method
dropwatch > start
在检测的过程中,如果输入Ctrl+C则返回提示符命令行,输入stop或者exit后就可以结束。
例如:
1 drops at location 0xffffffff8887453
14 drops at location 0xffffffff88964322
17 drops at location 0xffffffff8745466
1 drops at location 0xffffffff8867311
此时检测到丢包后,会打印出代码段对应丢包代码的位置,但是不是很直观,不能看出具体是哪一段代码出现了丢包。此时可以借助-l命令选项,即使用/proc/kallsyms将具体的地址转换为函数名。
dropwatch –l kas
其中kas是kernel all symbols的缩写。
例如:
1 drops at netlink_unicast+249 表示在netlink_unicast偏移249处丢包1个
6 drops at __udp4_lib_mcast_deliver+364
13 drops at __udp4_lib_mcast_deliver+364
1 drops at __netif_receive_skb+48a
11 drops at __udp4_lib_mcast_deliver+364
7 drops at __udp4_lib_mcast_deliver+364

11.4        TCP/UDP故障定位
11.4.1        现象描述
某业务环境,升级版本后TCP无法建立连接,业务侧统计失败率为100%,无法满足基本通信要求。
11.4.2        定位过程
1.        使用tcpdump抓包,发现接收端抓到的报文L4校验和错误,导致接收端直接将报文丢弃;
2.        抓取多组报文观察并编制程序计算校验和,发现这些校验和存在一定的规律,一组为报文中的校验和为报文伪头部的校验和,另一组报文中的校验和与正确的校验和差值为伪头部的校验和。
3.        与业务一起分析其相关代码,观察到其强制设置报文的skb->ip_summed为硬件计算校验和方式。但是对于其发送的报文,分为转发和自己组包两类。对于转发,除了修改skb->ip_summed字段,其他并无变动;对于自己组包的报文,除了修改skb->ip_summed字段为硬件计算校验和方式,同时将tcphdr->check字段赋为0。
4.        分析网卡驱动,当网卡驱动检测到skb->ip_summed为硬件计算校验和时,则告诉硬件需要计算L4校验和,然后由硬件发送报文。
5.        分析内核,当硬件具备计算L4校验和能力,并且报文的skb->ip_summed设置为硬件计算校验和,则协议栈计算伪头部的校验和并填充到tcphdr->check字段,据此可以推断出网卡硬件计算校验和时,默认情况下是需要tcphdr->check字段已经填充为伪头部校验和。而第3步中提到,业务两种组包场景下,显然都不满足这个要求。
6.        业务进行修改自己的协议栈,保持与内核一致的处理方式。再测试后现象消失。
11.4.3        Linux内核协议栈TCP校验和计算流程分析
Linux内核协议栈中TCP校验和计算流程分析
1.        无论是首次发送TCP段,还是重传,或者是建立TCP连接时发送SYN段,都会调用到tcp_transmit_skb()。该函数的注释也可以看出这点。


2.该函数处理之前,报文中还没有TCP头,所以需要先填充TCP头,然后计算TCP校验和。
1)构建TCP头

2)调用对应的钩子函数计算TCP校验和

对于IPv4-TCP报文来说,该Hook实际上为tcp_v4_send_check()函数。

3)tcp_v4_send_check()计算TCP校验和
从该函数的实现来看,如果skb中设置了让硬件计算校验和,则只计算伪头部的校验和并填充到th->check中,否则计算伪头部及TCP层整体校验和。


3.若组包时让硬件计算校验和,但硬件不具备该能力Linux协议栈处理方式
从第2步可以看出来,在报文送到dev_queue_xmit()之前,此种场景下th->check中已经有了伪头部的校验和。
dev_queue_xmit()中的判断,如果硬件不具备计算校验和的能力,则调用skb_checksum_help()计算TCP层的校验和,这样保证了该场景下L4层校验和的正确性。
12        追踪
12.1        Strace/lstrace进行追踪
strace、ltrace是linux下的跟踪工具,strace用来跟踪一个进程的系统调用或信号产生的情况,而 ltrace用来跟踪进程调用库函数的情况。
它们不仅可以从命令行调试一个新开始的程序,也可以把strace或ltrace绑定到一个已有的PID上来调试一个正在运行的程序。主要能跟踪进程运行过程中调用的系统函数/库函数,还有时间戳等信息。它们的用法都很类似,下面是strace/ltrace常见的参数:
参数        含义
-f              除了跟踪当前进程外,还跟踪其子进程
-o file         将输出信息写到文件file中,而不是显示到标准错误输出(stderr)
-p pid          绑定到一个由pid对应的正在运行的进程。此参数常用来调试后台进程
-T               每个库函数/系统函数调用的执行时间
  下面分别举例看如何使用。
12.1.1        strace跟踪系统调用
1、        启动跟踪,跟踪ls –al命令的系统调用,结果写入strace_ls.txt文件
#strace -o /mbsc/log/strace_ls.txt ls -al
2、        查看跟踪的情况(有截断):#cat /mbsc/log/strace_ls.txt
该信息解释如下:
系统函数(调用参数1,调用参数2,….) = 系统调用返回值
3、        跟踪系统调用的耗时:
#strace -o /mbsc/log/strace_ls.txt -T ls -al
4、        strace的详细参数(查看帮助信息):

12.1.2        ltrace跟踪库调用
5、        启动跟踪ltrace ls -al : 查看ls –al命令调用的库函数
打印格式:
库函数名(参数1,参数2,…) = 返回值
6、        同时跟踪库函数及系统调用:ltrace -S ls -al (结果有截断)

说明:以SYS_开头的就是系统调用。
7、        跟踪调用耗时:ltrace -S -T ls -al

说明:最右侧就是该函数执行时间
8、        ltrace函数详细参数(查看帮助)

下面该得文档给出了更为详细的使用说明
Linux问题定位手段之strace使用详解
strace 命令是一种强大的工具,它能够显示所有由用户空间程序发出的系统调用。 strace 显示这些调用的参数并返回符号形式的值。strace 从内核接收信息,而且不需要以任何特殊的方式来构建内核。
               
一、参数详解:
dl_scu ~ # strace
usage: strace [-dffhiqrtttTvVxx] [-a column] [-e expr] ... [-o file]
              [-p pid] ... [-s strsize] [-u username] [-E var=val] ...
              [command [arg ...]]
   or: strace -c -D [-e expr] ... [-O overhead] [-S sortby] [-E var=val] ...
              [command [arg ...]]
-c -- count time, calls, and errors for each syscall and report summary
-f -- follow forks, -ff -- with output into separate files
-F -- attempt to follow vforks, -h -- print help message
-i -- print instruction pointer at time of syscall
-q -- suppress messages about attaching, detaching, etc.
-r -- print relative timestamp, -t -- absolute timestamp, -tt -- with usecs
-T -- print time spent in each syscall, -V -- print version
-v -- verbose mode: print unabbreviated argv, stat, termio, etc. args
-x -- print non-ascii strings in hex, -xx -- print all strings in hex
-a column -- alignment COLUMN for printing syscall results (default 40)
-e expr -- a qualifying expression: option=[!]all or option=[!]val1[,val2]...
   options: trace, abbrev, verbose, raw, signal, read, or write
-o file -- send trace output to FILE instead of stderr
-O overhead -- set overhead for tracing syscalls to OVERHEAD usecs
-p pid -- trace process with process id PID, may be repeated
-D -- run tracer process as a detached grandchild, not as parent
-s strsize -- limit length of print strings to STRSIZE chars (default 32)
-S sortby -- sort syscall counts by: time, calls, name, nothing (default time)
-u username -- run command as username handling setuid and/or setgid
-E var=val -- put var=val in the environment for command
-E var -- remove var from the environment for command
??
主要参数说明:
?? -e expr
?? A qualifying expression which modifies which events to trace or how to trace
?? them. The format of the expression is:
?? [qualifier=][!]value1[,value2]...
?? 这里qualifier可以是trace、abbrev、verbose、raw、signal、read或者write。
?? value是qualifier相关的符号或数值。缺省qualifier是trace。!表示取反。

?? -eopen等价于-e trace=open,表示只跟踪open系统调用。-etrace=!open意思是跟踪除open系统调用之外的其他所有系统调用。此外value还可以取值all和none。
如:strace -o temp1.txt -eopen cat temp.txt
?? strace -o temp2.txt -e trace=\!open cat temp.txt或
strace -o temp4.txt -etrace='!'open cat temp.txt

?? 注意:某些shell用!表示重复历史指令,此时可能需要引号、转义符号(\)的帮助。
?? -e execve 只记录 execve 这类系统调用。
如:strace -e execve ls

?? -e trace=set
?? 只跟踪指定的系统调用列表。决定跟踪哪些系统调用时,-c选项很有用。
?? trace=open,close,read,write意即只跟踪这四种系统调用,缺省是trace=all
?? 如:strace -o temp5.txt -etrace=open,close,read,write cat temp.txt

?? -e trace=process:跟踪所有与进程管理相关的系统调用
?? Trace all system calls which involve process management. This is
?? useful for watching the fork, wait, and exec steps of a process.
?? 如:strace -o temp7.txt -e trace=process cat temp.txt


?? -e trace=network
?? 跟踪所有和网络相关的系统调用
?   如:strace -e trace=network ping 172.14.107.101

?? -e trace=signal
跟踪所有与信号相关的系统调用

?? -e trace=ipc
??跟踪所有与IPC相关的系统调用

-e trace=file
只跟踪有关文件操作的系统调用.
如:strace -o file.trace -e trace=file cat temp.txt

?? -e abbrev=set
?? Abbreviate the output from printing each member of large structures.
?? 缺省是abbrev=all,-v选项等价于abbrev=none
??
?? -e signal=set
?? 只跟踪指定的信号列表,缺省是signal=all。signal=!SIGIO (or signal=!io)
?? 导致 SIGIO 信号不被跟踪
??
-e read=set
输出从指定文件中读出的数据.
例如: -e read=3,5

-e write=set
输出写入到指定文件中的数据.

-e raw=set
将指定的系统调用的参数以十六进制显示.

?? -f
??跟踪某个进程时,如果发生fork()调用,则选择跟踪子进程
??
?? -ff
?? 如果-o file选项有效指定,则跟踪过程中新产生的其他相关进程的信息分别写
?? 入file.pid,这里pid是各个进程号。
?? 如:strace -o temp1 -ff cat temp.txt

?? -i
?? 输出系统调用的入口指针
?   如:strace -o tmp.txt -i cat temp.txt

?? -o filename
?? 指定保存strace输出信息的文件,默认使用标准错误输出stderr
??
?? -p pid
?? 指定待跟踪的进程号,可以用Ctrl+C终止这种跟踪而被跟踪进程继续运行。可以
?? 指定多达32个-p参数同时进行跟踪,此参数常用来调试后台进程。
?? 比如 strace -ff -o output -p 14653 -p 14117

     -r
以第一个系统调用(通常为execve)计时,精确到微秒
?? 如:strace -o temp3.txt -r cat temp.txt

?? -t
?? 与-r选项类似,只不过-r采用相对时间戳,-t采用绝对时间戳(当前时钟)
?? 如:strace -o temp4.txt -t cat temp.txt

?? -tt
?? 与-t类似,绝对时间戳中包含微秒
如:strace -tt cat temp.txt

?? -T
?? 这个选项显示单个系统调用耗时
     如:strace -T cat temp.txt

?? -u username
?? 用指定用户的UID、GID以及辅助组身份运行待跟踪程序
??
-x
以十六进制形式输出非标准字符串

-xx
所有字符串以十六进制形式输出

-q
禁止输出关于脱离的消息

-S sortby:分类排序
sort syscall counts by: time, calls, name, nothing (default time)
sortby取值:time、calls、name或nothing。
如按time排序:strace -c -D -S time cat temp.txt

-v
输出所有的系统调用.一些调用关于环境变量,状态,输入输出等调用由于使用频繁,默认不输出.如:strace -v -o file.txt cat tmp.txt


-c
统计每一系统调用所执行的时间,次数和出错的次数等

-d
输出strace关于标准错误的调试信息

-a column
?? 指定显示返回值的列位置,默认是40(从0开始计数),就是说"="出现在40列的位置。

-s strsize
?? 指定字符串最大显示长度,默认32。但文件名总是显示完整。

-h
?? 显示帮助信息

?? -V
?? 显示strace版本信息
目前我所使用的strace版本信息如下:
?? dl_scu ~ # strace -V
strace -- version 4.5.19

#strace -c -D ls
#strace -c -D -e trace=open ls
二、strace分析和定位问题案例:
引言
“Oops,系统挂死了..."
“Oops,程序崩溃了..."
“Oops,命令执行报错..."
对于维护人员来说,这样的悲剧每天都在上演。理想情况下,系统或应用程序的错误日志提供了足够全面的信息,通过查看相关日志,维护人员就能很快地定位出问 题发生的原因。但现实情况,许多错误日志打印模凌两可,更多地描述了出错时的现象(比如"could not open file","connect to XXX time out",而非出错的原因。
错误日志不能满足定位问题的需求,我们能从更“深层”的方面着手分析吗?程序或命令的执行,需要通过系统调用(system call)与操作系统产生交互,其实我们可以通过观察这些系统调用及其参数、返回值,界定出错的范围,甚至找出问题出现的根因。
在Linux中,strace就是这样一款工具。通过它,我们可以跟踪程序执行过程中产生的系统调用及接收到的信号,帮助我们分析程序或命令执行中遇到的异常情况。
一个简单的例子
如何使用strace对程序进行跟踪,如何查看相应的输出?下面我们通过一个例子来说明。
1.被跟踪程序示例
//main.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main( )
{
  int fd ;
  int i = 0 ;
  fd = open( “/tmp/foo”, O_RDONLY ) ;
  if ( fd < 0 )
    i=5;
  else
    i=2;
  return i;
}

以上程序尝试以只读的方式打开/tmp/foo文件,然后退出,其中只使用了open这一个系统调用函数。之后我们对该程序进行编译,生成可执行文件:
lx@LX:~$ gcc main.c -o main

2.strace跟踪输出
使用以下命令,我们将使用strace对以上程序进行跟踪,并将结果重定向至main.strace文件:
lx@LX:~$ strace -o main.strace ./main
接下来我们来看main.strace文件的内容:
lx@LX:~$ cat main.strace
1 execve("./main", ["./main"], [/* 43 vars */]) = 0
2 brk(0)                                  = 0x9ac4000
3 access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
4 mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7739000
5 access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
6 open("/etc/ld.so.cache", O_RDONLY)      = 3
7 fstat64(3, {st_mode=S_IFREG|0644, st_size=80682, ...}) = 0
8 mmap2(NULL, 80682, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7725000
9 close(3)                                = 0
10 access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or directory)
11 open("/lib/i386-linux-gnu/libc.so.6", O_RDONLY) = 3
12 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\220o\1\0004\0\0\0"..., 512) = 512
13 fstat64(3, {st_mode=S_IFREG|0755, st_size=1434180, ...}) = 0
14 mmap2(NULL, 1444360, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x56d000
15 mprotect(0x6c7000, 4096, PROT_NONE)     = 0
16 mmap2(0x6c8000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x15a) = 0x6c8000
17 mmap2(0x6cb000, 10760, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x6cb000
18 close(3)                                = 0
19 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7724000
20 set_thread_area({entry_number:-1 -> 6, base_addr:0xb77248d0, limit:1048575, seg_32bit:1, contents:0, read_exec_    only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
21 mprotect(0x6c8000, 8192, PROT_READ)     = 0
22 mprotect(0x8049000, 4096, PROT_READ)    = 0
23 mprotect(0x4b0000, 4096, PROT_READ)     = 0
24 munmap(0xb7725000, 80682)               = 0
25 open("/tmp/foo", O_RDONLY)              = -1 ENOENT (No such file or directory)
26 exit_group(5)                           = ?

看到这一堆输出,是否心生畏难情绪?不用担心,下面我们对输出逐条进行分析。
strace跟踪程序与系统交互时产生的系统调用,以上每一行就对应一个系统调用,格式为:
系统调用的名称( 参数... ) = 返回值 错误标志和描述
Line 1: 对于命令行下执行的程序,execve(或exec系列调用中的某一个)均为strace输出系统调用中的第一个。strace首先调用fork或clone函数新建一个子进程,然后在子进程中调用exec载入需要执行的程序(这里为./main)
Line 2: 以0作为参数调用brk,返回值为内存管理的起始地址(若在子进程中调用malloc,则从0x9ac4000地址开始分配空间)
Line 3: 调用access函数检验/etc/ld.so.nohwcap是否存在
Line 4: 使用mmap2函数进行匿名内存映射,以此来获取8192bytes内存空间,该空间起始地址为0xb7739000,关于匿名内存映射,可以看这里
Line 6: 调用open函数尝试打开/etc/ld.so.cache文件,返回文件描述符为3
Line 7: fstat64函数获取/etc/ld.so.cache文件信息
Line 8: 调用mmap2函数将/etc/ld.so.cache文件映射至内存,关于使用mmap映射文件至内存,可以看这里
Line 9: close关闭文件描述符为3指向的/etc/ld.so.cache文件
Line12: 调用read,从/lib/i386-linux-gnu/libc.so.6该libc库文件中读取512bytes,即读取ELF头信息
Line15: 使用mprotect函数对0x6c7000起始的4096bytes空间进行保护(PROT_NONE表示不能访问,PROT_READ表示可以读取)
Line24: 调用munmap函数,将/etc/ld.so.cache文件从内存中去映射,与Line 8的mmap2对应
Line25: 对应源码中使用到的唯一的系统调用——open函数,使用其打开/tmp/foo文件
Line26: 子进程结束,退出码为5(为什么退出值为5?返回前面程序示例部分看看源码吧:)

3.输出分析
呼呼!看完这么多系统调用函数,是不是有点摸不着北?让我们从整体入手,回到主题strace上来。
从上面输出可以发现,真正能与源码对应上的只有open这一个系统调用(Line25),其他系统调用几乎都用于进行进程初始化工作:装载被执行程序、载入libc函数库、设置内存映射等。
源码中的if语句或其他代码在相应strace输出中并没有体现,因为它们并没有唤起系统调用。strace只关心程序与系统之间产生的交互,因而strace不适用于程序逻辑代码的排错和分析。

使用strace处理程序挂死
最后我们通过一个程序示例,学习使用strace分析程序挂死的方法。
1.挂死程序源码
//hang.c
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>

int main(int argc, char** argv)
{
    getpid(); //该系统调用起到标识作用
    if(argc < 2)
    {
        printf("hang (user|system)\n";
        return 1;
    }
    if(!strcmp(argv[1], "user")
        while(1);
    else if(!strcmp(argv[1], "system")
        sleep(500);
    return 0;
}

可向该程序传送user和system参数,以上代码使用死循环模拟用户态挂死,调用sleep模拟内核态程序挂死。

2.strace跟踪输出
用户态挂死跟踪输出:
lx@LX:~$ gcc hang.c -o hang
lx@LX:~$ strace ./hang user
……
mprotect(0x8049000, 4096, PROT_READ)    = 0
mprotect(0xb59000, 4096, PROT_READ)     = 0
munmap(0xb77bf000, 80682)               = 0
getpid()                                = 14539

内核态挂死跟踪输出:
lx@LX:~$ strace ./hang system
……
mprotect(0x8049000, 4096, PROT_READ)    = 0
mprotect(0xddf000, 4096, PROT_READ)     = 0
munmap(0xb7855000, 80682)               = 0
getpid()                                = 14543
rt_sigprocmask(SIG_BLOCK, [CHLD], [], = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, = 0
nanosleep({500, 0},

3.输出分析
用户态挂死情况下,strace在getpid()一行输出之后没有其他系统调用输出;进程在内核态挂死,最后一行的系统调用nanosleep不能完整显示,这里nanosleep没有返回值表示该调用尚未完成。
因而我们可以得出以下结论:使用strace跟踪挂死程序,如果最后一行系统调用显示完整,程序在逻辑代码处挂死;如果最后一行系统调用显示不完整,程序在该系统调用处挂死。
当程序挂死在系统调用处,我们可以查看相应系统调用的man手册,了解在什么情况下该系统调用会出现挂死情况。另外,系统调用的参数也为我们提供了一些信息,例如挂死在如下系统调用:
read(16,
那我们可以知道read函数正在对文件描述符为16的文件或socket进行读取,进一步地,我们可以使用lsof工具,获取对应于文件描述符为16的文件名、该文件被哪些进程占用等信息。
小结
本文对Linux中常用的问题诊断工具strace进行了介绍,通过程序示例,介绍了strace的使用方法、输出格式以及使用strace分析程序挂死问题的方法。

论坛徽章:
3
天秤座
日期:2013-12-27 13:44:58射手座
日期:2014-05-22 16:52:43天蝎座
日期:2014-08-13 16:03:21
32 [报告]
发表于 2011-01-23 14:00 |只看该作者
本帖最后由 compare2000 于 2012-12-25 13:00 编辑

Linux基本命令学习
主要是cd, cat, more, mkdir, cp, rmdir, ln, chmod ,chown, mount, mkfs等文件操作, tar,gzip 等压缩命令, grep, find等查找命令,ps, top等系统监控命令, Vi 的使用,管道,输入输出重定向,系统目录结构, proc文件系统等基本知识。
               参考书目:鸟哥的Linux私房菜基础篇等任意一本Linux基础教程
嵌入式Linux基本环境构建,基本概念
明白交叉编译,工具链,kernel, busybox的配置,rootfs构建,系统启动过程等嵌入式编程的基本概念,单板软件开发基本步骤
                参考书目:嵌入式Linux开发技术详解
AR200的工程构建,配置,启动
GDB学习
学习GDB基本调试命令的使用
               参考GDB的使用手册
Linux环境下系统编程,高级编程
学习IO编程,进程控制,进程通信的知识,
               参考书目:Linux系统编程,UNIX环境高级编程
Linux 内核编程
              参考书目: Linux驱动程序设计,深入理解Linux内核

grep 用来选一行,功能很弱
sed用来逐行处理文本,功能很强,但用来处理行中的列很麻烦
awk解决了sed处理列麻烦的问题,sed能实现的他都能实现
python,perl完全可以代替awk,功能更全。sed 's/.*REGEX.*/\1/' 用REGEX替换整行。
awk如楼上,分列进行操作python: string.split(' ')[5]

/* 演示了线程调度的使用
** Linux目前的线程调度有三个策略,这里只描述最粗略的“印象”
** 1、SCHED_OTHER 默认的线程属性就是这个,多个普通线程间是时间片轮转策略,基本按照10~30ms的节奏进行切换。
** 2、SCHED_FIFO  是实时线程,一旦运行除非主动让出CPU,否则一直使用
** 3、SCHED_RR    SCHED_FIFO的衍生版本,除非主动出让CPU否则也是一直占用,不过多个RR之间会根据时间片分享CPU。
**
** 实时线程(SCHED_FIFO和SCHED_RR)与非实时线程的区别,可以用内核的中断与普通进程做类比。
** 实时线程响应及时,就绪状态的线程可以确保在1个时钟滴答(10ms)被调度。但最好不要长时间占用
** CPU,跟中断一样,如果长时间占用会导致系统的其他线程无法顺利调度。因此,这几个策略的使用建议是:
** 1、要想做到均衡调度,使用普通线程即可。通过nice值,调节各线程间的均衡配比。
** 2、要想响应及时,可以使用实时线程。但切记,运行时间要短。
**
** 这个示例演示了普通线程的均衡调度,以及一个实时线程的及时响应:
** 线程1、2、3、5,是普通线程,1的优先级最高,5的最低;线程4是个实时线程,使用了SCHED_RR策略。
** 线程5虽然也是一个普通线程,优先级最低,但会主动出让CPU;与线程4做相同的任务。
** 这几个线程运行后,会向同一个数组中写入当前线程号和当前时间,通过检查当前线程号是否一致,
** 即可确定线程是否发生过切换。此时打印出,切换顺序,以及所有线程最后一次运行的时间值。
**
** 测试数据可以发现,调度到3的概率要比1、2低一些。4号线程,每次唤醒后必然会得到调度,即10ms调度一次。
** 5号线程由于主动出让CPU,10ms的时间片用不完,从而获得了优先级的额外加成,优先级反而会比1、2、3高一些。
** 注意这一句“if((nIndex >= 4) && ((i % 3000) == 0))        usleep(0);”,这里主要是让4、5线程调度后多做一些事情。
** 如果线程4、5执行时间再短,改成“if(nIndex >= 4)usleep(0);”,线程4、5的高优先级体现更明显。
**
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <sched.h>

#ifndef _POSIX_PRIORITY_SCHEDULING
#error _POSIX_PRIORITY_SCHEDULING
#endif

static inline int LogGetTime(void)
{
        struct timeval time;
        gettimeofday(&time, NULL);
        return time.tv_sec*1000 + (time.tv_usec/1000);
}

int g_nLogAddr[64];

void *thread_printa(void *p)
{
        struct timespec ts;
    int nIndex = (int)p;
    int i=0;
    // 普通线程,使用nice进行优先级设置
    // 实时线程,不需要再设置了,好像设了也没用。优先级本来就很高了
        if(nIndex == 4)        nice(nIndex*3);

        while(1)
        {
            i++;
            // 线程切换时会打印出来,并把所有进程最后一次运行的时间也打出来
                if(g_nLogAddr[0] != nIndex)
                {
                    printf("[%d --> %d], [%d,%d,%d,%d,%d]\n", g_nLogAddr[0], nIndex, g_nLogAddr[1], g_nLogAddr[2], g_nLogAddr[3], g_nLogAddr[4], g_nLogAddr[5]);
                }
               
                g_nLogAddr[0]       = nIndex;
                g_nLogAddr[nIndex]  = LogGetTime();//理论上,使用了系统调用,会多一些被高优先级任务抢占的可能
               
                // 实时线程不应该运行太久,实时线程要保证的是线程唤醒后立刻被调度
                if((nIndex >= 4) && ((i % 3000) == 0))        usleep(0);
                //if(nIndex >= 4) usleep(0);
        }

        return NULL;
}

int main(int argc, char *argv[])
{
        pthread_attr_t attrNormal, attrRR;
        struct sched_param paramNormal, paramRR;
        pthread_t pid1, pid2, pid3;

//普通优先级的线程
{
        pthread_attr_init(&attrNormal);
           pthread_attr_getschedparam(&attrNormal, &paramNormal);
        //pthread_attr_setscope(&attrNormal, PTHREAD_SCOPE_SYSTEM);
        //pthread_attr_setschedpolicy(&attr1, SCHED_RR);
        paramNormal.sched_priority = 50; //好像普通线程的优先级没有用,使用nice设置
        pthread_attr_setschedparam(&attrNormal, &paramNormal);
        pthread_create(&pid1, &attrNormal, thread_printa, (void*)1);
        pthread_create(&pid2, &attrNormal, thread_printa, (void*)2);
        pthread_create(&pid2, &attrNormal, thread_printa, (void*)5);
}

//实时线程
{
        pthread_attr_init(&attrRR);
           pthread_attr_getschedparam(&attrRR, &paramRR);
        //pthread_attr_setscope(&attrRR, PTHREAD_SCOPE_SYSTEM);
        pthread_attr_setschedpolicy(&attrRR, SCHED_RR);
        paramRR.sched_priority = 1; //多个实时线程间的调度使用这个属性
        pthread_attr_setschedparam(&attrRR, &paramRR);
        pthread_create(&pid3, &attrRR, thread_printa, (void*)4);
}       
       
        pthread_attr_destroy(&attrNormal);
    pthread_attr_destroy(&attrRR);
   
        thread_printa((void*)3);

        return 0;

}

论坛徽章:
3
天秤座
日期:2013-12-27 13:44:58射手座
日期:2014-05-22 16:52:43天蝎座
日期:2014-08-13 16:03:21
33 [报告]
发表于 2011-01-23 14:04 |只看该作者
本帖最后由 compare2000 于 2012-12-25 12:06 编辑

Linux线程调度
1调度器的启动通常有两种方式:
A. 主动式
在核心应用中直接调用schedule()。这通常发生在因等待核心事件而需要将进程置于挂起(休眠)状态的时候--这时应该主动请求调度以方便其他进程使用CPU。下面就是一个主动调度的例子:
/* 节选自[drivers/input/mousedev.c] mousedev_read() */
add_wait_queue(&list->mousedev->wait, &wait);
current->state = TASK_INTERRUPTIBLE;
while (!list->ready) {
if (file->f_flags & O_NONBLOCK) {
retval = -EAGAIN;
break;
}
if (signal_pending(current)) {
retval = -ERESTARTSYS;
break;
}
schedule();
}
current->state = TASK_RUNNING; /* 这一句实际上可以省略,因为进程的状态在唤醒过程中就已经恢复到TASK_RUNNING了 */
remove_wait_queue(&list->mousedev->wait, &wait);
其过程通常可分为四步:
将进程添加到事件等待队列中;
置进程状态为TASK_INTERRUPTIBLE(或TASK_UNINTERRUPTIBLE);
在循环中检查等待条件是否满足,不满足则调用schedule(),满足了就退出循环;
将进程从事件等待队列中删除。
从" 调度器工作流程"中我们知道,调度器会将处于休眠状态的进程从就绪队列中删除,而只有就绪队列中的进程才有可能被调度到。将该进程重新放到就绪队列中的动 作是在事件发生时的"唤醒"过程中完成的。在以上所示的鼠标驱动中,鼠标中断将调用mousedev_event()函数,该函数的最后就会使用 wake_up_interruptible()唤醒等待鼠标事件的所有进程。wake_up_interruptible()将最终调用 try_to_wake_up()函数:
/* 节选自[kernel/sched.c] */
static inline int try_to_wake_up(struct task_struct * p, int synchronous)
{
unsigned long flags;
int success = 0;
spin_lock_irqsave(&runqueue_lock, flags);
p->state = TASK_RUNNING;
if (task_on_runqueue(p))
goto out;
add_to_runqueue(p); /* 添加到就绪队列中 */
if (!synchronous || !(p->cpus_allowed & (1 << smp_processor_id())))
reschedule_idle(p); /* 这种情况下调用wake_up(),synchronous总为0,此时,*/
/* 如果本CPU不适合运行该进程,则需要调用reschedule_idle()寻找合适的CPU */
success = 1;
out:
spin_unlock_irqrestore(&runqueue_lock, flags);
return success;
}
这时启动schedule()就是被动的了。


2 进程调度方法

一〉调度策略

调度策略考虑的几个因素:

1>IO型任务与cpu密集型任务

   linux为IO密集型任务提供高优先级,cpu密集型任务提供低优先级,使得IO密集型任务在IO完成时得到迅速反映

2>进程优先级:

linux 实施了动态优先级调度策略。有两种优先级参数:nice value和 real time 优先级。nice value由用户指定,范围在-19--20之间,real time优先级从0--99。拥有实时优先级的进程比基于nice value的进程优先级高,用于需要高度实时性的进程。基于这些优先级参数,linux在运行时动态调整进程的优先级

3)时间片

进程连续执行的一段时间称为时间片。长的时间片使得系统的交互性降低,过短的时间片增加了进程切换的开销,同时不利于cache的作用发挥。linux给高优先级的进程较长的时间片,低优先级的进程较短的时间片。

二〉数据结构

runqueue结构维护了一个cpu上的所有进程的信息。任何进程只属于一个runqueue。runqueue中包含active的优先级队列和iexpire优先级队列。对renqueue进行读写操作时,需要先对之加锁。

优先级对列数据结构为

struct prio_array{

int nr_active; //该结构中所有进程的个数

unsigned long bitmap[BITMAP_SIZE];//优先级位图,用于快速查找下一个运行的进程

struct list_head queue[MAX_PRIO];//优先级对列向量。向量中的每个元素为对应优先级的进程队列头

};


三种调度策略
(1)SCHED_OTHER。SCHED_OTHER是面向普通进程的时间片轮转策略。采用该策略时,系统为处于TASK_RUNNING状态的每个进程分配一个时间片。当时间片用完时,进程调度程序再选择下一个优先级相对较高的进程,并授予CPU使用权。
(2) SCHED_FIFO。SCHED_FIFO策略适用于对响应时间要求比较高,运行所需时间比较短的实时进程。采用该策略时,各实时进程按其进入可运行队 列的顺序依次获得CPU。除了因等待某个事件主动放弃CPU,或者出现优先级更高的进程而剥夺其CPU之外,该进程将一直占用CPU运行。
(3)SCHED_RR。SCHED_RR策略适用于对响应时间要求比较高,运行所需时间比较长的实时进程。采用该策略时,各实时进程按时间片轮流使用CPU。当一个运行进程的时间片用完后,进程调度程序停止其运行并将其置于可运行队列的末尾。

3进程调度依据
Linux 只有一个可运行队列,处于TASK_RUNNING状态的实时进程和普通进程都加入到这个可运行队列中。Linux的进程调度采用了动态优先级和权值调控 的方法,既可实现上述三种调度策略,又能保证实时进程总是比普通进程优先使用CPU。描述进程的数据结构task_struct中用以下几个数据作为调度 依据:
Struct task_struct {
    ……
    volatile long need_resched; /*是否需要重新调度*/
long counter; /*进程当前还拥有的时间片*/
long nice; /*普通进程的动态优先级,来自UNIX系统*/
unsigned long policy; /*进程调度策略*/
unsigned long rt_priority; /*实时进程的优先级*/
……
};
counter的值是动态变化的,进程运行时,每一个时钟滴答后,其值减1。当counter值为0时,表示该进程时间片已用完,该进程回到可运行队列中,等待再次调度。
为 保证实时进程优于普通进程,Linux采取加权处理法。在进程调度过程中,每次选取下一个运行进程时,调度程序首先给可运行队列中的每个进程赋予一个权值 weight。普通进程的权值就是其counter和优先级nice的综合,而实时进程的权值是它的rt_priority的值加1000,确保实时进程 的权值总能大于普通进程。调度程序检查可运行队列中所有进程的权值,选取权值最大者作为下一个运行进程,保证了实时进程优先于普通进程获得CPU。

进程获得的CPU时间的绝对数目取决于它的初始counter值,

初始的counter的计算公式(sched.c in kernel
p->counter = (p->counter >> 1) + ((20 - p->nice) >> 2) +1) p->counter = (p->counter >> 1) + ((20 - p->nice) >> 2) +1)
由公式可以計算出,對於標準進程(p->nice 為0), 得到的初始counter為6,即進程獲得的時間片為60ms。由公式可以计算出,对于标准进程(p->nice为0),得到的初始counter为6,即进程获得的时间片为60ms。
最高優先級進程(nice為-19)的初始counter值為10,進程的時間片為100ms。最高优先级进程(nice为-19)的初始counter值为10,进程的时间片为100ms。
最低優先級進程(nice為20)的初始counter值為1,進程時間片為10ms。最低优先级进程(nice为20)的初始counter值为1,进程时间片为10ms。
結論是最高優先級進程會獲得最低優先級進程10倍的執行時間,普通優先級進程接近兩倍的執行時間。结论是最高优先级进程会获得最低优先级进程10倍的执行时间,普通优先级进程接近两倍的执行时间。 當然,這是在進程不進行任何IO操作的時候的數據,在有IO操作的時候,進程會經常被迫睡眠來等待IO操作的完成,真正所佔用的CPU時間是很難比較的。当然,这是在进程不进行任何IO操作的时候的数据,在有IO操作的时候,进程会经常被迫睡眠来等待IO操作的完成,真正所占用的CPU时间是很难比较的。
我們可以看到每次重新計算counter的時候,新的counter值都要加上它本身剩餘值的一半,這種獎勵只適用於通過SCHED_YIELD主動放棄CPU的進程,只有它在重新計算的時候counter值沒有用完,所以在計算後counter值會增大,但永遠不可能超過20。我们可以看到每次重新计算counter的时候,新的counter值都要加上它本身剩余值的一半,这种奖励只适用于通过SCHED_YIELD主动放弃CPU的进程,只有它在重新计算的时候counter值没有用完,所以在计算后counter值会增大,但永远不可能超过20

Linux使用内核函数goodness()对进程进行加权处理:
Static inline goodness
(struct task_struct * pint this_cpu, struct mm_struct *this_mm)
{
Int weight;
Weight=-1;
/*判断如果任务的调度策略被置为SCHED_YIELD的话,则置权值为-1,返回。
系统调用SCHED_YIELD表示为“礼让”进程,其权值为最低*/
If (p->policy & SCHED_YIELD)
        goto out;
/*先对普通进程进行处理(由于多数是普通进程,这样做有利于提高系统效率)*/
If (p->policy==SCHED_OTHER){
      weight=p->counter;         /*返回权值为进程的counter值*/
/*如果当前进程的counter为0,则表示当前进程的时间片已用完,直接返回*/
If (! weight)
        Goto out;
#Ifdef CONFIG_SMP
If (p->processor==this_cpu)
                 Weight+=PROC_CHANGE_PENALTY;
#Endif
/*对进程权值进行微调,如果进程的内存空间使用当前正在运行的进程的内存空间,
则权值额外加1*/
     If (p->mm==this_mm||! p->mm)
              Weight+=1;
/*将权值加上20与进程优先级nice的差。普通进程的权值主要由counter值和nice值组成*/
Weight+=20-p->nice;
Goto out;
}
/*对实时进程进行处理,返回权值为rt_priority+1000,确保优先级高于普通进程*/
Weight=1000+p->rt_priority;
Out:
return weight; 
}
从goodness ()函数可以看出,对于普通进程,其权值主要取决于剩余的时间配额和nice两个因素。nice的规定取值范围为19~-20,只有特权用户才能把 nice值设为负数,而表达式(20-p->nice)掉转方向成为1~40。所以,综合的权值在时间片尚未用完时基本上是两者之和。如果是内核进 程,或者其用户空间与当前进程相同,则权值将额外加1作为奖励。对于实时进程,其权值为1000+p->rt_priority,当p-> counter达到0时该进程将移到队列的尾部,但其优先级仍不少于1000。可见当有实时进程就绪时,普通进程是没机会运行的。
由此可以看出,通过goodness()函数,Linux从优先考虑实时进程出发,实现了多种调度策略的统一处理,其设计思想可谓非常巧妙。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

调度程序运行时,要在所有可运行状态的进程中选择最值得运行的进程投入运行。选择进程的依据是什么呢?在每个进程的task_strUCt结构中有以下四项:policy、priority、counter、rt_priority。这四项是选择进程的依据。 其中,policy是进程的调度策略,用来区分实时进程和普通进程,实时进程优先于普通进程运行;priority是进程(包括实时和普通)的静态优先级;counter是进程剩余的时间片,它的起始值就是priority的值;由于counter在后面计算一个处于可运行状态的进程值得运行的程度goodness时起重要作用,因此,counter也可以看作是进程的动态优先级。rt_priority是实时进程特有的,用于实时进程间的选择。
  Linux用函数goodness()来衡量一个处于可运行状态的进程值得运行的程度。该函数综合了以上提到的四项,还结合了一些其他的因素,给每个处于可运行状态的进程赋予一个权值(weight),调度程序以这个权值作为选择进程的唯一依据。关于goodness()的情况在后面将会具体分析。
  
  进程调度策略
  
  调度程序运行时,要在所有处于可运行状态的进程之中选择最值得运行的进程投入运行。选择进程的依据是什么呢?在每个进程的task_struct 结构中有这么四项:
  
  policy, priority , counter, rt_priority
  
  这四项就是调度程序选择进程的依据.其中,policy是进程的调度策略,用来区分两种进程-实时和普通;priority是进程(实时和普通)的优先级;counter 是进程剩余的时间片,它的大小完全由priority决定;rt_priority是实时优先级,这是实时进程所特有的,用于实时进程间的选择。
  
  首先,Linux 根据policy从整体上区分实时进程和普通进程,因为实时进程和普通进程度调度是不同的,它们两者之间,实时进程应该先于普通进程而运行,然后,对于同一类型的不同进程,采用不同的标准来选择进程:
  
  对于普通进程,Linux采用动态优先调度,选择进程的依据就是进程counter的大小。进程创建时,优先级priority被赋一个初值,一般为0~70之间的数字,这个数字同时也是计数器counter的初值,就是说进程创建时两者是相等的。字面上看,priority是\"优先级\"、counter是\"计数器\"的意思,然而实际上,它们表达的是同一个意思-进程的\"时间片\"。Priority代表分配给该进程的时间片,counter表示该进程剩余的时间片。在进程运行过程中,counter不断减少,而priority保持不变,以便在counter变为0的时候(该进程用完了所分配的时间片)对counter重新赋值。当一个普通进程的时间片用完以后,并不马上用priority对counter进行赋值,只有所有处于可运行状态的普通进程的时间片(p->counter==0)都用完了以后,才用priority对counter重新赋值,这个普通进程才有了再次被调度的机会。这说明,普通进程运行过程中,counter的减小给了其它进程得以运行的机会,直至counter减为0时才完全放弃对CPU的使用,这就相对于优先级在动态变化,所以称之为动态优先调度。至于时间片这个概念,和其他不同操作系统一样的,Linux的时间单位也是\"时钟滴答\",只是不同操作系统对一个时钟滴答的定义不同而已(Linux为10ms)。进程的时间片就是指多少个时钟滴答,比如,若priority为20,则分配给该进程的时间片就为20个时钟滴答,也就是20*10ms=200ms。Linux中某个进程的调度策略(policy)、优先级(priority)等可以作为参数由用户自己决定,具有相当的灵活性。内核创建新进程时分配给进程的时间片缺省为200ms(更准确的,应为210ms),用户可以通过系统调用改变它。
  
  对于实时进程,Linux采用了两种调度策略,即FIFO(先来先服务调度)和RR(时间片轮转调度)。因为实时进程具有一定程度的紧迫性,所以衡量一个实时进程是否应该运行,Linux采用了一个比较固定的标准。实时进程的counter只是用来表示该进程的剩余时间片,并不作为衡量它是否值得运行的标准。实时进程的counter只是用来表示该进程的剩余时间片,并不作为衡量它是否值得运行的标准,这和普通进程是有区别的。上面已经看到,每个进程有两个优先级,实时优先级就是用来衡量实时进程是否值得运行的。
  
  这一切看来比较麻烦,但实际上Linux中的实现相当简单。Linux用函数goodness()来衡量一个处于可运行状态的进程值得运行的程度。该函数综合了上面提到的各个方面,给每个处于可运行状态的进程赋予一个权值(weight),调度程序以这个权值作为选择进程的唯一依据。
  
  Linux根据policy的值将进程总体上分为实时进程和普通进程,提供了三种调度算法:一种传统的Unix调度程序和两个由POSIX.1b(原名为POSIX.4)操作系统标准所规定的\"实时\"调度程序。但这种实时只是软实时,不满足诸如中断等待时间等硬实时要求,只是保证了当实时进程需要时一定只把CPU分配给实时进程。
  
  非实时进程有两种优先级,一种是静态优先级,另一种是动态优先级。实时进程又增加了第三种优先级,实时优先级。优先级是一些简单的整数,为了决定应该答应哪一个进程使用CPU的资源,用优先级代表相对权值-优先级越高,它得到CPU时间的机会也就越大。
  
  ? 静态优先级(priority)-不随时间而改变,只能由用户进行修改。它指明了在被迫和其他进程竞争CPU之前,该进程所应该被答应的时间片的最大值(但很可能的,在该时间片耗尽之前,进程就被迫交出了CPU)。

  
  ? 动态优先级(counter)-只要进程拥有CPU,它就随着时间不断减小;当它小于0时,标记进程重新调度。它指明了在这个时间片中所剩余的时间量。
  
  ? 实时优先级(rt_priority)-指明这个进程自动把CPU交给哪一个其他进程;较高权值的进程总是优先于较低权值的进程。假如一个进程不是实时进程,其优先级就是0,所以实时进程总是优先于非实时进程的(但实际上,实时进程也会主动放弃CPU)。
  
  当policy分别为以下值时:
  
  1) SCHED_OTHER:这是普通的用户进程,进程的缺省类型,采用动态优先调度策略,选择进程的依据主要是根据进程goodness值的大小。这种进程在运行时,可以被高goodness值的进程抢先。
  
  2) SCHED_FIFO:这是一种实时进程,遵守POSIX1.b标准的FIFO(先入先出)调度规则。它会一直运行,直到有一个进程因I/O阻塞,或者主动释放CPU,或者是CPU被另一个具有更高rt_priority的实时进程抢先。在Linux实现中,SCHED_FIFO进程仍然拥有时间片-只有当时间片用完时它们才被迫释放CPU。因此,如同POSIX1.b一样,这样的进程就象没有时间片(不是采用分时)一样运行。Linux中进程仍然保持对其时间片的记录(不修改counter)主要是为了实现的方便,同时避免在调度代码的要害路径上出现条件判定语句 if (!(current->policy&SCHED_FIFO)){...}-要知道,其他大量非FIFO进程都需要记录时间片,这种多余的检测只会浪费CPU资源。(一种优化措施,不该将执行时间占10%的代码的运行时间减少到50%;而是将执行时间占90%的代码的运行时间减少到95%。0.9+0.1*0.5=0.95>0.1+0.9*0.9=0.91)
  
  3) SCHED_RR:这也是一种实时进程,遵守POSIX1.b标准的RR(循环round-robin)调度规则。除了时间片有些不同外,这种策略与SCHED_FIFO类似。当SCHED_RR进程的时间片用完后,就被放到SCHED_FIFO和SCHED_RR队列的末尾。
  
  只要系统中有一个实时进程在运行,则任何SCHED_OTHER进程都不能在任何CPU运行。每个实时进程有一个rt_priority,因此,可以按照rt_priority在所有SCHED_RR进程之间分配CPU。其作用与SCHED_OTHER进程的priority作用一样。只有root用户能够用系统调用sched_setscheduler,来改变当前进程的类型(sys_nice,sys_setpriority)。
  此外,内核还定义了SCHED_YIELD,这并不是一种调度策略,而是截取调度策略的一个附加位。如同前面说明的一样,假如有其他进程需要CPU,它就提示调度程序释放CPU。非凡要注重的就是这甚至会引起实时进程把CPU释放给非实时进程。
  
  主要的进程调度的函数分析
  
  真正执行调度的函数是schedule(void),它选择一个最合适的进程执行,并且真正进行上下文切换,使得选中的进程得以执行。而reschedule_idle(struct task_struct *p)的作用是为进程选择一个合适的CPU来执行,假如它选中了某个CPU,则将该CPU上当前运行进程的need_resched标志置为1,然后向它发出一个重新调度的处理机间中断,使得选中的CPU能够在中断处理返回时执行schedule函数,真正调度进程p在CPU上执行。在schedule()和reschedule_idle()中调用了goodness()函数。goodness()函数用来衡量一个处于可运行状态的进程值得运行的程度。此外,在schedule()函数中还调用了schedule_tail()函数;在reschedule_idle()函数中还调用了reschedule_idle_slow()。这些函数的实现对理解SMP的调度非常重要,下面一一分析这些函数。先给出每个函数的主要流程图,然后给出源代码,并加注释。
  
  goodness()函数分析
  
  goodness()函数计算一个处于可运行状态的进程值得运行的程度。一个任务的goodness是以下因素的函数:正在运行的任务、想要运行的任务、当前的CPU。goodness返回下面两类值中的一个:1000以下或者1000以上。1000或者1000以上的值只能赋给\"实时\"进程,从0到999的值只能赋给普通进程。实际上,在单处理器情况下,普通进程的goodness值只使用这个范围底部的一部分,从0到41。在SMP情况下,SMP模式会优先照顾等待同一个处理器的进程。不过,不管是UP还是SMP,实时进程的goodness值的范围是从1001到1099。
  
  goodness()函数其实是不会返回-1000的,也不会返回其他负值。由于idle进程的counter值为负,所以假如使用idle进程作为参数调用goodness,就会返回负值,但这是不会发生的。
资料引用:http://www.knowsky.com/386808.html



论坛徽章:
3
天秤座
日期:2013-12-27 13:44:58射手座
日期:2014-05-22 16:52:43天蝎座
日期:2014-08-13 16:03:21
34 [报告]
发表于 2011-01-23 14:05 |只看该作者
本帖最后由 compare2000 于 2013-07-20 09:53 编辑

《Linux下进程调度与优先级的深入分析》
1)初识调度


为配合系统对进程的调度,采用两种方式进行处理
1.1)协同多任务处理

当进程因为事件的等待,而自动放弃CPU资源,而使其它进程得以使用CPU,这时称之为协同多任务处理.
其实如果进程都采用协同多任务处理时,系统将会轻松的调度进程,以分配资源

1.2)抢先式多任务处理
当进程不进行I/O,比如计算型运算应用时,一直占用大量的CPU时间,这时系统将会利用中断,使原占用CPU的进程放弃CPU.
这时称之为抢先式多任务处理

1.3)总结
1.3.1)UNIX/LINUX采用协同多任务处理与抢先式多任务处理相结合的方式处理进程.
1.3.2)当进程都采用协同多任务处理,系统就可能永远不会用到抢先式.
1.3.3)调度程序本身也是一个进程,PID是0,是INIT进行的父进程






2)阻塞,抢先占用和放弃


2.1)抢先占用的触发:

2.1.1)当一个进程因为它的时间片用完而被内核停止执行时,就说这个进程被抢占.
2.1.2)当一个享有更高优先公的进程在就绪队列,内核同样可以抢占正在执行的进程,即使它的时间片还没用完.


2.2)放弃的触发:
2.2.1)用户进程可以通过sched_yield系统调用来放弃使用CPU.
2.2.2)用户进程通过其它系统调用来放弃CPU.
例如:一个进程正在调用read/write时,它很可能不得不等待相应的设备的响应,这时它应用使自己睡眠(sleep),放弃CPU,直到设备就绪为止.


2.3)阻塞的触发:
2.3.1)当进程在内核模式下等待一个事件时,就是阻塞,直到所等侍的事件来唤醒它为止.

2.4)总结:
2.4.1)阻塞与放弃的区别
一个阻塞的进程即不会占用CPU,也不会被调度程序调度.而放弃的进程则会被调度程序调度.
2.4.2)linux2.6内核是一个可抢先占有的内核,在不可抢先有的内核则高优先级的进程不能抢占低优先级的进程.





3)优先级

3.1)动态优先级
因为高优先级的进程总比低优先级的进程先被调度,为防止有多个高优先级且一直占用CPU资源,导致其它进程不能占用CPU,所以引用动态优先级概念.

3.2)交互式的进程
如果某个进程被认为是交互式的,那么将被赋予较高的优先权,例如:键盘输入.交互式的进程从来不被抢占,并且占用CPU很少,它们常常自动放弃CPU.

3.3)有效优先级
进程的有效优先级就是静态优先级与额外值的和.

静态优先级是在系统创建时就已经分配给进程了,整个运行周期里不变.
额外值是一个可正可负的值,也可以把额外值理解为动态优先级,因为系统通过改变这个额外值(动态优先级)来改变进程的有效优先级.
额外值是由内核来管理

3.4)用一个例子来说明系统是如何给进程分配动态优先级的

新建nicegy脚本,这个脚本用sleep使其部分时间在睡眠状态.
#!/bin/sh
while true; do
sleep .1
done

新建cruncher脚本,这个脚本在循环中使用true,一直占用CPU.
#!/bin/sh
while true; do
true
done


新建脚本runex,这个脚本使行cruncher和niceguy两个脚本,监控这两个脚本的动态优先级.
#!/bin/sh

./cruncher &
./niceguy &


trap 'echo stoping; kill %1 %2; break' SIGINT

while true; do
        ps -C niceguy -C cruncher -o etime,pid,pri,cmd
        sleep .5
done

运行runex

./runex
    ELAPSED   PID PRI CMD
      00:00  2343  20 /bin/sh ./cruncher
      00:00  2344  21 /bin/sh ./niceguy
    ELAPSED   PID PRI CMD
      00:01  2343  20 /bin/sh ./cruncher
      00:01  2344  22 /bin/sh ./niceguy
    ELAPSED   PID PRI CMD
      00:01  2343  19 /bin/sh ./cruncher
      00:01  2344  22 /bin/sh ./niceguy
    ELAPSED   PID PRI CMD
      00:02  2343  18 /bin/sh ./cruncher
      00:02  2344  23 /bin/sh ./niceguy
    ELAPSED   PID PRI CMD
      00:02  2343  15 /bin/sh ./cruncher
      00:02  2344  23 /bin/sh ./niceguy
    ELAPSED   PID PRI CMD
      00:03  2343  14 /bin/sh ./cruncher
      00:03  2344  23 /bin/sh ./niceguy
    ELAPSED   PID PRI CMD
      00:04  2343  14 /bin/sh ./cruncher
      00:04  2344  23 /bin/sh ./niceguy
      
结论:
1)这两个进程会随时时间变化而变化
进程cruncher会一直运行不休眠(sleep),因此调度程序会给它一个负的额外值以降低它的有效优先级.
而进程niceguy大部从那时间则处于休息状态,因此调度程序会给它一个正的额外值以提高它的有效优先级.
2)而这两个进程在此之后就处于相对稳定的状态.
3)PRI是有效优先级,系统不能改变进程的静态优先级,但可以改变它的额外值以达到降低有效优先级的目的.
例如:静态优先级是20,额外值是-6,则有效优先级就是PRI=20+(-6)=14,注意这里没有涉及nice值,我们下面再来谈nice值对优先级的影响.






4)nice值与有效优先级

4.1)nice值的由来
内核允许用户通过使用一个名为nice的数值来影响调度程序关于优先级的调度
也就是说nice值是用户来触发,而我们上面说的额外值是内核来触发的.

4.2)nice值对有效优先级的影响

nice值越高,有效优先级就越低.
nice值越低,有效优先级就越高.
有效优先级=静态优先值+额外值-nice值
例如:
静态优先值为20
额外值为-6
nice值为-10
那最后有效优先级就是:
PRI=20+(-6)-(-10)=24
而如果nice值为10
PRI=20+(-6)-10=4


4.3)nice与有效优先级的范围

nice的范围是-20到19
有效优先级的范围是0-39


4.4)例子:nice是如何影响有效优先级的

cruncher进程的有效优先级是14,nice值是0

ps -C cruncher -o etime,pid,pri,ni,cmd
    ELAPSED   PID PRI  NI CMD
      00:17  6034  14   0 /bin/sh ./cruncher

更改nice值为-20
renice -20 -p 6034
6034: old priority 0, new priority -20

当nice的值为-20,PRI的值变成34
PRI = 静态优先级(20) + 附加值(-6) - nice(-20) = 34
ps -C cruncher -o etime,pid,pri,ni,cmd
    ELAPSED   PID PRI  NI CMD
      00:39  6034  34 -20 /bin/sh ./cruncher

更改nice的值为19
renice 19 -p 6034
6034: old priority -20, new priority 19

当nice的值为19,PRI的值为0
PRI = 静态优先级(20) + 附加值(-6) - nice(19) = 0 因为最低0,即使是-5最后也0

ps -C cruncher -o etime,pid,pri,ni,cmd
    ELAPSED   PID PRI  NI CMD
      01:03  6034   0  19 /bin/sh ./cruncher

注意RI为34时,系统的反应会变慢.

论坛徽章:
3
天秤座
日期:2013-12-27 13:44:58射手座
日期:2014-05-22 16:52:43天蝎座
日期:2014-08-13 16:03:21
35 [报告]
发表于 2011-01-23 14:07 |只看该作者
本帖最后由 compare2000 于 2012-12-25 13:03 编辑

5)实时优先级

5.1)实时优先级概述:
linux提供了一个实时调度策略,提供了100个额外优先级别,以保证系统能及时响应进程.

5.2)实时优先级和普通优先级的区别:
实时优先级比普通优先级高,普通优先级是0-39.而实时优先级是(41-139),优先级一般不用40.

实时优先级在整个进程的生命周期里是不变的,所以实时进程没有nice值,也没有额外值.它的有效优先级就是静态优先级.

5.3)POSIX标准为实时进程指定了两种策略:先进先出(FIFO),时间片法(Round_Robin,简称RR)

5.3.1)先进先出(FIFO)调度
如果有两个同优先级的进程位于就绪队列,通常情况下,排在前面的先被执行

FIFO的策略要求进程不能抢占CPU,除非另一个实时进程有更高优先级

5.3.2)FIFO调度的例子
这个程序将永远不会退出.系统将会死机.

新建chewer脚本
#!/bin/sh
(sleep 50;kill -ALRM $$) &
while true;do
true;
done

程序为什么不在50秒之后退出呢,原因是一个fifo的调度,是不会运行(sleep 5;kill -ALRM $$),而永远进入了一个死循环.
在2.6.18的内核中,这个会造成死机,而新的2.6.32内核则不会,我们依然有机会终止它.
我们在2.6.32的内核中看下它的优先级

指定调度策略为FIFO,优先级为50
chrt -f 50 ./chewer &
[2] 2414

查看优先级,CLS显示了调度策略,chewer的调度策略是FF,FF表示FIFO,PTRPIO是实时优先级,这里chewer是50,
PRI是有效优先级,在实时系统里也叫绝对优先级,有效优先级是实时优先级与40的和,所以这里是90.

ps -eo pid,ppid,tid,class,rtprio,ni,pri,psr,pcpu,stat,wchan:14,command
  PID  PPID   TID CLS RTPRIO  NI PRI PSR %CPU STAT WCHAN          COMMAND
    1     0     1 TS       -   0  19   0  0.0 Ss   poll_schedule_ init [2]  
    2     0     2 TS       -   0  19   0  0.0 S    kthreadd       [kthreadd]
    3     2     3 FF      99   - 139   0  0.0 S    migration_thre [migration/0]
    4     2     4 TS       -   0  19   0  0.0 S    ksoftirqd      [ksoftirqd/0]
    5     2     5 TS       -   0  19   0  0.0 S    worker_thread  [events/0]
    6     2     6 TS       -   0  19   0  0.0 S    worker_thread  [khelper]
   11     2    11 TS       -   0  19   0  0.0 S    async_manager_ [async/mgr]
   58     2    58 TS       -   0  19   0  0.0 S    bdi_sync_super [sync_supers]
   60     2    60 TS       -   0  19   0  0.0 S    bdi_forker_tas [bdi-default]
   62     2    62 TS       -   0  19   0  0.0 S    worker_thread  [kblockd/0]
   64     2    64 TS       -   0  19   0  0.0 S    worker_thread  [kacpid]
   65     2    65 TS       -   0  19   0  0.0 S    worker_thread  [kacpi_notify]
   66     2    66 TS       -   0  19   0  0.0 S    worker_thread  [kacpi_hotplug]
  118     2   118 TS       -   0  19   0  0.0 S    serio_thread   [kseriod]
  168     2   168 TS       -   0  19   0  0.0 S    kswapd         [kswapd0]
  169     2   169 TS       -   0  19   0  0.0 S    worker_thread  [aio/0]
  170     2   170 TS       -   0  19   0  0.0 S    worker_thread  [crypto/0]
  552     2   552 TS       -   0  19   0  0.0 S    scsi_error_han [scsi_eh_0]
  812     2   812 TS       -   0  19   0  0.0 S    kjournald      [kjournald]
  902     1   902 TS       -  -4  23   0  0.0 S<s  poll_schedule_ udevd --daemon
1035     2  1035 TS       -   0  19   0  0.0 S    worker_thread  [kpsmoused]
1551     2  1551 TS       -   0  19   0  0.0 S    worker_thread  [kstriped]
1562     2  1562 TS       -   0  19   0  0.0 S    worker_thread  [ksnapd]
1588     2  1588 TS       -   0  19   0  0.0 S    kjournald      [kjournald]
1589     2  1589 TS       -   0  19   0  0.0 S    kjournald      [kjournald]
1659     1  1659 TS       -   0  19   0  0.0 Ss   poll_schedule_ dhclient3 -pf /var/run/dhclient.eth0.pid -lf /var/lib/dhcp3/dhclie
1675     1  1675 TS       -   0  19   0  0.0 Ss   poll_schedule_ /sbin/portmap
1839     1  1839 TS       -   0  19   0  0.0 Sl   poll_schedule_ /usr/sbin/rsyslogd -c3
1852     1  1852 TS       -   0  19   0  0.0 Ss   poll_schedule_ /usr/sbin/acpid
2127     1  2127 TS       -   0  19   0  0.0 Ss   poll_schedule_ /usr/sbin/exim4 -bd -q30m
2139     1  2139 TS       -   0  19   0  0.0 Ss   poll_schedule_ /usr/sbin/inetd
2158     1  2158 TS       -   0  19   0  0.0 Ss   poll_schedule_ /usr/sbin/sshd
2162     1  2162 TS       -   0  19   0  0.0 Ss   poll_schedule_ /sbin/rpc.statd
2163  2158  2163 TS       -   0  19   0  0.0 Ss   poll_schedule_ sshd: root@pts/0,pts/1
2172     1  2172 TS       -   0  19   0  0.0 Ss   hrtimer_nanosl /usr/sbin/atd
2192     1  2192 TS       -   0  19   0  0.0 Ss   hrtimer_nanosl /usr/sbin/cron
2206  2163  2206 TS       -   0  19   0  0.0 Ss   wait           -bash
2211     1  2211 TS       -   0  19   0  0.0 Ss   poll_schedule_ /usr/sbin/apache2 -k start
2228     1  2228 TS       -   0  19   0  0.0 Ss+  n_tty_read     /sbin/getty 38400 tty1
2229     1  2229 TS       -   0  19   0  0.0 Ss+  n_tty_read     /sbin/getty 38400 tty2
2230     1  2230 TS       -   0  19   0  0.0 Ss+  n_tty_read     /sbin/getty 38400 tty3
2231     1  2231 TS       -   0  19   0  0.0 Ss+  n_tty_read     /sbin/getty 38400 tty4
2232     1  2232 TS       -   0  19   0  0.0 Ss+  n_tty_read     /sbin/getty 38400 tty5
2233     1  2233 TS       -   0  19   0  0.0 Ss+  n_tty_read     /sbin/getty 38400 tty6
2236  2211  2236 TS       -   0  19   0  0.0 S    inet_csk_accep /usr/sbin/apache2 -k start
2237  2211  2237 TS       -   0  19   0  0.0 S    inet_csk_accep /usr/sbin/apache2 -k start
2238  2211  2238 TS       -   0  19   0  0.0 S    inet_csk_accep /usr/sbin/apache2 -k start
2239  2211  2239 TS       -   0  19   0  0.0 S    inet_csk_accep /usr/sbin/apache2 -k start
2240  2211  2240 TS       -   0  19   0  0.0 S    inet_csk_accep /usr/sbin/apache2 -k start
2276  2163  2276 TS       -   0  19   0  0.0 Ss   wait           -bash
2280  2276  2280 TS       -   0  19   0  0.1 S+   poll_schedule_ top
2347     2  2347 TS       -   0  19   0  0.0 S    bdi_writeback_ [flush-8:0]
2414  2206  2414 FF      50   -  90   0  112 R    -              /bin/sh ./chewer
2415  2414  2415 FF      50   -  90   0  0.0 R    -              /bin/sh ./chewer


5.3.3)时间片调度(RR)

用时间片调度来执行chewer程序,则不会出现死机的情况.因为它在运行一段时间后,会根据时间片释放自己,这样就会fork出sleep进程,最后kill掉自己(chewer).

依然用chrt程序,-r表示用实时时间片调度,级别依然是50
chrt -r 50 ./chewer &

用ps命令查看有sleep 50的进程,同时chewer的调度状态CLS为RR
ps -eo pid,ppid,tid,class,rtprio,ni,pri,psr,pcpu,stat,wchan:14,command
  PID  PPID   TID CLS RTPRIO  NI PRI PSR %CPU STAT WCHAN          COMMAND
    1     0     1 TS       -   0  19   0  0.0 Ss   poll_schedule_ init [2]  
    2     0     2 TS       -   0  19   0  0.0 S    kthreadd       [kthreadd]
    3     2     3 FF      99   - 139   0  0.0 S    migration_thre [migration/0]
    4     2     4 TS       -   0  19   0  0.0 S    ksoftirqd      [ksoftirqd/0]
    5     2     5 TS       -   0  19   0  0.0 S    worker_thread  [events/0]
    6     2     6 TS       -   0  19   0  0.0 S    worker_thread  [khelper]
   11     2    11 TS       -   0  19   0  0.0 S    async_manager_ [async/mgr]
   58     2    58 TS       -   0  19   0  0.0 S    bdi_sync_super [sync_supers]
   60     2    60 TS       -   0  19   0  0.0 S    bdi_forker_tas [bdi-default]
   62     2    62 TS       -   0  19   0  0.0 S    worker_thread  [kblockd/0]
   64     2    64 TS       -   0  19   0  0.0 S    worker_thread  [kacpid]
   65     2    65 TS       -   0  19   0  0.0 S    worker_thread  [kacpi_notify]
   66     2    66 TS       -   0  19   0  0.0 S    worker_thread  [kacpi_hotplug]
  118     2   118 TS       -   0  19   0  0.0 S    serio_thread   [kseriod]
  168     2   168 TS       -   0  19   0  0.0 S    kswapd         [kswapd0]
  169     2   169 TS       -   0  19   0  0.0 S    worker_thread  [aio/0]
  170     2   170 TS       -   0  19   0  0.0 S    worker_thread  [crypto/0]
  552     2   552 TS       -   0  19   0  0.0 S    scsi_error_han [scsi_eh_0]
  812     2   812 TS       -   0  19   0  0.0 S    kjournald      [kjournald]
  902     1   902 TS       -  -4  23   0  0.0 S<s  poll_schedule_ udevd --daemon
1035     2  1035 TS       -   0  19   0  0.0 S    worker_thread  [kpsmoused]
1551     2  1551 TS       -   0  19   0  0.0 S    worker_thread  [kstriped]
1562     2  1562 TS       -   0  19   0  0.0 S    worker_thread  [ksnapd]
1588     2  1588 TS       -   0  19   0  0.0 S    kjournald      [kjournald]
1589     2  1589 TS       -   0  19   0  0.0 S    kjournald      [kjournald]
1659     1  1659 TS       -   0  19   0  0.0 Ss   poll_schedule_ dhclient3 -pf /var/run/dhclient.eth0.pid -lf /var/lib/dhcp3/dhclie
1675     1  1675 TS       -   0  19   0  0.0 Ss   poll_schedule_ /sbin/portmap
1839     1  1839 TS       -   0  19   0  0.0 Sl   poll_schedule_ /usr/sbin/rsyslogd -c3
1852     1  1852 TS       -   0  19   0  0.0 Ss   poll_schedule_ /usr/sbin/acpid
2127     1  2127 TS       -   0  19   0  0.0 Ss   poll_schedule_ /usr/sbin/exim4 -bd -q30m
2139     1  2139 TS       -   0  19   0  0.0 Ss   poll_schedule_ /usr/sbin/inetd
2158     1  2158 TS       -   0  19   0  0.0 Ss   poll_schedule_ /usr/sbin/sshd
2162     1  2162 TS       -   0  19   0  0.0 Ss   poll_schedule_ /sbin/rpc.statd
2163  2158  2163 TS       -   0  19   0  0.0 Ss   poll_schedule_ sshd: root@pts/0,pts/1
2172     1  2172 TS       -   0  19   0  0.0 Ss   hrtimer_nanosl /usr/sbin/atd
2192     1  2192 TS       -   0  19   0  0.0 Ss   hrtimer_nanosl /usr/sbin/cron
2206  2163  2206 TS       -   0  19   0  0.0 Ss   wait           -bash
2211     1  2211 TS       -   0  19   0  0.0 Ss   poll_schedule_ /usr/sbin/apache2 -k start
2228     1  2228 TS       -   0  19   0  0.0 Ss+  n_tty_read     /sbin/getty 38400 tty1
2229     1  2229 TS       -   0  19   0  0.0 Ss+  n_tty_read     /sbin/getty 38400 tty2
2230     1  2230 TS       -   0  19   0  0.0 Ss+  n_tty_read     /sbin/getty 38400 tty3
2231     1  2231 TS       -   0  19   0  0.0 Ss+  n_tty_read     /sbin/getty 38400 tty4
2232     1  2232 TS       -   0  19   0  0.0 Ss+  n_tty_read     /sbin/getty 38400 tty5
2233     1  2233 TS       -   0  19   0  0.0 Ss+  n_tty_read     /sbin/getty 38400 tty6
2236  2211  2236 TS       -   0  19   0  0.0 S    inet_csk_accep /usr/sbin/apache2 -k start
2237  2211  2237 TS       -   0  19   0  0.0 S    inet_csk_accep /usr/sbin/apache2 -k start
2238  2211  2238 TS       -   0  19   0  0.0 S    inet_csk_accep /usr/sbin/apache2 -k start
2239  2211  2239 TS       -   0  19   0  0.0 S    inet_csk_accep /usr/sbin/apache2 -k start
2240  2211  2240 TS       -   0  19   0  0.0 S    inet_csk_accep /usr/sbin/apache2 -k start
2276  2163  2276 TS       -   0  19   0  0.0 Ss   wait           -bash
2280  2276  2280 TS       -   0  19   0  0.1 S+   poll_schedule_ top
2434     2  2434 TS       -   0  19   0  0.0 S    bdi_writeback_ [flush-8:0]
2456  2206  2456 RR      50   -  90   0  141 R    -              /bin/sh ./chewer
2457  2456  2457 RR      50   -  90   0  0.0 S    wait           /bin/sh ./chewer
2458  2457  2458 RR      50   -  90   0  0.0 S    hrtimer_nanosl sleep 50
2459  2206  2459 TS       -   0  19   0  0.0 R+   -              ps -eo pid,ppid,tid,class,rtprio,ni,pri,psr,pcpu,stat,wc


注:
实时时间片调度进程的时间片与普通进程的时间片不一样,实时进程的时间片法,如果该进程被另一个更高优先级的进程抢占,
在高优先级执先完后,允许该进程用完剩余的时间片,如果普通进程则它的时间片将会缩短.



5.3.4)批处理调度(BATCH)

这种调度算法不是实时调度策略,这种调度策略和实时调度策略相反,因为只会在没有其他进程占用CPU时间时,它才会运行.
但与nice值设成最大不同,因为即便是优先权最低还是有可能轮到它.

下面指定批处理调度来运行chewer
chrt -b 0 ./chewer &
[1] 2508

可以看到chewer进程的CLS一列为B,它的实时优先级只能是0.
ps -eo pid,ppid,tid,class,rtprio,ni,pri,psr,pcpu,stat,wchan:30,command
  PID  PPID   TID CLS RTPRIO  NI PRI PSR %CPU STAT WCHAN                          COMMAND
    1     0     1 TS       -   0  19   0  0.0 Ss   poll_schedule_timeout          init [2]  
    2     0     2 TS       -   0  19   0  0.0 S    kthreadd                       [kthreadd]
    3     2     3 FF      99   - 139   0  0.0 S    migration_thread               [migration/0]
    4     2     4 TS       -   0  19   0  0.0 S    ksoftirqd                      [ksoftirqd/0]
    5     2     5 TS       -   0  19   0  0.0 S    worker_thread                  [events/0]
    6     2     6 TS       -   0  19   0  0.0 S    worker_thread                  [khelper]
   11     2    11 TS       -   0  19   0  0.0 S    async_manager_thread           [async/mgr]
   58     2    58 TS       -   0  19   0  0.0 S    bdi_sync_supers                [sync_supers]
   60     2    60 TS       -   0  19   0  0.0 S    bdi_forker_task                [bdi-default]
   62     2    62 TS       -   0  19   0  0.0 S    worker_thread                  [kblockd/0]
   64     2    64 TS       -   0  19   0  0.0 S    worker_thread                  [kacpid]
   65     2    65 TS       -   0  19   0  0.0 S    worker_thread                  [kacpi_notify]
   66     2    66 TS       -   0  19   0  0.0 S    worker_thread                  [kacpi_hotplug]
  118     2   118 TS       -   0  19   0  0.0 S    serio_thread                   [kseriod]
  168     2   168 TS       -   0  19   0  0.0 S    kswapd                         [kswapd0]
  169     2   169 TS       -   0  19   0  0.0 S    worker_thread                  [aio/0]
  170     2   170 TS       -   0  19   0  0.0 S    worker_thread                  [crypto/0]
  552     2   552 TS       -   0  19   0  0.0 S    scsi_error_handler             [scsi_eh_0]
  812     2   812 TS       -   0  19   0  0.0 S    kjournald                      [kjournald]
  902     1   902 TS       -  -4  23   0  0.0 S<s  poll_schedule_timeout          udevd --daemon
1035     2  1035 TS       -   0  19   0  0.0 S    worker_thread                  [kpsmoused]
1551     2  1551 TS       -   0  19   0  0.0 S    worker_thread                  [kstriped]
1562     2  1562 TS       -   0  19   0  0.0 S    worker_thread                  [ksnapd]
1588     2  1588 TS       -   0  19   0  0.0 S    kjournald                      [kjournald]
1589     2  1589 TS       -   0  19   0  0.0 S    kjournald                      [kjournald]
1659     1  1659 TS       -   0  19   0  0.0 Ss   poll_schedule_timeout          dhclient3 -pf /var/run/dhclient.eth0.pid -lf /var/
1675     1  1675 TS       -   0  19   0  0.0 Ss   poll_schedule_timeout          /sbin/portmap
1839     1  1839 TS       -   0  19   0  0.0 Sl   poll_schedule_timeout          /usr/sbin/rsyslogd -c3
1852     1  1852 TS       -   0  19   0  0.0 Ss   poll_schedule_timeout          /usr/sbin/acpid
2127     1  2127 TS       -   0  19   0  0.0 Ss   poll_schedule_timeout          /usr/sbin/exim4 -bd -q30m
2139     1  2139 TS       -   0  19   0  0.0 Ss   poll_schedule_timeout          /usr/sbin/inetd
2158     1  2158 TS       -   0  19   0  0.0 Ss   poll_schedule_timeout          /usr/sbin/sshd
2162     1  2162 TS       -   0  19   0  0.0 Ss   poll_schedule_timeout          /sbin/rpc.statd
2163  2158  2163 TS       -   0  19   0  0.0 Ss   poll_schedule_timeout          sshd: root@pts/0,pts/1
2172     1  2172 TS       -   0  19   0  0.0 Ss   hrtimer_nanosleep              /usr/sbin/atd
2192     1  2192 TS       -   0  19   0  0.0 Ss   hrtimer_nanosleep              /usr/sbin/cron
2206  2163  2206 TS       -   0  19   0  0.0 Ss   wait                           -bash
2211     1  2211 TS       -   0  19   0  0.0 Ss   poll_schedule_timeout          /usr/sbin/apache2 -k start
2228     1  2228 TS       -   0  19   0  0.0 Ss+  n_tty_read                     /sbin/getty 38400 tty1
2229     1  2229 TS       -   0  19   0  0.0 Ss+  n_tty_read                     /sbin/getty 38400 tty2
2230     1  2230 TS       -   0  19   0  0.0 Ss+  n_tty_read                     /sbin/getty 38400 tty3
2231     1  2231 TS       -   0  19   0  0.0 Ss+  n_tty_read                     /sbin/getty 38400 tty4
2232     1  2232 TS       -   0  19   0  0.0 Ss+  n_tty_read                     /sbin/getty 38400 tty5
2233     1  2233 TS       -   0  19   0  0.0 Ss+  n_tty_read                     /sbin/getty 38400 tty6
2236  2211  2236 TS       -   0  19   0  0.0 S    inet_csk_accept                /usr/sbin/apache2 -k start
2237  2211  2237 TS       -   0  19   0  0.0 S    inet_csk_accept                /usr/sbin/apache2 -k start
2238  2211  2238 TS       -   0  19   0  0.0 S    inet_csk_accept                /usr/sbin/apache2 -k start
2239  2211  2239 TS       -   0  19   0  0.0 S    inet_csk_accept                /usr/sbin/apache2 -k start
2240  2211  2240 TS       -   0  19   0  0.0 S    inet_csk_accept                /usr/sbin/apache2 -k start
2276  2163  2276 TS       -   0  19   0  0.0 Ss   wait                           -bash
2280  2276  2280 TS       -   0  19   0  0.1 S+   poll_schedule_timeout          top
2491     2  2491 TS       -   0  19   0  0.0 S    bdi_writeback_task             [flush-8:0]
2508  2206  2508 B        0   -  19   0 85.6 R    -                              /bin/sh ./chewer
2509  2508  2509 B        0   -  19   0  0.0 S    wait                           /bin/sh ./chewer
2510  2509  2510 B        0   -  19   0  0.0 S    hrtimer_nanosleep              sleep 50

论坛徽章:
3
天秤座
日期:2013-12-27 13:44:58射手座
日期:2014-05-22 16:52:43天蝎座
日期:2014-08-13 16:03:21
36 [报告]
发表于 2011-01-23 14:08 |只看该作者
本帖最后由 compare2000 于 2014-06-05 15:16 编辑

6)chrt命令

chrt命令的用法:
可以指定进程的调度方法
6.1)--fifo or -f 表示先入先出策略
例如:
chrt --fifo 50 ./chewer &

6.2)--rr or -r 表示时间片策略
例如:
chrt --rr 50 ./chewer &

6.3)--batch or -b 表示批处理或空闲的策略
例如:
chrt --batch 0 ./chewer &

6.4)--other or -o 表示普通的分时进程
chrt --other 0 ./chewer &

--max or -m 可以打印出chrt分配优先级的范围
chrt --max

6.5)--pid or -p 可以打印出进程的调度策略及优先级

chrt  -p 2537
pid 2537's current scheduling policy: SCHED_RR
pid 2537's current scheduling priority: 50


6.6)用chrt命令测试优先级的抢占

根据上面的论述,高的优先级进程抢占低的优先级的进程,之所以用FIFO的策略,优先级别为50,会造成死机,这个进程的策略是最高的.
而又没有进程的优先级超过它,它自己又不会放弃或阻塞,所以会死机

那我们用更高的优先级来KILL它,可以吗?
答案是可以的.
还是那个程序.首先用时间片策略调度程序,优先级为50
chrt -r 50 ./chewer &

再用chrt指定它为fifo的策略,优先级为60,2563为它的进程号
chrt -f -p 60 2563

我们用ps查询sleep的PID为2565
ps -eo pid,ppid,tid,class,rtprio,ni,pri,psr,pcpu,stat,wchan:14,command
2565  2564  2565 RR      50   -  90   0  0.0 R    -              sleep 50

再用chrt指定sleep的优先级为70
chrt -f -p 70 2565

这时程序在50秒后,就退出了.因为sleep是最高的,它kill掉了chewer





7)调度策略的总结

在进程调度中有四种方法,也就是四种类型的宏

普通的分时策略    TS  SCHED_OTHER
实时FIFO的策略    FF  SCHED_FIFO
实时时间片策略    RR  SCHED_RR
普通批处理策略   B  SCHED_BATCH

在三种状态可以在ps 命令的CLS列查出来
例如:
ps -eo pid,ppid,tid,class,rtprio,ni,pri,psr,pcpu,stat,wchan:14,command

class代表CLS列
trprio代表实时优先级
ni代表nice,(在实时进程中无意思,所以为-)
pri代表绝对优先级,也就是有效优先级,在实时进程来说,绝对优先级是大于40
例如:指定fifo的优先级为1,绝对优先级就是41
chrt -f 1 ps -C ps -o pri,ni,rtprio,comm
PRI  NI RTPRIO COMMAND
41   -      1 ps
wchan:14代表操作系统调用,14代表宽度为14个字符

基于Linux的实时系统
越来越多的开发者在基于 Linux 系统构造嵌入式实时应用,他们迫切地需要一份基于 Linux 系统构造嵌入式实时系统的指南性的文章。考虑到这种需求,本文在介绍了几种基本的实时进程调度算法的基础上,研究了普通的 Linux 操作系统的进程调度,并十分全面地调查了各种实时 Linux 系统为了支持实时特性对普通 Linux 系统所做的改进。文章分析了将 Linux 操作系统应用于实时领域中时所出现的一些问题,并总结了各种实时 Linux 是如何解决这些问题的,最后对于如何将这些已有的研究成果应用与实际的研究和开发工作中作了很好的建议。

第一部分: 实时调度算法介绍

对于什么是实时系统,POSIX 1003.b 作了这样的定义:指系统能够在限定的响应时间内提供所需水平的服务。而一个由 Donald Gillies 提出的更加为大家接受的定义是:一个实时系统是指计算的正确性不仅取决于程序的逻辑正确性,也取决于结果产生的时间,如果系统的时间约束条件得不到满足,将会发生系统出错。

实时系统根据其对于实时性要求的不同,可以分为软实时和硬实时两种类型。硬实时系统指系统要有确保的最坏情况下的服务时间,即对于事件的响应时间的截止期限是无论如何都必须得到满足。比如航天中的宇宙飞船的控制等就是现实中这样的系统。其他的所有有实时特性的系统都可以称之为软实时系统。如果明确地来说,软实时系统就是那些从统计的角度来说,一个任务(在下面的论述中,我们将对任务和进程不作区分)能够得到有确保的处理时间,到达系统的事件也能够在截止期限到来之前得到处理,但违反截止期限并不会带来致命的错误,像实时多媒体系统就是一种软实时系统。

一个计算机系统为了提供对于实时性的支持,它的操作系统必须对于 CPU 和其他资源进行有效的调度和管理。在多任务实时系统中,资源的调度和管理更加复杂。本文下面将先从分类的角度对各种实时任务调度算法进行讨论,然后研究普通的 Linux 操作系统的进程调度以及各种实时 Linux 系统为了支持实时特性对普通 Linux 系统所做的改进。最后分析了将 Linux 操作系统应用于实时领域中时所出现的一些问题,并总结了各种实时 Linux 是如何解决这些问题的。

1. 实时 CPU 调度算法分类

各种实时操作系统的实时调度算法可以分为如下三种类别 [Wang99][Gopalan01]:基于优先级的调度算法(Priority-driven scheduling-PD)、基于 CPU 使用比例的共享式的调度算法(Share-driven scheduling-SD)、以及基于时间的进程调度算法(Time-driven scheduling-TD),下面对这三种调度算法逐一进行介绍。

1.1. 基于优先级的调度算法

基于优先级的调度算法给每个进程分配一个优先级,在每次进程调度时,调度器总是调度那个具有最高优先级的任务来执行。根据不同的优先级分配方法,基于优先级的调度算法可以分为如下两种类型 [Krishna01][Wang99]:

静态优先级调度算法:

这种调度算法给那些系统中得到运行的所有进程都静态地分配一个优先级。静态优先级的分配可以根据应用的属性来进行,比如任务的周期,用户优先级,或者其它的预先确定的策略。RM(Rate-Monotonic)调度算法是一种典型的静态优先级调度算法,它根据任务的执行周期的长短来决定调度优先级,那些具有小的执行周期的任务具有较高的优先级。

动态优先级调度算法:

这种调度算法根据任务的资源需求来动态地分配任务的优先级,其目的就是在资源分配和调度时有更大的灵活性。非实时系统中就有很多这种调度算法,比如短作业优先的调度算法。在实时调度算法中,EDF 算法是使用最多的一种动态优先级调度算法,该算法给就绪队列中的各个任务根据它们的截止期限(Deadline)来分配优先级,具有最近的截止期限的任务具有最高的优先级。

1.2. 基于比例共享调度算法

虽然基于优先级的调度算法简单而有效,但这种调度算法提供的是一种硬实时的调度,在很多情况下并不适合使用这种调度算法:比如象实时多媒体会议系统这样的软实时应用。对于这种软实时应用,使用一种比例共享式的资源调度算法(SD 算法)更为适合。

比例共享调度算法指基于 CPU 使用比例的共享式的调度算法,其基本思想就是按照一定的权重(比例)对一组需要调度的任务进行调度,让它们的执行时间与它们的权重完全成正比。

我们可以通过两种方法来实现比例共享调度算法 [Nieh01]:第一种方法是调节各个就绪进程出现在调度队列队首的频率,并调度队首的进程执行;第二种做法就是逐次调度就绪队列中的各个进程投入运行,但根据分配的权重调节分配个每个进程的运行时间片。


一、Software Architecture篇
     这个领域没有什么"畅销书",可能读者中本来就是开发设计人员与项目经理占了多数,真正定位为架构师而且做的也是架构师工作的不多吧,你懂的尽是偏僻的人生。

《Software Architecture in Practice,2nd Edition--软件构架实践(第2版)》

   第一版是第九届JOLT作品,一本被引用很多的架构书。

《Documenting Software Architectures --软件构架编档》

   第13届JOLT大奖作品,捕获架构的过程,徐昊推荐。

《Applied Software Architecture --实用软件体系结构》

   另一本被引用很多的架构之书。






二、UML 篇
  UML、4+1视图始终是架构师界最通用的东西,寻找一种向世界妥协的方式。

1. 《UML Distilled 3rd》

      没什么特别想推荐的UML工具书,选本最薄的吧。

2.《The Elements of UML 2.0 Style》

     胜在没有同类书。

3.《UML和模式应用(第3版)--Applying UML and Patterns 3rd》
   UML+RUP作的OOAD过程。




三、特定领域篇
    开发人员有GOF23 Pattern,架构师同样也有架构师的Pattern。不同领域的架构师需要不同的知识。
1. 公共领域
《Domain-Specific Application Frameworks --特定领域应用框架:行业的框架体验》
  推荐,介绍了30个特定领域特定框架的设计。

《Head First Design Patterns》
  最好的GOF23经典设计模式阐释,适合被[GAMMA95]折磨的架构师拿来复习,中文版即将发行。

  



2. Java EE领域
  《Patterns of Enterprise Application Architecture --企业应用架构模式》
      Martin Fowler老书,企业应用各层上的模式。   
  
  《Effective Enterprise Java--中文版》   
      Neward, Ted作品,作者学贯东西(.Net与Java),像写Blog一样,每一页里面都有大量的信息。

      可惜两本都比较旧了,没有新版。

  




3. EAI/SOA领域
《Enterprise Integration Patterns --企业集成模式:设计、构建及部署消息传递解决方案》


  



4. 网络与后台服务编程领域
《Pattern-Oriented Software Architecture, Volume 2 --面向模式的软件体系结构 卷2:用于并发和网络化对象的模式》

《Pattern-Oriented Software Architecture, Volume 3 --面向模式的软件体系结构卷3:资源管理模式》

    著名的POSA2与POSA3。
  


四、闲书篇
《Code Complete 2 --代码大全2》
   一本你教育小弟时的代言人。

《The Pragmatic Programmer --程序员修炼之道:从小工到专家》
   一本你启发小弟的代言人。

《The Art of Unix Programming --UNIX编程艺术》






五、高效读书心得
   刚好Head First系列开头都有一段教人如何读书的话,再加工整理如下:

1.尽量阅读中文版
  虽然有人英文很强,有的翻译很差,但AnyWay 中文阅读与理解的时间,略读与快速定位的速度还是要快一些。
  
2.即时批注、总结笔记与交流
  虽然爱书,但发现最有效的读书方式还是不断的制造脂批本,读书时在重要的文字下划线,把自己的心得写在页旁。
  在明天复习一次批注,最好可以有空重新整理笔记,或者拿来与人讨论。

3.大量思考或重复记忆
  看书最郁闷的事情就是看完之后脑袋空空了。技术书还好点,虽然看的时候可能很辛苦,但就像学会了骑单车,之后再骑的时候总是会的;而偏设计与管理的书,最容易的事情就是看的时候很快,看完没什么留下到实践中。
  所以,我们不能以看小说的速度来看设计书,要寻找思考的机会,思考是最好的记忆。
  又或者,大量的重复记忆,重复多遍直到无意识的记忆。
  
4.人体工学
  那些见缝插针的时间与地点不是看这个书单的好地方。
  环境不要有电视,音乐等强输入源,而微风阳光鸟语等弱输入源则有助活跃大脑。
  看书时大量的喝水。
  如果发现自己的大脑已经疲累,已经在浮光掠影的翻看,就要休息。
  留给大脑消化的时间,看完书不要接着看其他有难度的书或事情。

比例共享调度算法可以分为以下几个类别:轮转法、公平共享、公平队列、彩票调度法(Lottery)等。

比例共享调度算法的一个问题就是它没有定义任何优先级的概念;所有的任务都根据它们申请的比例共享 CPU 资源,当系统处于过载状态时,所有的任务的执行都会按比例地变慢。所以为了保证系统中实时进程能够获得一定的 CPU 处理时间,一般采用一种动态调节进程权重的方法。

1.3. 基于时间的进程调度算法

对于那些具有稳定、已知输入的简单系统,可以使用时间驱动(Time-driven:TD)的调度算法,它能够为数据处理提供很好的预测性。这种调度算法本质上是一种设计时就确定下来的离线的静态调度方法。在系统的设计阶段,在明确系统中所有的处理情况下,对于各个任务的开始、切换、以及结束时间等就事先做出明确的安排和设计。这种调度算法适合于那些很小的嵌入式系统、自控系统、传感器等应用环境。

这种调度算法的优点是任务的执行有很好的可预测性,但最大的缺点是缺乏灵活性,并且会出现有任务需要被执行而 CPU 却保持空闲的情况。

2. 通用 Linux 系统中的 CPU 调度

通用 Linux 系统支持实时和非实时两种进程,实时进程相对于普通进程具有绝对的优先级。对应地,实时进程采用 SCHED_FIFO 或者 SCHED_RR 调度策略,普通的进程采用 SCHED_OTHER 调度策略。

在调度算法的实现上,Linux 中的每个任务有四个与调度相关的参数,它们是 rt_priority、policy、priority(nice)、counter。调度程序根据这四个参数进行进程调度。

在 SCHED_OTHER 调度策略中,调度器总是选择那个 priority+counter 值最大的进程来调度执行。从逻辑上分析,SCHED_OTHER 调度策略存在着调度周期(epoch),在每一个调度周期中,一个进程的 priority 和 counter 值的大小影响了当前时刻应该调度哪一个进程来执行,其中 priority 是一个固定不变的值,在进程创建时就已经确定,它代表了该进程的优先级,也代表这该进程在每一个调度周期中能够得到的时间片的多少;counter是一个动态变化的值,它反映了一个进程在当前的调度周期中还剩下的时间片。在每一个调度周期的开始,priority 的值被赋给 counter,然后每次该进程被调度执行时,counter 值都减少。当 counter 值为零时,该进程用完自己在本调度周期中的时间片,不再参与本调度周期的进程调度。当所有进程的时间片都用完时,一个调度周期结束,然后周而复始。另外可以看出 Linux 系统中的调度周期不是静态的,它是一个动态变化的量,比如处于可运行状态的进程的多少和它们 priority 值都可以影响一个 epoch 的长短。值得注意的一点是,在 2.4 以上的内核中,priority 被 nice 所取代,但二者作用类似。

可见 SCHED_OTHER 调度策略本质上是一种比例共享的调度策略,它的这种设计方法能够保证进程调度时的公平性--一个低优先级的进程在每一个 epoch 中也会得到自己应得的那些CPU执行时间,另外它也提供了不同进程的优先级区分,具有高 priority 值的进程能够获得更多的执行时间。

对于实时进程来说,它们使用的是基于实时优先级 rt_priority 的优先级调度策略,但根据不同的调度策略,同一实时优先级的进程之间的调度方法有所不同:

SCHED_FIFO:不同的进程根据静态优先级进行排队,然后在同一优先级的队列中,谁先准备好运行就先调度谁,并且正在运行的进程不会被终止直到以下情况发生:1.被有更高优先级的进程所强占 CPU;2.自己因为资源请求而阻塞;3.自己主动放弃 CPU(调用 sched_yield);
SCHED_RR:这种调度策略跟上面的 SCHED_FIFO 一模一样,除了它给每个进程分配一个时间片,时间片到了正在执行的进程就放弃执行;时间片的长度可以通过 sched_rr_get_interval 调用得到;

由于 Linux 系统本身是一个面向桌面的系统,所以将它应用于实时应用中时存在如下的一些问题:
Linux 系统中的调度单位为10ms,所以它不能够提供精确的定时;
当一个进程调用系统调用进入内核态运行时,它是不可被抢占的;
Linux 内核实现中使用了大量的封中断操作会造成中断的丢失;
由于使用虚拟内存技术,当发生页出错时,需要从硬盘中读取交换数据,但硬盘读写由于存储位置的随机性会导致随机的读写时间,这在某些情况下会影响一些实时任务的截止期限;
虽然 Linux 进程调度也支持实时优先级,但缺乏有效的实时任务的调度机制和调度算法;它的网络子系统的协议处理和其它设备的中断处理都没有与它对应的进程的调度关联起来,并且它们自身也没有明确的调度机制;

3. 各种实时 Linux 系统

3.1. RT- Linux 和 RTAI

RT- Linux 是新墨西哥科技大学(New Mexico Institute of Technology)的研究成果[RT Linux Web][Barabanov97]。它的基本思想是,为了在 Linux 系统中提供对于硬实时的支持,它实现了一个微内核的小的实时操作系统(我们也称之为 RT- Linux 的实时子系统),而将普通 Linux 系统作为一个该操作系统中的一个低优先级的任务  

论坛徽章:
3
天秤座
日期:2013-12-27 13:44:58射手座
日期:2014-05-22 16:52:43天蝎座
日期:2014-08-13 16:03:21
37 [报告]
发表于 2011-01-23 14:09 |只看该作者
本帖最后由 compare2000 于 2014-09-18 11:43 编辑

职场最受益的9个好习惯
细节决定成败的职场命题,最集中的表现就是职场习惯。无怪乎,人们常说,播种行为,收获习惯;播种习惯,收获性格;播种性格,收获命运。一个职场好习惯,拥有让你成长得更快的强大力量。

1.把自己的时间调快五分钟

关键词:守时

把手表、手机、电脑、挂钟……你身边一切的计时器的指针往前轻轻拨动五分钟。于是,你发现,早上上班不再顶着一头乱发气急败坏地冲向打卡机,再也不会出现拉开会议室的门发现领导已经端坐在里面等你的尴尬,去拜访客户再也不用一边赶路一边整理领带或是补妆……一天依然是24小时,工作量依然,但你会发现因为这五分钟,自己的工作和心境却从容、自信了很多,表现更加出色。

达人分享:Ivy,外企文员——总是提前两小时
我的工作特点是前紧后松,习惯工作任务提前两小时完成。在这两个小时里,给自己留下了从容地检查、补救、完美的余地,也给领导留下了准时、敬业的好印象。

2. 使用To-do List

关键词:高效

职场中“忙”声一片,再看看众多职场人的办公桌、电脑桌面,也是堆满文件、报表,一片繁忙景象。多头绪的工作,临时任务,总让人感到疲于奔命,却又收效甚微。其实,你真正需要的不是向领导抱怨工作量太大,也不是挤出休息时间忙工作,你需要的只是头一天或当天花五分钟,写一张To-do List,按轻重缓急列出工作任务,设置好提醒,就能让你的工作一环接一环,有条不紊。时间管理专家Mark Forster还给出了改进To-do List的几条建议,例如:将To-do List写在纸上而不是放在电脑上;只写下那些你真正有时间去完成的工作,而且预留应付各种意外情况的时间;不要将新想法直接写到To-do List中,单独列个“日后可能做”的列表;保持每个项目都是可具体执行的行动,最好不要写“完成XX项目的报告”,而是写“完成XX项目报告的提纲”等等。

达人分享:Ava,国企人事主管——习惯说“no”
一旦确定了当下工作重点,我就有一个说“no”的习惯,以尽量避免被其他事情所牵绊,这是我从风靡全球的高效能人士七大习惯中学到的,当然这是在不损害团队利益的前提下进行的。从当新人时习惯说“yes”到现在学会说“no”,我认为先有了自己的高效,才能去谈团队的高效。

3.早中晚静思十分钟

关键词:成长

古人说,一日三省吾身。这一人生大智慧在职场中同样受用。趁清晨赖床的时候,想想昨天的失误、今天的要事;午餐后,找个安静的角落闭目养神,想想今天工作中碰到的难题和难缠的客户,检查一下自己这方的问题出在哪里;晚上睡觉前,提前几分钟关掉电视,总结总结自己今天的收获,问问自己是不是还可以做得更好。每天给自己一点安静反省的时间,就是在一点点修炼自己的品格,坚持下来就成了你职场中的一大步。注意,这几分钟一定要用来反问和审视自己,而不是抱怨。

达人分享:彭sir,销售经理——睡前工作日志
工作十年,我从前辈那里学了一个雷打不动的习惯。每晚睡前,我都会拿出日记本,写下当天的工作心得,有收获,也有检讨。虽然现在博客普及,但我还是偏爱手写,这样可以让自己的思考更谨慎、更深入,对教训也铭记得更深刻。

4. 放一本书在包里

关键词:学习

李开复是利用“时间碎片”的高手,向他学习会让你受益匪浅。每天,我们都有不少时间用在等待上,与其读报纸上的家长里短,不如带一本书上班、等地铁、等女朋友……把这些无所事事的时间碎片利用来学习、充电,让自己的思想和知识时时更新,又怎会有时间来抱怨没空闲去培训呢?

达人分享: Daniel Wong,公关公司文案——向自己讨厌的人学习
我渐渐发现,讨厌或不喜欢是一种很复杂的情绪,很多时候其实是在嫉妒,又或是恐惧,只是自己意识不到罢了。这样想之后,我也开始发现——原来,从讨厌的人身上更能对照出自己的不足,也更能激发自己去学习、去完善的斗志。我想,如此生动的课程恐怕是培训教室里学不来的。

5.幽默

关键词:乐观

面对穿着油漆工服、头发上沾满涂料的面试者,面试官问:“假设有个人不穿着正装就跑过来面试,然后我却录用了他,你会怎么评价?”这位面试者镇定而幽默地回答道:“那他的裤子一定很不错。”大笑的面试官最终录用了他。这是电影《当幸福来敲门》中的经典对白,主人公Chris历经磨难,却始终乐观以对,最终圆了自己的职业梦。

职场中,既然困境、不如意无法逃避,何不养成幽自己一默的好习惯?对沮丧、痛苦迟钝一些,常给自己开个玩笑,当笑容绽放,心境豁然开朗,坚持的勇气又重回胸中。

达人分享:乐天,媒体人——幻想法
每当工作受阻、让人抓狂的时候,我就会开一会小差,幻想一下当这项工作完成后我会如何去“狂欢”,有时干脆去订好餐厅,或边工作边下载好电影,这样的幻想总能激励我完成工作。要说没有职业倦怠那是瞎话,但后来我养成了一个习惯——经常用自己羡慕的那种职业状态、生活状态来刺激自己,比如眼馋高端品牌的广告,看看精英访谈的节目,相较那个远大而美好的梦想,现在也就不那么苦闷无聊了。

6.用 “我们”开头

关键词:共赢

总是以一副好战分子的姿态示人,想必也不会得到多少鲜花和笑脸。其实,职场不是角斗场,团队的共赢、企业的共赢、客户的共赢必定会比单打独斗创造出更大的价值。无论自己思考还是与人沟通,养成用“你”“你们”“我们”开头的习惯,多用“请”“谢谢”,你会发现自己更能理解他人,沟通、合作比以前顺畅得多,原因很简单:你如何对待他人,他人也将如何待你。同理之心、感恩之心必定会带来人际的良性循环。

达人分享:晓岚,人际关系培训讲师——沟通三段论
职场中,我们每天都在沟通。无论什么规模的沟通,我都喜欢用第一、第二、第三给自己的话做一个分段,在听完对方的话之后,我习惯简要地复述一遍。这样的沟通非常清晰和有效,表达了尊重,节约了双方的时间,也是一种共赢。

7.对不认识的同事点头微笑

关键词:礼仪

办公室里,走廊里,总会遇到一些陌生的面孔,可能是来拜访的客人,也可能是其他部门的同事,甚至有可能是上司的家属。当面对面,你是面无表情地飘过,还是点头微笑,几秒的时间里对方就会给你的修养,也给部门或公司的修养打出分数。那么,形成一个喜欢微笑的好习惯吧,温暖了他人,也会闪亮自己。

达人分享:小米,公务员——先人一步
上班到的早,帮领导和同事打打水、拖拖地;坐电梯,主动问问别人到哪层并帮助按下按钮;吃饭时,主动帮同桌添点茶水;出去玩,帮年纪大的同事拎拎包……在机关里,大家都夸我勤快、懂礼貌,领导出差也喜欢带着我。其实我自己真不是故意这么去做的,从我第一天上班,老爸就经常教育我:“懂礼貌、手脚勤快、有眼力见的孩子谁都喜欢”,日久天长就形成习惯啦。

8.睡觉前准备好第二天的上班装

关键词:职业化

早上又起晚了,可偏偏越是着急越出岔子,“呀,这个裙子配这双鞋好奇怪!哎,管不了了。”临出门了,“呀,手机、眼镜去哪里了?”好不容易进了办公室了,却惊出一身冷汗:“OMG!昨晚带回家做的文件忘带来了”……带着这生活上的一团乱,很难想象工作中能井井有条。何不在晚上睡觉前做好功课呢?精心搭配好第二天的职业装,把“行李”都装好,包括爱吃的零食,再以干练优雅的职业化形象准时出现在办公室。还有,试着让自己的上班包、办公桌面、抽屉、电脑始终井然有序,这样的好习惯表示了你对这份工作的在乎,更会让你在工作中保持沉稳、冷静。

达人分享:康康,招聘网站客服——公私分明的办公桌
女孩子总会放一些零食和化妆品在办公室,我也不例外。但我从来不会让这些东西出现在我的办公桌上,要么放在包里,要么放在抽屉里。在办公室电脑的桌面上,也绝不会出现和工作无关的东西,我不会把爱玩的QQ游戏的快捷方式放在桌面上,并且尽量避免在电脑里存储私人文件。这个习惯是从上司那里学来的。对自己来说,可以专注工作,心无旁骛;对同事和上司来说,我会给他们留下一个公私分明的职业化的好印象。

9.在办公室做伸展运动

关键词:健康

十个职场人中,八九个都会被手腕、腰、颈、背的毛病所困扰。其实,只要养成一些好习惯就会大大降低你的身体不适指数。早上到办公室后,先做几分钟伸展运动,这有助于加快一天的新陈代谢,避免久坐形成脂肪。工作中,每一到两个小时就站起来活动活动,以伸展为主。上下楼少坐电梯、爬爬楼梯,堵车厉害就干脆自行车或步行,节假日选择窝在家里?那就搬搬扛扛改换环境……其实锻炼身体的机会很多,只要不犯懒就行。

达人分享:艾莉,猎头——五个一
我们做猎头的,工作压力大,健康状况自然好不到哪里去。自认为我这五个一的习惯对自己的健康起了大作用,每天带一种当季水果到办公室;每两小时开窗透一次气;每天下午一杯茶;每天步行上下15楼一次;每周玩一次真人CS。

01-.tar格式解包:[*******]$ tar xvf FileName.tar打包:[*******]$ tar cvf FileName.tar DirName(注:tar是打包,不是压缩!)02-.gz格式解压1:[*******]$ gunzip FileName.gz解压2:[*******]$ gzip -d FileName.gz压 缩:[*******]$ gzip FileName03-.tar.gz格式解压:[*******]$ tar zxvf FileName.tar.gz压缩:[*******]$ tar zcvf FileName.tar.gz DirName04-.bz2格式解压1:[*******]$ bzip2 -d FileName.bz2解压2:[*******]$ bunzip2 FileName.bz2压 缩: [*******]$ bzip2 -z FileName05-.tar.bz2格式解压:[*******]$ tar jxvf FileName.tar.bz2压缩:[*******]$ tar jcvf FileName.tar.bz2 DirName06-.bz格式解压1:[*******]$ bzip2 -d FileName.bz解压2:[*******]$ bunzip2 FileName.bz07-.tar.bz格式解压:[*******]$ tar jxvf FileName.tar.bz08-.Z格式解压:[*******]$ uncompress FileName.Z压缩:[*******]$ compress FileName09-.tar.Z格式解压:[*******]$ tar Zxvf FileName.tar.Z压缩:[*******]$ tar Zcvf FileName.tar.Z DirName10-.tgz格式解压:[*******]$ tar zxvf FileName.tgz11-.tar.tgz格式解压:[*******]$ tar zxvf FileName.tar.tgz压缩:[*******]$ tar zcvf FileName.tar.tgz FileName12-.zip格式解压:[*******]$ unzip FileName.zip压缩:[*******]$ zip FileName.zip DirName13-.lha格式解压:[*******]$ lha -e FileName.lha压缩:[*******]$ lha -a FileName.lha FileName14-.rar格式解压:[*******]$ rar a FileName.rar压缩:[*******]$ rar e FileName.rar     rar请到:http://www.rarsoft.com/download.htm 下载!解压后请将rar_static拷贝到/usr/bin目录(其他由$PATH环境变量指定的目录也行):[*******]$ cp rar_static /usr/bin/rar

论坛徽章:
3
天秤座
日期:2013-12-27 13:44:58射手座
日期:2014-05-22 16:52:43天蝎座
日期:2014-08-13 16:03:21
38 [报告]
发表于 2011-01-23 14:25 |只看该作者
本帖最后由 compare2000 于 2014-07-25 10:11 编辑

如何管理项目的知识?
我们需要获取什么知识?
我们即将产生什么知识?
这些知识将会在
项目知识管理计划中定义
项目知识管理计划是一份文档,定义项目将如何管理自己的知
识,包括项目需要的知识以及项目即将产生的知识。
为什么要做
项目知识管理计划?
帮助识别为提升绩效、减少风险、克服挑战:
项目需要学习什么?
将采取怎样的行动计划?
同时,向管理层保证:
我们将学习以往的经验教训,
项目知识将被有效管理。
项目知识管理计划聚焦两件事情:
为成功交付,项目需要哪些知识?
我们将捕获并分享哪些项目经验?
项目知识管理计划在项目启动之初定义,并在每个阶段点刷新
通过Workshop方式制订项目知识管理计划:
识别项目中的关键知识
这些知识从哪里获取
我们采取哪些学习行动?
项目过程中如何管理知识?
项目知识经理
负责知识管理计划:
由项目经理指定
起草并管理知识管理计划
监控各项知识管理活动的开展
定期通报计划执行的状态
MAC的一些知识
一、桥MAC
每台设备出厂都会给设备分配一个网段的可用MAC。
TOR MAC是存在于NOR flash中,每台TOR有16个可用MAC,设备桥MAC最小,以0结尾
128 MAC是存在于框背板 e2prom中,是一组2(master)+2(slave)芯片,主要存储elabel(esn)、MAC;每个框有255个可用MAC,设备桥MAC最小,以00结尾。

二、系统MAC
单机系统MAC就是设备桥MAC
堆叠系统MAC根据竞争结果,以堆叠主桥MAC作为系统MAC。
128系统MAC可配置,指定某一个框的桥MAC为系统MAC,配置存储在主控板NVRAM中,由是否配置系统MAC标志和MAC组成。

三、系统MAC切换的几个规则:
1、立即切换:可以通过命令行设置,主备倒换后,系统MAC立即切换为新系统主MAC
2、不切换(切换时间=0):主备倒换后,仍然使用之前的系统MAC;128命令行设置系统MAC后,主备倒换后不切换,仍然以设置系统MAC为准。
3、切换时间(>0,1~60min):主备倒换后,在设置的切换时间内,原系统主成功注册,则系统MAC不切换;如果超过切换时间,原系统主仍然没有注册成功,则系统MAC切换为新系统主
4、TOR系统MAC默认切换,切换时间10min;128系统MAC默认不切换

四、端口MAC
管理网口MAC跟系统MAC是一致的。
物理端口、堆叠逻辑口、trunk的MAC选取规则是系统MAC+1。
vlanif MAC在可用MAC网段中按照一定规则选取。
有朋友经常会说“你真有境界!”“你都到这境界啦!”等等之类的话。而在程序员的职业生涯这条求道之路上,你可否想过自己正处于哪个境界呢?可否想过程序员的最高境界是怎样的一个高度呢?不妨根据自己的现状一起来找到自己的境界吧!

国学大师王国维先生认为古今成大事业、大学问者,必经过三种境界,第一种境界:“昨夜西风凋碧树。独上高楼,望尽天涯路”;第二种境界:“衣带渐宽终不悔,为伊消得人憔悴”,第三种境界:“众里寻他千百度,蓦然回首,那人却在灯火阑珊处”。一代宗师真是体察入微,寥寥数语,道尽了求道者的心路历程,将一个人由浅尝、迷茫到彻悟的过程尽数概括,可谓入木三分。

IT行业可谓现在的热门行业,程序员也是很多人羡慕的工作。薪水高,不用东跑西颠,敲敲键盘,看看屏幕,一切工作全都搞定,轻松而方便。果真如此吗?不尽然,实际上,程序员的职业生涯也是一个求道的过程,需要不断的提高和学习,IT行业知识更新之快,常让程序员们有随时掉队的危险,无一日不战战兢兢,不敢稍有懈怠。

程序员的职业生涯也可分为四个阶段,初级程序员(菜鸟)、高级程序员(熟练工)、系统程序员(高手)、软件大师(大师),其作品也经历四种境界:

&Oslash;  可以运行的程序

&Oslash;  健壮、高效的程序

&Oslash;  结构优美的程序

&Oslash;  思想深邃的程序

程序员的必经第一个阶段都是编写可以运行的程序。很多人的编程生涯是从“Hello World”开始,当第一次按照教科书上的步骤,将源文件编辑完后,编译、连接、运行,在屏幕上显示出“Hello World”时,心中的激动一点也不亚于阿里巴巴打开了宝库的大门。初级程序员的目标一般是让程序能运行起来,他们迷惑于库函数的众多,不知道该用哪一个,他们还要学习基本的语法,以使程序编译通过。初级程序员一般不会考虑设计模式、软件结构等问题。记得本人编写的第一个较大的程序是本人的本科毕业论文题目——一个计算机辅助实验系统,开发工具为Turbo C,在DOS下开发(那个时候Windows还不太流行,怎么样,年代够久远吧),整个软件大约7000行代码,在当时已经能干不少事,在DOS下也能显示不少花里胡哨的图形界面,支持中文,支持鼠标操作(那时候在DOS下需要自己处理鼠标事件中断),当时还颇受好评。可是今天再重新温习过去的作品,真有点惨不忍睹,整个软件毫无结构可言,一共分成两个源文件还是由于编译器不支持一个太大的源文件而被迫分开,整个系统就是源代码的简单堆砌。相信每个程序员都需要经历这个阶段,它是程序员职业生涯的开始,没有捷径可以跨越,只有不断的实践、学习和总结。

第二阶段的程序员已积累了不少的编程经验,语法和库函数不再是障碍,他们已不再满足于程序正确运行、功能实现无误。他们需要了解程序背后发生的事情,需要了解操作系统的原理和调度机制,内存管理,文件系统组织等;了解开发工具的细节,如C的函数调用机制,参数的传送机制、堆栈的建立过程等;了解C++的封装、继承和多态性背后的机制,虚函数实现机理等。他们不仅知道程序应该如何运行,还知道它为什么这样运行,能编写高效、鲁棒的程序。

第三阶段的程序员能构建结构优美的软件系统,软件系统结构的合理性、可扩展性、可维护性、可测试性是系统程序员考虑的重点,结构优美的软件系统同一栋完美的建筑群一样,每个部分各司其职,搭配合理。本人一直认为,一个好的软件系统应当具有美学特征,如简洁、和谐、层次感等,一个好的软件系统应当是简洁的,易于理解的;应当是和谐的,每个部分高内聚、低耦合,既分工又合作;应当是层次分明,易于维护和移植。所以,本人建议那些进行软件系统设计的程序员,当你设计完一个系统后,需要问问自己:"它美吗?",如果答案是否定的,那么我建议你需要重新考虑系统的设计,如果答案是肯定的,那么,恭喜你,你已经达到一个相当高的水平。

    最后一级也许是每个程序员梦想达到的顶峰,程序设计不再是简单的工具,而是大师们改变世界的魔杖,从C到C++,再到COM和COBRA,再到XML和WEB SERVICES,每次改变,不是软件语法和开发工具的升级,而是用软件构建现实世界模型的改变,是一种软件思想的革命,软件具有了灵魂和智能。如果没有理解这一点,认为C++只是更好的C,COM只是更好的C++的话,你就没有了解它们的精髓和思想性。



      “程序员之路漫漫兮,吾将上下而求索。”希望与所有的程序员共勉。

1.1        安装wrlinux6.0开发环境
获取wrlinux6.0开发环境安装包:wrlinux6.0.0.1-disk.tar.gz (下载地址:\\10.68.132.212\系统镜像\workspace_ubuntu12.04\wrlinux6.0_target_build ), 拷贝到ubuntu12.04 host主机环境下进行安装。参考命令如下:
$ tar zxf wrlinux6.0.0.1-disk.tar.gz
$ cd wrlinux6.0/disk1/
$ ./setup_linux  #启动安装进程,根据图形化安装界面信息进行安装

注意:建议安装过程使用当前用户权限进行,安装目录也选择当前用户权限下的目录。因为如果在root用户模式下安装,则安装文件权限是root,在后续创建及编译工程过程中,会出现一些“脚本无权限执行”或“库文件无法访问”等问题。

1.2        wrlinux6.0系统平台工程的配置及编译
    系统平台工程包含针对某种bsp类型的完备OS编译环境,以及多种应用子工程,如:linux kernel,qemu,libvirt等,由该工程输出kernel image, rootfs, sdk,rmp 包等操作系统基本组成元素。
1.2.1        配置编译系统平台工程
系统平台工程配置示例:
$ mkdir –p intel-x86-64_proj   #创建任意文件夹作为系统平台工程目录
$ cd intel-x86-64_proj
$ /home/suntao/WindRiver/wrlinux-6/wrlinux/configure \
--enable-board=intel-x86-64 \
--enable-kernel=standard+features/kvm/qemu-kvm-enable.scc \
--enable-jobs=4 --enable-parallel-pkgbuilds=4 \
--enable-rootfs=glibc-std --enable-build=production \
--with-layer="wr-qat,wr-dpdk" \ --with-template=feature/kvm,feature/analysis,feature/code_coverage,feature/debug,feature/gdb,feature/target-toolchain
   
参数说明:
configure :wrlinux6.0安装目录下的configure脚本
--enable-board:支持的BSP类型,必选
--enable-kernel:内核属性设置,必选
--enable-jobs,--enable-parallel-pkgbuilds :编译过程中的并行任务数
--enable-rootfs :rootfs类型,必选
--enable-build :创建release版WRLinux OS
--with-template :设置添加到target OS的应用软件
--with-layer:与--with-template功能类似

1.2.2        系统平台工程常用目录
(以系统平台工程根目录为参考目录)
        build/: 所有子工程的存放目录,常用的有kernel,qemu,libvirt等子工程
        export/:  rootfs, kernel bzImage, sdk, rpm等操作系统相关元素导出目录
        config.log : 系统平台工程配置信息
        pkglist: 已安装的软件包列表

1.2.3        系统平台工程常用操作方法
(以系统平台工程根目录为参考目录)
        编译整个系统平台工程环境
$ make  
这一步会编译整个系统平台工程的所有任务,编译很全面,但是速度较慢。
执行make之后,会在工程的export/目录下输出rootfs,kernel bzImage,kernel modules等操作系统基本元素。以intel-x86-64_proj工程export/目录的文件为例:
        intel-x86-64-bzImage-WR6.0.0.1_standard:kernel bzImage文件
        intel-x86-64-linux-modules-WR6.0.0.1_standard.tgz:kernel modules文件
        intel-x86-64-glibc-std-standard-dist.tar.bz2:rootfs压缩包

        编译文件系统
$ make fs

        编译内核
$ make –C build linux-windriver.menuconfig    # 设置内核编译选项
$ make –C build linux-windriver.clean          # 清空内核编译环境
$ make –C build linux-windriver.rebuild        # 重新编译内核
内核源码工程的目录为: build/linux-windriver/linux

        输出sdk(交叉编译工具链)
make -C build lib32-zlib.addpkg
make -C build lib32-gcc.addpkg
make export-sdk
$ cd export/
$ ./wrlinux-6.0.0.1-XXX-sdk.sh    # 这一步会提示指定sdk输出路径
        将输出的sdk内容打包,用作交叉编译工具链。

        输出rootfs的debug补丁包(gdb调试过程中使用)
$ make fs-debug
在export/目录下输出debug补丁包:XXX.dist-debuginfo.tar.bz2,使用时,直接在wrlinux6.0 target OS的根目录下解压缩即可。

        pkg的添加,配置及编译
$ make –C build <pkg name>.addpkg   #添加指定的pkg信息
$ make –C build <pkg name>.rmpkg    #删除指定的pkg信息
$ make –C build <pkg name>.config    # 配置pkg工程
$ make –C build <pkg name>.build     # 编译pkg工程
$ make –C build <pkg name>.clean     # 清空pkg工程
$ make –C build <pkg name>.rebuild    # 重新编译pkg工程
一般而言,完成pkg的添加或者删除后,都需要make一下整个系统平台工程,保证新增/删除的pkg包信息体现在新的rootfs中。
或者,到pkg对应的子工程目录下,找出相应的rpm包,拷贝到wrlinux6.0 target OS环境中进行手动安装。
更多wrlinux 6.0系统平台工程的工程结构及操作方法请参看windriver的帮助手册:

关于当前wrlinux6.0支持的board type, pkg name等信息则请参看wrlinux6.0 release note:

论坛徽章:
3
天秤座
日期:2013-12-27 13:44:58射手座
日期:2014-05-22 16:52:43天蝎座
日期:2014-08-13 16:03:21
39 [报告]
发表于 2011-01-23 14:37 |只看该作者
本帖最后由 compare2000 于 2013-09-03 21:23 编辑

墨菲定律、二八法则、马太效应、手表定理、“不值得”定律、彼得原理、零和游戏、华盛顿合作规律、酒与污水定律、水桶定律、蘑菇管理原理、钱的问题、奥卡姆剃刀等13条是左右人生的金科玉律
一、墨菲定律
    1949年,一位名叫墨菲的空军上尉工程师,认为他的某位同事是个倒霉蛋,不经意间开了句玩笑:“如果一件事情有可能被弄糟,让他去做就一定会弄糟。”
??这句话迅速流传,并扩散到世界各地。在流传扩散的过程中,这句笑话逐渐失去它原有的局限性,演变成各种各样的形式,其中一个最通行的形式是:“如果坏事情有可能发生,不管这种可能性多么小,它总会发生,并引起最大可能的损失。”
??  这就是著名的“墨菲定律”。下面是墨菲定律的一些变种或推论。
??人生哲学
?? 1.别试图教猫唱歌,这样不但不会有结果,还会惹猫不高兴?
?? 2.别跟傻瓜吵架,不然旁人会搞不清楚,到底谁是傻瓜?
?? 3.不要以为自己很重要,因为没有你,太阳明天还是一样从东方升上来?
?? 4.笑一笑,明天未必比今天好。
?? 5.好的开始,未必就有好结果;坏的开始,结果往往会更糟。
??处世原理
?? 6.你若帮助了一个急需用钱的朋友,他一定会记得你——在他下次急需用钱的时候。
?? 7.有能力的——让他做;没能力的──教他做;做不来的──管理他。
?? 8.你早到了,会议却取消;你准时到,却还要等;迟到,就是迟了。
?? 9.你携伴出游,越不想让人看见,越会遇见熟人。
??爱情意义
?? 10.你爱上的人,总以为你爱上他是因为:他使你想起你的老情人。
?? 11.你最后硬着头皮寄出的情书;寄达对方的时间有多长,你反悔的时间就有多长。
??生活常识
?? 12.东西越好,越不中用。
?? 13.一种产品保证60天不会出故障,等于保证第61天一定就会坏掉。
?? 14.东西久久都派不上用场,就可以丢掉;东西一丢掉,往往就必须要用它。
?? 15.你丢掉了东西时,最先去找的地方,往往也是可能找到的最后一个地方。
?? 16.你往往会找到不是你正想找的东西。
?? 17.你出去买爆米花的时候,银幕上偏偏就出现了精彩镜头。
?? 18.另一排总是动的比较快;你换到另一排,你原来站的那一排,就开始动的比较快了;你站的越久,越有可能是站错了排。
?? 19.一分钟有多长? 这要看你是蹲在厕所里面,还是等在厕所外面。

    二、二八法则

    1897年,意大利经济学家帕列托在对19世纪英国社会各阶层的财富和收益统计分析时发现:80%的社会财富集中在20%的人手里,而80%的人只拥有社会财富的20%,这就是“二八法则”。“二八法则”反应了一种不平衡性,但它却在社会、经济及生活中无处不在。    附:破窗理论等

     在商品营销中,商家往往会认为所有顾客一样重要;所有生意、每一种产品都必须付出相同的努力,所有机会都必须抓住。而“二八法则”恰恰指出了在原因和结果、投入和产出、努力和报酬之间存在这样一种典型的不平衡现象:80%的成绩,归功于20%的努力;市场上80%的产品可能是20%的企业生产的;20% 的顾客可能给商家带来80%的利润。遵循“二八法则”的企业在经营和管理中往往能抓住关键的少数顾客,精确定位,加强服务,达到事半功倍的效果。美国的普尔斯马特会员店始终坚持会员制,就是基于这一经营理念。

    “二八法则”同样适用于我们的生活,如一个人应该选择在几件事上追求卓越,而不必强求在每件事上都有好的表现;锁定少数能完成的人生目标,而不必追求所有的机会。

    三、马太效应

    《新约·马太福音》中有这样一个故事,一个国王远行前,交给三个仆人每人一锭银子,吩咐他们:“你们去做生意,等我回来时,再来见我。”国王回来时,第一个仆人说:“主人,你交给我的一锭银子,我已赚了10锭。”于是国王奖励了他10座城邑。第二个仆人报告说:“主人,你给我的一锭银子,我已赚了5锭。” 于是国王便奖励了他5座城邑。第三个仆人报告说:“主人,你给我的一锭银子,我一直包在手巾里存着,我怕丢失,一直没有拿出来。”于是国王命令将第三个仆人的那锭银子赏给第一个仆人,并且说:“凡是少的,就连他所有的,也要夺过来。凡是多的,还要给他,叫他多多益善。”这就是马太效应,它反映了当今社会中存在的一个普遍现象,即赢家通吃。
对企业经营发展而言,马太效应告诉我们,要想在某个领域保持优势,就必须在此领域迅速做大。当你成为某个领域的领头羊的时候,即便投资回报率相同,你也能更轻易地获得比弱小的同行更大的收益。而若没有实力迅速在某个领域做大,就要不停地寻找新的发展领域,才能保证获得较好的回报。

    四、手表定理

    手表定理是指一个人有一只表时,可以知道现在是几点钟,而当他同时拥有两只表时却无法确定。两只表并不能告诉一个人更准确的时间,反而会让看表的人失去对准确时间的信心。你要做的就是选择其中较信赖的一只,尽力校准它,并以此作为你的标准,听从它的指引行事。记住尼采的话:“兄弟,如果你是幸运的,你只需有一种道德而不要贪多,这样,你过桥更容易些。”
  如果每个人都“选择你所爱,爱你所选择”,无论成败都可以心安理得。然而,困扰很多人的是:他们被“两只表”弄得无所,心身交瘁,不知自己该信仰哪一个,还有人在环境、他人的压力下,违心选择了自己并不喜欢的道路,为此而郁郁终生,即使取得了受人瞩目的成就,也体会不到成功的快乐。
  手表定理在企业经营管理方面给我们一种非常直观的启发,就是对同一个人或同一个组织的管理不能同时采用两种不同的方法,不能同时设置两个不同的目标。甚至每一个人不能由两个人来同时指挥,否则将使这个企业或这个人无所适从。手表定理所指的另一层含义在于每个人都不能同时挑选两种不同的价值观,否则,你的行为将陷于混乱。

    五、“不值得”定律

    不值得定律最直观的表述是:不值得做的事情,就不值得做好,这个定律似乎再简单不过了,但它的重要性却时时被人们疏忘。不值得定律反映出人们的一种心理,一个人如果从事的是一份自认为不值得做的事情,往往会保持冷嘲热讽,敷衍了事的态度。不仅成功率小,而且即使成功,也不会觉得有多大的成就感。
   哪些事值得做呢?一般而言,这取决于三个因素。
  1、价值观。关于价值观我们已经谈了很多,只有符合我们价值观的事,我们才会满怀热情去做。
  2、个性和气质。一个人如果做一份与他的个性气质完全背离的工作,他是很难做好的,如一个好交往的人成了档案员,或一个害羞者不得不每天和不同的人打交道。
  3、现实的处境。同样一份工作,在不同的处境下去做,给我们的感受也是不同的。例如,在一家大公司,如果你最初做的是打杂跑腿的工作,你很可能认为是不值得的,可是,一旦你被提升为领班或部门经理,你就不会这样认为了。
  总结一下,值得做的工作是:符合我们的价值观,适合我们的个性与气质,并能让我们看到期望。如果你的工作不具备这三个因素,你就要考虑换一个更合适的工作,并努力做好它。
  因此,对个人来说,应在多种可供选择的奋斗目标及价值观中挑选一种,然后为之而奋斗。“选择你所爱的,爱你所选择的”,才可能激发我们的奋斗毅力,也才可以心安理得。而对一个企业或组织来说,则要很好地分析员工的性格特性,合理分配工作,如让成就欲较强的职工单独或牵头来完成具有一定风险和难度的工作,并在其完成时给予定时的肯定和赞扬;让依附欲较强的职工更多地参加到某个团体中共同工作;让权力欲较强的职工担任一个与之能力相适应的主管。同时要加强员工对企业目标的认同感,让员工感觉到自己所做的工作是值得的,这样才能激发职工的热情。

    六、彼得原理

管理学家劳伦斯·丁·彼得(Laurence.J.Peter),1917年牛于加拿大的范库弗,1957年获美国华盛顿州立大学学士学位,6年后又获得该校教育哲学博士学位,他阅历丰富,博学多才,著述颇丰,他的名字还被收人了《美国名人榜》、《美国科学界名人录》和《国际名人传记辞典》等辞书中。

     彼得原理(The Peter PrinciPle)正是彼得根据千百个有关组织中不能胜任的失败实例的分析而归纳出来的。其具体内容是:“在一个等级制度中,每个职工趋向于上升到他所不能胜任的地位”。彼得指出,每一个职工由于在原有职位上工作成绩表现好(胜任),就将被提升到更高一级职位;其后,如果继续胜任则将进一步被提升,直至到达他所不能胜任的职位。由此导出的彼得推论是,“每一个职位最终都将被一个不能胜任其工作的职工所占据。层级组织的工作任务多半是由尚未达到不胜任阶层的员工完成的。”每一个职工最终都将达到彼得高地,在该处他的提升商数(PQ)为零。至于如何加速提升到这个高地,有两种方法。其一。是上面的“拉动”,即依靠裙带关系和熟人等从上面拉;其二是自我的“推动”,即自我训练和进步等,而前者是被普遍采用的。

     彼得认为,由于彼得原理的推出,使他“无意间”创设了一门新的科学——层级组织学(hierarchiolgy)。该科学是解开所有阶层制度之谜的钥匙,因此也是了解整个文明结构的关键所在。凡是置身于商业、工业、政治、行政、军亨、宗教、教育各界的每个人都和层级组织息息相关,亦都受彼得原理的控制。当然,原理的假设条件是:时间足够长,五层级组织里有足够的阶层。彼得原理被认为是同帕金森定律有联系的。

     帕金森(C.N.Parkinson)是著名的社会理论家,他曾仔细观察并有趣地描述层级组织中冗员累积的现象。他假设,组织中的高级主管采用分化和征服的策略,故意使组织效率降低,借以提升自己的权势,这种现象即帕金森所说的“爬升金字塔”。彼得认为这种理论设计是有缺陷的,他给出的解释员工累增现象的原因是层级组织的高级主管真诚追求效率(虽然徒劳无功)。正如彼得原理显示的,许多或大多数主管必已到达他们的不胜任阶层。这些人无法改进现有的状况,因为所有的员工已经竭尽全力了,于是为了再增进效率,他们只好雇用更多的员工。员工的增加或许可以使效率暂时提升,但是这些新进的人员最后将因晋升过程而到达不胜任阶层,于是唯一改善的方法就是再次增雇员工,再次获得暂时的高效率,然后是另一。次逐渐归于无效率。这样就使组织中的人数超过了工作的实际需要。

     彼得原理首次公开发表于1960年9月美国联邦出资的一次研习会上,听众是一群负责教育研究计划、并刚获晋升的项目主管,彼得认为他们多数人“只是拼命地想复制一些老掉牙了的统计习题”,于是引介彼得原理说明他们的困境。演说召来了敌意与嘲笑,但是彼得仍然决定以独特的讽刺手法呈现彼得原理,尽管所有案例研究都经过精确编纂,且引用的资料也都符合事实,最后定稿于1965年春完成,然后总计有16家之多的出版社无情地拒绝了该书的手稿。1966年,作者零星地在报纸上发表了几篇述论同一主题的文章,读者的反应异常热烈,引得各个出版社趋之若婺鸳。正如彼得在自传中提到的,人偶尔会在镜中瞥见自己的身影而不能立即自我辩认,于是在不自知前就加以嘲笑一番,这样的片刻里正好可以使人进一步认识自己,“彼得原理”扮演的正是那样一面镜子。

    七、零和游戏

一个游戏无论几个人来玩,总有输家和赢家,赢家所赢的都是输家所翰的,所以无论输赢多少,正负相抵,最后游戏的总和都为零,这就是零和游戏。
    零和游戏之所以受人关注,是因为人们在社会生活中处处都能找到与零和游戏雷同或类似的现象。我们大肆开发利用煤炭石油资源,留给后人的便越来越少;我们研究生产了大量的转基因产品,一些新的病毒也跟着冒了出来;我们修筑了葛洲坝水利工程,白鳍豚就再也不能洄游到金沙江产卵了……
    发展是硬道理。人类在经历了经济高速增长、科技迅猛发展、全球经济一体化及曰益严重的生态破坏、环境污染之后,可持续发展理论才逐渐浮出水面。零和游戏原理正在逐渐为“双赢”观念所取代,人们逐渐认识到“利己”而不“损人”才是最美好的结局。实践证明,通过有效合作,实现皆大欢喜的结局是可能的。
    领导者要善于跳出“零和”的圈子,寻找能够实现“双赢”的机遇和突破口,防止负面影响抵消正面成绩。批评下属如何才能做到使其接受而不抵触,发展经济如何才能做到不损害环境,开展竞争如何使自己胜出而不让对方受到伤害,这些都是每一个为官者应该仔细思考的问题。
    还是那句话,世上没有现成的标准答案。这些企业经营管理定律只能供我们参考和借鉴,至于什么条件下适合借鉴哪一种,回到手表定理上去,你需要自己选择一块戴着舒适而又走时准确的手表。

    八、华盛顿合作规律

    华盛顿合作规律说的是:一个人敷衍了事,两个人互相推诿,三个人则永无成事之日。多少有点类似于“三个和尚”的故事。

  人与人的合作不是人力的简单相加,而是复杂和微妙得多。在人与人的合作中,假定每一个人的能力都为1,那么10个人的合作结果有时比10大得多,有时甚至比1还要小。因为人不是静止的物,而更像方向不同的能量,相互推动时自然事半功倍,相互抵触时则一事无成。

    九、酒与污水定律

    酒与污水定律是指,如果把一匙酒倒进一桶污水中,你得到的是一桶污水;如果把一匙污水倒进一桶酒中,你得到的还是一桶污水。几乎在任何组织里,都存在几个难弄的人物,他们存在的目的似乎就是为了把事情搞糟。他们到处搬弄是非,传播流言、破坏组织内部的和谐。最糟糕的是,他们像果箱里的烂苹果,如果你不及时处理,它会迅速传染,把果箱里其它苹果也弄烂,“烂苹果”的可怕之处在于它那惊人的破坏力。一个正直能干的人进入一个混乱的部门可能会被吞没,而一个人无德无才者能很快将一个高效的部门变成一盘散沙。组织系统往往是脆弱的,是建立在相互理解、妥协和容忍的基础上的,它很容易被侵害、被毒化。破坏者能力非凡的另一个重要原因在于,破坏总比建设容易。一个能工巧匠花费时日精心制作的陶瓷器,一头驴子一秒钟就能毁坏掉。如果拥有再多的能工巧匠,也不会有多少像样的工作成果。如果你的组织里有这样的一头驴子,你应该马上把它清除掉;如果你无力这样做,你就应该把它拴起来。

     十、水桶定律

    一只水桶能装多少水取决于水桶中最短的一块木板而不是最长的那块木板。
    任何组织几乎都有一个共同的特点,即构成组织的各个部分往往是优劣不齐的,但劣势部分却往往决定着整个组织的水平。问题是劣势部分是组织中一个有用的部分,你不能把它当成烂苹果扔掉,否则,你会一点水也装不了,可它却让你那些长的东西白长了!
    劣势决定优势,劣势决定生死,这是市场竞争的残酷法则。水桶定律告诉我们,领导者要有忧患意识,如果你个人身上某个方面是“最短的一块”,你应该考虑尽快把它补起来;如果你所领导的集体中存在着“一块最短的木板”,你一定要迅速将它做长补齐,否则,它带给你的损失可能是毁灭性的—叫艮多时候,往往就是因为一件事没做好而毁了所有的努力。有些人也许不知道水桶定律,但都知道“一票否决”,这是中国的“水桶”,有了它你便矢口道水桶定律是多么重要。
    决策和执行发生的机率。让谋划的人尽心谋划,让执行的人全力执行,让他们都从中获得间接而不是直接的功利,这样我们才能把“粥”分得更好。当然,还应有必不可少的独立的监督。

    十一、蘑菇管理原理

    蘑菇长在阴暗的角落,得不到阳光,也没有肥料,自生自灭,只有长到足够高的时候才开始被人关注,可此时它自己已经能够接受阳光了。
    蘑菇管理是大多数组织对待初入门者、初学者的一种管理方法。从传统的观念上讲,“蘑菇经历”是一件好事,它是人才蜕壳羽化前的一种磨炼,对人的意志和耐力的培养有促进作用。但用发展的眼光来看,蘑菇管理有着先天的不足:一是太慢,还没等它长高长大恐怕疯长的野草就已经把它盖住了,使它没有成长的机会;二是缺乏主动,有些本来基因较好的蘑菇,一钻出土就碰上了石头,因为得不到帮助,结果胎死腹中。
    让初入门者当上一段时间的“蘑菇”,可以消除他们不切实际的幻想,从而使他们更加接近现实,更实际、更理性地思考问题和处理问题。领导者应当注意的是,这一过程不可过长,时间太长便会使其消极退化乃至枯萎,须知不给阳光不给关爱不仅是任其自生自灭,而且更是对其成长的抑制。如何让他们成功地走过生命中的这一段,尽快吸取经验、成熟起来,这才是领导者所应当考虑的。

    十二、钱的问题

    当某人告诉你:“不是钱,而是原则问题”时,十有八九就是钱的问题。
  照一般的说法,金钱是价值的尺度,交换的媒介,财富的贮藏。但是这种说法忽略了它的另一面,它令人陶醉、令人疯狂、令人激动的一面,也撇开了爱钱的心理不谈。马克思说,金钱是“人情的离心力”,就是指这一方面而言。
  关于金钱的本质、作用和功过,从古到今,人们已经留下了无数精辟深刻的格言和妙语。我们常会看到,人们为钱而兴奋,努力赚钱,用财富的画面挑逗自己。金钱对世界的秩序以及我们的生活产生的影响是巨大的、广泛的,这种影响有时是潜在的,我们往往意识不到它的作用如此巨大,然而奇妙的是:它完全是人类自己创造的。致富的驱动力并不是起源于生物学上的需要,动物生活中也找不到任何相同的现象。它不能顺应基本的目标,不能满足根本的需求 -的确,“致富”的定义就是获得超过自己需要的东西。然而这个看起来漫无目标的驱动力却是人类最强大的力量,人类为金钱而互相伤害,远超过其他原因。

    附:一街东头那个乞丐去摸彩票。中了五等奖,得款50元。甚喜!这个冬天好过了,他拥有棉袄、棉裤、和棉鞋了。街西头那个乞丐也去摸彩票。中了一等奖,得款50万元。狂喜! 

 首先大宴宾客,热闹三天,煞是风光,耗款3千元,小意思。然后买西服、配手机、穿金戴银,容光焕发,一扫穷气。再次,买房子,满街转悠,要带车库的。第四,就是买车了。“夏利”太便宜,“奔驰”太贵,还是“桑塔纳”吧!第五……第六……第七……过年的时候,街东头那个乞丐还在到处晃悠,穿着那50元买的 “家当”;而街西头那个乞丐却在劳教所里,据说是因为赌博、嫖娼、吸毒、闹事……拥有50元,街东头的乞丐不再受冻,自得其乐;拥有50万元,街西头乞丐成了个大富翁,却也把自己送上了死路。不懂得善用钱财的人,还是没钱点才安全。

    十三、奥卡姆剃刀定律

    12世纪,英国奥卡姆的威廉主张唯名论,只承认确实存在的东西,认为那些空洞无物的普遍性概念都是无用的累赘,应当被无情地“剃除”。他主张“如无必要,勿增实体”。这就是常说的“奥卡姆剃刀”。这把剃刀曾使很多人感到威胁,被认为是异端邪说,威廉本人也因此受到迫害。然而,并未损害这把刀的锋利,相反,经过数百年的岁月,奥卡姆剃刀已被历史磨得越来越快,并早已超载原来狭窄的领域,而具有广泛、丰富、深刻的意义。

  奥卡姆剃刀定律在企业管理中可进一步演化为简单与复杂定律:把事情变复杂很简单,把事情变简单很复杂。这个定律要求,我们在处理事情时,要把握事情的主要实质,把握主流,解决最根本的问题,尤其要顺应自然,不要把事情人为地复杂化,这样才能把事情处理好。

    美国政治学家威尔逊和犯罪学家凯林经过观察提出了“破窗理论”。

  如果有人打坏了一栋建筑上的一块玻璃,又没有及时修复,别人就可能受到某些暗示性的纵容,去打碎更多的玻璃。久而久之,这些窗户就给人造成一种无序的感觉,在这种麻木不仁的氛围中,犯罪就会滋生、蔓延。

  “破窗理论”更多的是从犯罪的心理去思考问题,但不管把“破窗理论”用在什么领域,角度不同,道理却相似:环境具有强烈的暗示性和诱导性,必须及时修好“第一扇被打碎玻璃的窗户”。

  推而广之,从人与环境的关系这个角度去看,我们周围生活中所发生的许多事情,不正是环境暗示和诱导作用的结果吗?

  比如,在窗明几净、环境优雅的场所,没有人会大声喧哗,或“噗”地吐出一口痰来;相反,如果环境脏乱不堪,倒是时常可以看见吐痰、便溺、打闹、互骂等不文明的举止。

  又比如,在公交车站,如果大家都井然有序地排队上车,又有多少人会不顾众人的文明举动和鄙夷眼光而贸然插队?与这相反,车辆尚未停稳,猴急的人们你推我拥,争先恐后,后来的人如果想排队上车,恐怕也没有耐心了。因此,环境好,不文明之举也会有所收敛;环境不好,文明的举动也会受到影响。人是环境的产物,同样,人的行为也是环境的一部分,两者之间是一种互动的关系。

  在公共场合,如果每个人都举止优雅、谈吐文明、遵守公德,往往能够营造出文明而富有教养的氛围。千万不要因为我们个人的粗鲁、野蛮和低俗行为而形成“破窗效应”,进而给公共场所带来无序和失去规范的感觉。

  从这个意义上说,我们平时一直强调的“从我做起,从身边做起”,就不仅仅是一个空洞的口号,它决定了我们自身的一言一行对环境造成什么样的影响。

论坛徽章:
3
天秤座
日期:2013-12-27 13:44:58射手座
日期:2014-05-22 16:52:43天蝎座
日期:2014-08-13 16:03:21
40 [报告]
发表于 2011-01-23 14:37 |只看该作者
本帖最后由 compare2000 于 2013-09-03 21:24 编辑

提问的智慧(How To Ask Questions The Smart Way
简介
      提问之前
      怎样提问
      谨慎选择论坛
      尽量使用邮件列表
      用辞贴切,语法正确,拼写无误
      用易读格式发送问题
      使用含义丰富,描述准确的标题
      精确描述,信息量大
      话不在多
      只说症状,不说猜想
      按时间顺序列出症状
      别要求私下答复
      明白你想问什么
      别问应该自己解决的问题
      去除无意义的疑问
      谦逊绝没有害处,而且常帮大忙
      问题解决后,加个简短说明
      如何理解答案
      RTFM和STFW:别烦我啦
      还是不懂

      面对无礼
      决不要象个失败者
      三思而后问
      好问题,坏问题
      找不到答案怎么办

      ====
      简介
      ====

      在黑客世界里,当提出一个技术问题时,你能得到怎样的回答?这取决于挖出答案的难
      度,同样取决于你提问的方法。本指南旨在帮助你提高发问技巧,以获取你最想要的答
      案。

      首先你必须明白,黑客们只偏爱艰巨的任务,或者能激发他们思维的好问题。如若不然,
      我们还来干吗?如果你有值得我们反复咀嚼玩味的好问题,我们自会对你感激不尽。好问
      题是激励,是厚礼,可以提高我们的理解力,而且通常会暴露我们以前从没意识到或者思
      考过的问题。对黑客而言,“问得好!”是发自内心的大力称赞。

      尽管黑客们有蔑视简单问题和不友善的坏名声,有时看起来似乎我们对新手,对知识贫乏
      者怀有敌意,但其实不是那样的。

      我们不想掩饰对这样一些人的蔑视--他们不愿思考,或者在发问前不去完成他们应该做的
      事。这种人只会谋杀时间--他们只愿索取,从不付出,无端消耗我们的时间,而我们本可
      以把时间用在更有趣的问题或者更值得回答的人身上。我们称这样的人为“失败者”(由
      于历史原因,我们有时把它拼作“lusers”)。

      我们也知道,很多人只想使用我们编写的软件,对技术细节没什么兴趣。对多数人们而
      言,计算机不过是一个工具,一种达到目的的手段;他们有更重要的事情要做,有更重要
      的生活要过。我们明白这点,也并不奢望每个人都对另我们痴狂的技术问题有兴致。然
      而,我们回答问题的风格是针对这样一群人--他们有兴趣,并且愿意积极参与问题的解
      决。这点不会改变,也不应该改变;如果变了,我们将失去我们引以为傲的效率。

      我们在很大程度上属于志愿者,从繁忙的生活中抽出时间来解惑答疑,而且时常被提问淹
      没。所以我们无情的滤掉一些话题,特别是抛弃那些看起来象失败者的家伙,以便更高效
      的利用时间来回答胜利者的问题。

      如果你觉得我们过于傲慢的态度让你不爽,让你委屈,不妨设身处地想想。我们并没有要
      求你向我们屈服--事实上,我们中的大多数人最喜欢公平交易不过了,只要你付出小小努
      力来满足最起码的要求,我们就会欢迎你加入到我们的文化中来。但让我们帮助那些不愿
      意帮助自己的人是没有意义的。如果你不能接受这种“歧视”,我们建议你花点钱找家商
      业公司签个技术支持协议得了,别向黑客乞求帮助。

      如果你决定向我们求助,当然不希望被视为失败者,更不愿成为失败者中的一员。立刻得
      到有效答案的最好方法,就是象胜利者那样提问--聪明、自信、有解决问题的思路,只是
      偶尔在特定的问题上需要获得一点帮助。

      (欢迎对本指南提出改进意见。任何建议请E-mail至esr@thyrsus.com,然而请注意,本
      文并非网络礼节的通用指南,我通常会拒绝无助于在技术论坛得到有用答案的建议。)
      (当然,如果你写中文,最好还是寄到DHGrand@hotmail.com;-)

      ========
      提问之前
      ========

      在通过电邮、新闻组或者聊天室提出技术问题前,检查你有没有做到:
      1. 通读手册,试着自己找答案。
      2. 在FAQ里找答案(一份维护得好的FAQ可以包罗万象:)。
      3. 在网上搜索(个人推荐google~)。
      4. 向你身边精于此道的朋友打听。


      当你提出问题的时候,首先要说明在此之前你干了些什么;这将有助于树立你的形象:你
      不是一个妄图不劳而获的乞讨者,不愿浪费别人的时间。能说明你从这些操作中学到了什
      么就更好了。如果提问者能从答案中学到东西,我们更乐于回答他的问题。

      周全的思考,准备好你的问题,草率的发问只能得到草率的回答,或者根本得不到任何答
      案。越表现出在寻求帮助前为解决问题付出的努力,你越能得到实质性的帮助。

      小心别问错了问题。如果你的问题基于错误的假设,普通黑客(J. Random Hacker)通
      常会用无意义的字面解释来答复你,心里想着“蠢问题...”,希望着你会从问题的回答
      (而非你想得到的答案)中汲取教训。

      决不要自以为够资格得到答案,你没这种资格。毕竟你没有为这种服务支付任何报酬。你
      要自己去“挣”回一个答案,靠提出一个有内涵的,有趣的,有思维激励作用的问题--一
      个对社区的经验有潜在贡献的问题,而不仅仅是被动的从他人处索要知识--去挣到这个答
      案。

      另一方面,表明你愿意在找答案的过程中做点什么,是一个非常好的开端。“谁能给点提
      示?”、“我这个例子里缺了什么?”以及“我应该检查什么地方?”比“请把确切的过
      程贴出来”更容易得到答复。因为你显得只要有人指点正确的方向,你就有完成它的能力
      和决心。

      ========
      怎样提问
      ========

      ------------
      谨慎选择论坛
      ------------

      小心选择提问的场合。如果象下面描述的那样,你很可能被忽略掉或者被看作失败者:
      1. 在风马牛不相及的论坛贴出你的问题
      2. 在探讨高级技巧的论坛张贴非常初级的问题;反之亦然
      3. 在太多的不同新闻组交叉张贴

      黑客们通常砍掉问错地方的问题,以保护自己的社区不被大量无关帖子淹没。你不会希望
      自己的帖子被这样砍掉吧。

      总的说来,问题发到精心挑选的公众论坛,比发到封闭的小圈子更容易得到有用的答案。
      这一现象有多种原因,其中之一是公众论坛有更多潜在的问题回答者;另一个原因是公众
      论坛有更多的听众。黑客们更愿意让尽量多的人--而非有限的一两个--从回答中受益。

      ----------------
      尽量使用邮件列表
      ----------------

      如果某项目有自己的开发邮件列表,要把问题发到这个邮件列表而不是某个开发者,即使
      你很清楚谁最能回答你的问题。仔细查看项目文档和项目主页,找到这个项目的邮件列表
      地址,这样做的理由有四:
      1. 任何值得问某位开发者的好问题,都值得向整个开发团体提出。反之,若你认为这个
      问题不值得在邮件列表中提起,就没有理由用它来骚扰任何一位开发者。
      2. 在邮件列表提问可以分担开发者的工作量。某位开发者(尤其当他是项目负责人的情
      况下),可能忙得没时间回答你的问题。
      3. 大多数邮件列表都有历史存档,而且都能在搜索引擎中检索到。人们可以从中找到你
      的问题和答案,不用一遍又一遍在列表中发问。
      4. 如果某个问题经常被提出,开发者可以据此改进文档或改进软件,以减少用户的困
      惑。而如果问题总在私下提出,就不会有人对此有整体上的把握了。

      如果你找不到项目的邮件列表地址,只能看到项目维护者的,那就写给维护者吧。在这种
      情况下,也别以为邮件列表并不存在。在你的信中写明你已尽力寻找,仍无法找到邮件列
      表。另外表明你不介意将此消息转给他人。(大多数人认为私信就应该是私下的,即使并
      没有什么可保密的内容。允许你的消息被转寄给他人,给了收信者一种处理你邮件的选
      择。)


      ----------------------------
      用辞贴切,语法正确,拼写无误
      ----------------------------

      我们从经验中发现,粗心的写作者通常也是马虎的思考者(我敢打包票)。回答粗心大意
      者的问题很不值得,我们宁愿把时间耗在别处。

      因此,明确充分表述你的问题非常重要。如果你嫌这样做麻烦,我们也会懒得搭理你。注
      意推敲你的用辞,不一定要用呆板正式的语言--事实上,黑客文化的价值观是不拘小节。
      准确的运用俚语和富有幽默感的语言,但别乱用;一定要能表明你在思考,在关注。


      正确的拼写,标点符号和大小写很重要。别把“its”和“it's”或者“loose”和
      “lose”搞混淆了。别用全部大写的形式,这被视为粗鲁的大声叫嚷(全都用小写也好不
      到哪儿去,因为这会给阅读带来困难。Alan Cox可以用全部小写,但你不行)。


      更一般的说,如果你的提问写得象个半文盲,你很有可能被忽视。如果写得象一个窥客
      (破解爱好者)或者灰客(只会用现成工具的捣乱者)绝对是自己找死,保证你除了无情
      的抵制什么也得不到(或者,最好的结局是得到一大堆挖苦嘲笑的“帮助”)。

      如果你在使用非母语的论坛提问,你可以犯点拼写和语法上的小错--但决不能在思考上马
      虎(没错,我们能弄清两者的分别)。另外,除非你确切知道你的回答者会使用什么语
      言,否则请用英文。匆匆忙忙的黑客往往简单的跳过他们看不懂的问题,而英文是网络上
      的工作语言。用英文可以降低你的问题未被阅读即遭抛弃的风险。

      ------------------
      用易读格式发送问题
      ------------------

      如果人为造成你的提问难以阅读和理解,将会更容易被人忽略。因此你要:
      1. 使用纯文本邮件,不要使用HTML(关掉HTML并不难)。
      2. 通常可以附加MIME附件,但一定要有真正的内容(例如附加的源文件或者补丁),而
      不仅仅是你的邮件客户端产生的文件模板(例如你邮件的一份拷贝)。
      3. 不要把所有问题放在不停换行的一整段中。(这将让答复的人难于回答其中一部分问
      题,即使能回答所有问题,我也更希望条理清楚的一个一个来:)。很可能收件人只能在
      80个字符宽度的文本显示器上读信,因此要相应的把行环绕模式设在80字符以内。
      4. 不要在英文论坛使用MIME Quoted-Printable编码发送;这种编码格式对ASCII码不
      能表达的语言来说是非常必要的,但很多邮件代理不支持它,这时,满篇的“=20”符号
      把文字分割开,既难看,又分散注意力。

      5. 永远不要指望黑客会乐于阅读封闭所有权的文件格式,例如萎软的Word格式。多数黑
      客对此的反应就象你在门口的阶梯上堆满热烘烘的猪粪(意即谁也不会踏进你的门--译者
      注)。

      6. 如果你通过一台安装Windows的电脑发送邮件,关闭萎软愚蠢的“智能引用”功能。这
      能使你免于在邮件中夹带垃圾字符。

      ----------------------------
      使用含义丰富,描述准确的标题
      ----------------------------

      在邮件列表或者新闻组中,大约50字以内的主题标题是抓住资深专家注意力的黄金时机。
      别用喋喋不休的“帮帮忙”(更别说“救命啊!!!!!”这样让人反感的话)来浪费这
      个机会。不要妄想用你的痛苦程度来打动我们,别用空格代替问题的描述,哪怕是极其简
      短的描述。

      蠢问题:
      救命啊!我的膝上机不能正常显示了!

      聪明问题:
      XFree86 4.1下鼠标光标变形,Fooware MV1005的显示芯片。

      如果你在回复中提出问题,记得要修改内容标题,表明里面有一个问题。一个看起来象
      “Re:测试”或者“Re:新bug”的问题很难引起足够重视。另外,引用并删减前文的内
      容,给新来的读者留下线索。

      ------------------
      精确描述,信息量大
      ------------------

      1. 谨慎明确的描述症状。
      2. 提供问题发生的环境(机器配置、操作系统、应用程序以及别的什么)。
      3. 说明你在提问前是怎样去研究和理解这个问题的。
      4. 说明你在提问前采取了什么步骤去解决它。
      5. 罗列最近做过什么可能有影响的硬件、软件变更。

      尽量想象一个黑客会怎样反问你,在提问的时候预先给他答案。

      Simon Tatham写过一篇名为《如何有效的报告Bug》的出色短文。强力推荐你也读一读。


      --------
      话不在多
      --------

      你需要提供精确有效的信息。这并不是要求你简单的把成吨的出错代码或者数据完全转储
      摘录到你的提问中。如果你有庞大而复杂的测试条件,尽量把它剪裁得越小越好。

      这样做的用处至少有三点。第一,表现出你为简化问题付出了努力,这可以使你得到回答
      的机会增加;第二,简化问题使你得到有用答案的机会增加;第三,在提炼你的bug报告
      的过程中,也许你自己就能找出问题所在或作出更正。

      ------------------
      只说症状,不说猜想
      ------------------

      告诉黑客们你认为问题是怎样引起的没什么帮助。(如果你的推断如此有效,还用向别人
      求助吗?),因此要确信你原原本本告诉了他们问题的症状,不要加进你自己的理解和推
      论。让黑客们来诊断吧。

      蠢问题:
      我在内核编译中一次又一次遇到SIG11错误,我怀疑某条飞线搭在主板的走线上了,这种
      情况应该怎样检查最好?

      聪明问题:
      我自制的一套K6/233系统,主板是FIC-PA2007 (VIA Apollo VP2芯片组),256MB
      Corsair PC133 SDRAM,在内核编译中频频产生SIG11错误,从开机20分钟以后就有这种
      情况,开机前20分钟内从没发生过。重启也没有用,但是关机一晚上就又能工作20分钟。
      所有内存都换过了,没有效果。相关部分的典型编译记录如下...。

      ------------------
      按时间顺序列出症状
      ------------------

      对找出问题最有帮助的线索,往往就是问题发生前的一系列操作,因此,你的说明应该包
      含操作步骤,以及电脑的反应,直到问题产生。在命令行操作的情况下,保存一个操作记
      录(例如使用脚本工具),并且引用相关的大约20条命令会大有帮助。

      如果崩溃的程序有诊断选项(例如用-v转到详尽模式),试着仔细考虑选择选项以在操作
      记录中增加有用的调试信息。

      如果你的说明很长(超过四个段落),在开头简述问题会有所帮助,接下来按时间顺序详
      述。这样黑客们就知道该在你的说明中找什么。

      --------------
      别要求私下答复
      --------------

      黑客们认为解决问题应该有公开、透明的流程。只要任何更有见地的人注意到答案的不完
      善或者不正确,这个最初的答案就可以和应该得到纠正。同时,通过能力和知识被大家注
      意,被大家接受,回答问题者得到了应有的奖励。

      如果你要求对方私下回答你,这既破坏了整个流程,也破坏了奖励制度。别提这要求,这
      是回答者的权利,由他来选择是否私下答复--如果他选择这样做,通常是因为他认为这个
      答案过于显而易见或者有不良的公开影响,别人不会感兴趣。

      只有一种有限的例外:如果你预计将收到大量雷同的答复,你可以说:“把答案寄给我,
      由我来汇总吧。”将邮件列表或者新闻组从大量重复的帖子中打救出来是很有君子之风的
      --但请记住,履行自己关于汇总的承诺。

      --------------
      明白你想问什么

      --------------

      漫无边际的提问近乎无休无止的时间黑洞。最能给你有用答案的人也正是最忙的人(他们
      忙是因为要亲自完成大部分工作)。这样的人对无节制的时间黑洞不太感冒,因此也可以
      说他们对漫无边际的提问不大感冒。

      如果你明确表述需要回答者做什么(提供建议,发送一段代码,检查你的补丁或是别
      的),就最有可能得到有用的答案。这会定出一个时间和精力的上限,便于回答者集中精
      力来帮你,这很凑效。

      要理解专家们生活的世界,要把专业技能想象为充裕的资源,而回复的时间则是贫乏的资
      源。解决你的问题需要的时间越少,越能从忙碌的专家口中掏出答案。

      因此,优化问题的结构,尽量减少专家们解决它所需要的时间,会有很大的帮助--这通常
      和简化问题有所区别。因此,问“我想更好的理解X,能给点提示吗?”通常比问“你能
      解释一下X吗?”更好。如果你的代码不能工作,问问它有什么地方不对,比要求别人替
      你修改要明智得多。


      ------------------------
      别问应该自己解决的问题
      ------------------------

      黑客们总是善于分辨哪些问题应该由你自己解决;因为我们中的大多数都曾自己解决这类
      问题。同样,这些问题得由你来搞定,你会从中学到东西。你可以要求给点提示,但别要
      求得到完整的解决方案。

      ----------------
      去除无意义的疑问
      ----------------

      别用无意义的话结束提问,例如“有人能帮我吗?”或者“有答案吗?”。首先:如果你
      对问题的描述不很合适,这样问更是画蛇添足。其次:由于这样问是画蛇添足,黑客们会
      很厌烦你--而且通常会用逻辑上正确的回答来表示他们的蔑视,例如:“没错,有人能帮
      你”或者“不,没答案”。

      ----------------------------
      谦逊绝没有害处,而且常帮大忙
      ----------------------------

      彬彬有礼,多用“请”和“先道个谢了”。让大家都知道你对他们花费时间义务提供帮助
      心存感激。

      实话实说,虽然这不象合乎语法、清楚准确的描述,避免私有格式等等那么重要(也不能
      用来替代它们);黑客一般更喜欢直接了当然而技术上敏锐的bug报告,而不是彬彬有礼
      的废话(如果这让你迷惑不解,请记住,我们衡量一个问题价值的标准是:它能让我们学
      会多少)。

      然而,如果你有很多问题无法解决,礼貌将会增加你得到有用答案的机会。

      (我们注意到,自从本指南发布后,从资深黑客处得到的唯一严重缺陷反馈,就是对预先
      道谢这一条。一些黑客觉得“先谢了”的言外之意是过后就不会再感谢任何人了。我们的
      建议是:都道谢。)

      ------------------------

      问题解决后,加个简短说明
      ------------------------

      问题解决后,向所有帮助过你的人发个说明,让他们知道问题是怎样解决的,并再一次向
      他们表示感谢。如果问题在新闻组或者邮件列表中引起了广泛关注,应该在那里贴一个补
      充说明。

      补充说明不必很长或是很深入;简单的一句“你好,原来是网线出了问题!谢谢大家
      --Bill”比什么也不说要强。事实上,除非结论真的很有技术含量,否则简短可爱的小结
      比长篇学术论文更好。说明问题是怎样解决的,但大可不必将解决问题的过程复述一遍。


      除了表示礼貌和反馈信息以外,这种补充有助于他人在邮件列表/新闻组/论坛中搜索对你
      有过帮助的完整解决方案,这可能对他们也很有用。

      最后(至少?),这种补充有助于所有提供过帮助的人从中得到满足感。如果你自己不是
      老手或者黑客,那就相信我们,这种感觉对于那些你向他们求助的导师或者专家而言,是
      非常重要的。问题久拖未决会让人灰心;黑客们渴望看到问题被解决。好人有好报,满足
      他们的渴望,你会在下次贴出新问题时尝到甜头。

      ============
      如何理解答案
      ============

      --------------------
      RTFM和STFW:别烦我啦
      --------------------

      有一个古老而神圣的传统:如果你收到“RTFM (Read The Fucking Manual)”的回
      复,回答者认为你应该去读TMD手册。当然,基本上他是对的,你应该读一读。

      RTFM有一个年轻的亲戚。如果答案是“STFW (Search The Fucking Web)”,回答者
      认为你应该到TMD的网上去搜索。基本上,他也是对的,你就去找吧。

      通常,用这两句之一回答你的人会给你一份包含你需要内容的手册或者一个网址,而且他
      们打这些字的时候正在阅读着。这些答复意味着回答者认为(1). 你需要的信息非常容易
      获得;(2). 你自己去搜索这些信息比灌给你能让你学到更多。

      别为这个而不爽;依照黑客的标准,他没有对你的要求视而不见,已经能大致能表示对你
      的关注。你应该对他祖母般的慈祥表示感谢。

      ----------
      还是不懂
      ----------

      如果你不是很理解答案,别立刻要求对方解释。象你以前试着自己解决问题时那样(利用
      手册,FAQ,网络,身边的高手),去理解它。如果你真的需要对方解释,记得表现出你
      已经学到了点什么。

      比方说,如果我回答你:“看来似乎是zEntry被阻塞了;你应该先清除它。”,然后:

      一个很糟的后续问题:“zEntry是什么?”

      聪明的问法应该是这样:“哦~我看过帮助了但是只有-z和-p两个参数中提到了
      zEntry而且还都没有清楚的解释:<你是指这两个中的哪一个吗?还是我看漏了什么?”


      --------
      面对无礼
      --------

      黑客圈子里很多貌似粗鲁的言行并非有意冒犯。更恰当的说,这是直率、不说废话的沟通
      方式的产物,这种沟通方式源于人们关注问题的解决--多过让人感受温暖亲情然而却依旧
      糊里糊涂--的天性。

      如果你觉得受到粗鲁的对待,请保持冷静。如果真有人表现粗野,通常会有列表/新闻组/
      论坛的长辈找他谈心,如果没有这样,而你又大发脾气,则很可能对方的言行是黑客社区
      行为规范许可内,而你被认为是有过错的。这会不利于你得到信息或者帮助。

      另一方面,你偶尔也会无缘无故有粗野的言行和心态。上述现象的另一面是,人们允许狠
      狠打击真正的冒犯者,用尖刻的言语剖析他们的不当言行。如果你真决定这样做,先仔细
      又仔细的掂量一下你自己的分量。合理的粗鲁与发动一场无意义的论战之间只隔了一条细
      细的线,冒冒失失撞上去的黑客不在少数;如果你是新手或者门外汉,不犯这种错的机会
      是很渺茫的。如果你想得到信息而不是来胡闹,别冒险回复,最好把手从键盘上拿开。

      (有些人声称多数黑客有孤僻症或者社交障碍综合征的轻度症状,而且确实缺少部分有助
      “常人”进行社交行为的脑组织结构。这也许是真的,也许不是。如果你自己不是黑客,
      那么,把我们想象成脑部有缺陷的人有助你面对我们的古怪。有话直说,我们无所谓;我
      们乐于按自己的想法生活,而且总是对医学概念持相当怀疑的态度。)

      在下一节里,我们将谈论另一个话题;当你行差踏错时可能遇到的“无礼”。

      ================
      决不要象个失败者
      ================

      很有可能,你在黑客社区的论坛会受到很多公开的攻击--用本文提到的各种方式或类似的
      方法,而且很可能会有各式各样的旁敲侧击来告诉你你有多讨厌。

      如果噩梦成真,你能做的最糟的事就是为此发牢骚,抱怨受到人身攻击,要求对方道歉,
      尖叫,屏住呼吸,威胁要控诉对方,向他老板告状,不掀起马桶座圈,等等等等。然而,
      你应该这样:

      由它去吧,这没什么大不了的。实际上这么做是恰当的和有益的(主要是有利身心健
      康:)。

      社区的规范不靠社区,而是靠积极推行它们的人们来维护,这种维护是公开的,显而易见
      的。别抱怨说一切批评都应该通过私信传送,它本来就不该那样。当别人指出你的话有错
      误,或者他有不同观点的时候,坚持认为他在羞辱你是没有用的。这些都是失败者的态
      度。

      有那么一些黑客论坛,出于对高度自谦的误解,禁止参与者张贴专给人找茬的帖子,而且
      被告知“如果不愿帮助用户,那就闭嘴。”,他们认为,引开参与者的话题,只会使得他
      们陶醉在毫无意义的喋喋不休中,从而失去了技术论坛的意义。

      夸张的“友善”(以那种方式)还是有用的帮助:你自己选择吧。

      记住:当黑客说你很烦人,(无论用多么粗暴的语言)警告你别再那样做了,他的本意并
      非是针对(1)你,以及(2)他的社区。他本来可以轻易的忽略你,把你从他的视线中抹去。
      如果你无法接受要向他表示感激,至少应该表现出你的气度,别抱怨,别期望只因为你是
      新人,你有戏剧般的敏感脆弱的神经和自封的权利,而受到易碎玩偶般的特别对待。

      ==========
      三思而后问
      ==========

      以下是几个经典蠢问题,以及黑客在拒绝回答时的心中所想:

      问题:我能在哪找到X程序?
      问题:我的程序/配置/SQL申明没有用
      问题:我的Windows有问题,你能帮我吗?
      问题:我在安装Linux(或者X)时有问题,你能帮我吗?
      问题:我怎么才能破解root帐号/窃取OP特权/读别人的邮件呢?

      提问:我能在哪找到X程序?
      回答:就在我找到它的地方啊蠢货--搜索引擎的那一头。天呐!还有人不会用Google吗?


      提问:我的程序(配置、SQL申明)没有用
      回答:这不算是问题吧,我对找出你的真正问题没兴趣--如果要我问你二十个问题才找得
      出来的话--我有更有意思的事要做呢。在看到这类问题的时候,我的反应通常不外如下三
      种:
      1. 你还有什么要补充的吗?
      2. 真糟糕,希望你能搞定。
      3. 这跟我有什么鸟相关?

      提问:我的Windows有问题,你能帮我吗?
      回答:能啊,扔掉萎软的垃圾,换Linux吧。

      提问:我在安装Linux(或者X)时有问题,你能帮我吗?
      回答:不能,我只有亲自在你的电脑上动手才能找到毛病。还是去找你当地的Linux用户
      组寻求手把手的指导吧(你能在这儿找到用户组的清单)。

      提问:我怎么才能破解root帐号/窃取OP特权/读别人的邮件呢?
      回答:想要这样做,说明你是个卑鄙小人;想找个黑客帮你,说明你是个白痴!

      ==============
      好问题,坏问题
      ==============

      最后,我举一些例子来说明,怎样聪明的提问;同一个问题的两种问法被放在一起,一种
      是愚蠢的,另一种才是明智的。

      蠢问题:我可以在哪儿找到关于Foonly Flurbamatic的资料?
      这种问法无非想得到“STFW”这样的回答。

      聪明问题:我用Google搜索过“Foonly Flurbamatic 2600”,但是没找到有用的结
      果。谁知道上哪儿去找对这种设备编程的资料?
      这个问题已经STFW过了,看起来他真的遇到了麻烦。

      蠢问题:我从FOO项目找来的源码没法编译。它怎么这么烂?
      他觉得都是别人的错,这个傲慢自大的家伙

      聪明问题:FOO项目代码在Nulix 6.2版下无法编译通过。我读过了FAQ,但里面没有提到
      跟Nulix有关的问题。这是我编译过程的记录,我有什么做得不对的地方吗?
      他讲明了环境,也读过了FAQ,还指明了错误,并且他没有把问题的责任推到别人头上,
      这个家伙值得留意。

      蠢问题:我的主板有问题了,谁来帮我?
      普通黑客对这类问题的回答通常是:“好的,还要帮你拍拍背和换尿布吗?” ,然后按
      下删除键。

      聪明问题:我在S2464主板上试过了X、Y和Z,但没什么作用,我又试了A、B和C。请注意
      当我尝试C时的奇怪现象。显然边带传输中出现了收缩,但结果出人意料。在多处理器主
      板上引起边带泄漏的通常原因是什么?谁有好主意接下来我该做些什么测试才能找出问
      题?
      这个家伙,从另一个角度来看,值得去回答他。他表现出了解决问题的能力,而不是坐等
      天上掉答案。

      在最后一个问题中,注意“告诉我答案”和“给我启示,指出我还应该做什么诊断工作”
      之间微妙而又重要的区别。

      事实上,后一个问题源自于2001年8月在Linux内核邮件列表上的一个真实的提问。我
      (Eric)就是那个提出问题的人。我在Tyan S2464主板上观察到了这种无法解释的锁定
      现象,列表成员们提供了解决那一问题的重要信息。

      通过我的提问方法,我给了大家值得玩味的东西;我让人们很容易参与并且被吸引进来。
      我显示了自己具备和他们同等的能力,邀请他们与我共同探讨。我告诉他们我所走过的弯
      路,以避免他们再浪费时间,这是一种对他人时间价值的尊重。

      后来,当我向每个人表示感谢,并且赞赏这套程序(指邮件列表中的讨论--译者注)运作
      得非常出色的时候,一个Linux内核邮件列表(lkml)成员表示,问题得到解决并非由于
      我是这个列表中的“名人”,而是因为我用了正确的方式来提问。

      我们黑客从某种角度来说是拥有丰富知识但缺乏人情味的家伙;我相信他是对的,如果我
      象个乞讨者那样提问,不论我是谁,一定会惹恼某些人或者被他们忽视。他建议我记下这
      件事,给编写这个指南的人一些指导。

      ================
      找不到答案怎么办
      ================

      如果仍得不到答案,请不要以为我们觉得无法帮助你。有时只是看到你问题的人不知道答
      案罢了。没有回应不代表你被忽视,虽然不可否认这种差别很难区分。


      总的说来,简单的重复张贴问题是个很糟的想法。这将被视为无意义的喧闹。

      你可以通过其它渠道获得帮助,这些渠道通常更适合初学者的需要。

      有许多网上的以及本地的用户组,由狂热的软件爱好者(即使他们可能从没亲自写过任何
      软件)组成。通常人们组建这样的团体来互相帮助并帮助新手。

      另外,你可以向很多商业公司寻求帮助,不论公司大还是小(Red Hat和LinuxCare就是
      两个最常见的例子)。别为要付费才能获得帮助而感到沮丧!毕竟,假使你的汽车发动机
      汽缸密封圈爆掉了--完全可能如此--你还得把它送到修车铺,并且为维修付费。就算软件
      没花费你一分钱,你也不能强求技术支持总是免费的。

      对大众化的软件,就象Linux之类而言,每个开发者至少会有上万名用户。根本不可能由
      一个人来处理来自上万名用户的求助电话。要知道,即使你要为帮助付费,同你必须购买
      同类软件相比,你所付出的也是微不足道的(通常封闭源代码软件的技术支持费用比开放
      源代码软件要高得多,而且内容也不那么丰富)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP