??xml version="1.0" encoding="utf-8" standalone="yes"?>久久国产一片免费观看,日本人妻丰满熟妇久久久久久,久久九九兔免费精品6http://www.shnenglu.com/elva/category/4331.htmlzh-cnSat, 18 Feb 2012 12:08:00 GMTSat, 18 Feb 2012 12:08:00 GMT60Ubuntu 更新源签名错?–BADSIG 40976EAF437D05B5http://www.shnenglu.com/elva/archive/2012/02/18/165876.html叶子叶子Fri, 17 Feb 2012 19:10:00 GMThttp://www.shnenglu.com/elva/archive/2012/02/18/165876.htmlhttp://www.shnenglu.com/elva/comments/165876.htmlhttp://www.shnenglu.com/elva/archive/2012/02/18/165876.html#Feedback0http://www.shnenglu.com/elva/comments/commentRss/165876.htmlhttp://www.shnenglu.com/elva/services/trackbacks/165876.html

Ubuntu 更新源签名错?–BADSIG 40976EAF437D05B5

2011-02-19 xiao H Posted in pȝ理

错误提示Q?/p>

GPG 错误Qhttp://mirrors.163.com maverick-updates Release: 下列{֐无效Q?BADSIG 40976EAF437D05B5 Ubuntu Archive Automatic Signing Key <ftpmaster @ubuntu.com> </ftpmaster>

修复Ҏ(gu)
gpg --keyserver keyserver.ubuntu.com --recv 40976EAF437D05B5 gpg --export --armor 40976EAF437D05B5 | sudo apt-key add -

上面的方法不行可以试试下面这?/p>

sudo aptitude -o Acquire::http::No-Cache=True -o Acquire::BrokenProxy=true update

l极大法

sudo apt-get clean cd /var/lib/apt sudo mv lists lists.old sudo mkdir -p lists/partial sudo apt-get clean sudo apt-get update

以上Ҏ(gu)来自Q?/p>

http://forum.ubuntu.org.



转自Q?br />
http://www.linuxbyte.org/ubuntu-geng-xin-yuan-qian-ming-cuo-wu-badsig-40976eaf437d05b5.html


叶子 2012-02-18 03:10 发表评论
]]>
Linux无法dQ显Cmodule is unknownhttp://www.shnenglu.com/elva/archive/2012/01/06/163709.html叶子叶子Fri, 06 Jan 2012 04:35:00 GMThttp://www.shnenglu.com/elva/archive/2012/01/06/163709.htmlhttp://www.shnenglu.com/elva/comments/163709.htmlhttp://www.shnenglu.com/elva/archive/2012/01/06/163709.html#Feedback0http://www.shnenglu.com/elva/comments/commentRss/163709.htmlhttp://www.shnenglu.com/elva/services/trackbacks/163709.html今天在配|Oracle安装环境Ӟ更改了一些系l参敎ͼ注销重新d时发现即使输入正的用户名和密码Q也无法dQ在按回车的那一瞬间可以看到密码下方有一行快速闪q的提示“module is unknown”。不解何意?

    本h的系l默认是命o行界面启动的。于是重启以RunLevel 5q入囑Ş界面。发现图形界面可以正常进入。下面就查询日志吧:

   1:  # cd /var/log/
   2:  #cat security 

在日志文件中Q我看到了如下信息:

PAM unable to dlopen(/lib/security/pam_limits.so)

PAM [error: /lib/security/pam_limits.so: wrong ELF class: ELFCLASS32]

PAM adding faulty module: /lib/security/pam_limits.so

pam_unix(login:session): session opened for user Oracle by LOGIN(uid=0)

Module is unknown

看到q里Q我惌v我在/etc/pam.d/login中加入了:

session required /lib/security/pam_limits.so

session required pam_limits.so

两条配置语句。根据日志信息以上Login上的其他配置信息Q将W一条语句注释掉Q?br />

#session required /lib/security/pam_limits.so

session required pam_limits.so

重启Q登录,一切正常。问题解冟?/p>

########################更新##########################33

以上问题的出现是׃操作pȝ的问题。我本想安装32位centosQ结果错手拿了一?4bit Centos安装Q然后按?2位的配置q行了配|。正配|在64位下应ؓQ?/p>

   1:  session required /lib64/security/pam_limits.so
   2:   
   3:  session required pam_limits.so


转自Q?div>http://www.zhaofengcao.com/archives/138

叶子 2012-01-06 12:35 发表评论
]]>
/dev/sdc is apparently in use by the system; will not make a filesystem here! http://www.shnenglu.com/elva/archive/2011/11/22/160717.html叶子叶子Tue, 22 Nov 2011 08:20:00 GMThttp://www.shnenglu.com/elva/archive/2011/11/22/160717.htmlhttp://www.shnenglu.com/elva/comments/160717.htmlhttp://www.shnenglu.com/elva/archive/2011/11/22/160717.html#Feedback0http://www.shnenglu.com/elva/comments/commentRss/160717.htmlhttp://www.shnenglu.com/elva/services/trackbacks/160717.htmlRe: /dev/sdc is apparently in use by the system; will not make a filesystem here!
Quote:
Originally Posted by abriejo View Post
Hi

I was about to try the CD startup when I tried one last thing again.

sudo mdadm --stop /dev/md0

It worked, but I find it strange because I did it before and md0 did not appear in the fdisk -l screen.

Immdiately after that I was able to run the sudo mkfs.ext3 /dev/sdc


Maybe it is because I ran the zero-superblock tasks overnight - something that made me nervous, since I have no idea what it does.

Than You for your help!

It worked for me. Thanks!


叶子 2011-11-22 16:20 发表评论
]]>
Linux Signalshttp://www.shnenglu.com/elva/archive/2010/08/11/123050.html叶子叶子Wed, 11 Aug 2010 04:12:00 GMThttp://www.shnenglu.com/elva/archive/2010/08/11/123050.htmlhttp://www.shnenglu.com/elva/comments/123050.htmlhttp://www.shnenglu.com/elva/archive/2010/08/11/123050.html#Feedback0http://www.shnenglu.com/elva/comments/commentRss/123050.htmlhttp://www.shnenglu.com/elva/services/trackbacks/123050.htmlSignals

Linux Signals are:

Signal Name Number Description
SIGHUP 1 Hangup (POSIX)
SIGINT 2 Terminal interrupt (ANSI)
SIGQUIT 3 Terminal quit (POSIX)
SIGILL 4 Illegal instruction (ANSI)
SIGTRAP 5 Trace trap (POSIX)
SIGIOT 6 IOT Trap (4.2 BSD)
SIGBUS 7 BUS error (4.2 BSD)
SIGFPE 8 Floating point exception (ANSI)
SIGKILL 9 Kill(can't be caught or ignored) (POSIX)
SIGUSR1 10 User defined signal 1 (POSIX)
SIGSEGV 11 Invalid memory segment access (ANSI)
SIGUSR2 12 User defined signal 2 (POSIX)
SIGPIPE 13 Write on a pipe with no reader, Broken pipe (POSIX)
SIGALRM 14 Alarm clock (POSIX)
SIGTERM 15 Termination (ANSI)
SIGSTKFLT 16 Stack fault
SIGCHLD 17 Child process has stopped or exited, changed (POSIX)
SIGCONT 18 Continue executing, if stopped (POSIX)
SIGSTOP 19 Stop executing(can't be caught or ignored) (POSIX)
SIGTSTP 20 Terminal stop signal (POSIX)
SIGTTIN 21 Background process trying to read, from TTY (POSIX)
SIGTTOU 22 Background process trying to write, to TTY (POSIX)
SIGURG 23 Urgent condition on socket (4.2 BSD)
SIGXCPU 24 CPU limit exceeded (4.2 BSD)
SIGXFSZ 25 File size limit exceeded (4.2 BSD)
SIGVTALRM 26 Virtual alarm clock (4.2 BSD)
SIGPROF 27 Profiling alarm clock (4.2 BSD)
SIGWINCH 28 Window size change (4.3 BSD, Sun)
SIGIO 29 I/O now possible (4.2 BSD)
SIGPWR 30 Power failure restart (System V)

As noted above, processes can ignore, block, or catch all signals except SIGSTOP and SIGKILL. If a process catches a signal, it means that it includes code that will take appropriate action when the signal is received. If the signal is not caught by the process, the kernel will take default action for the signal.

FIFOs

FIFOs are permanent objects and can be created using the mkfifo(1) or mknod(1) command. Inside the program, the FIFO can be created using the mknod command, then opened and read from or written to just like a normal file. The FIFO is normally in blocking mode when attempting to perform read operations.


引用自:http://www.comptechdoc.org/os/linux/programming/linux_pgsignals.html



在终端用kill -l 命o可以昄所有的信号?br> $kill -l
1) SIGHUP
2) SIGINT 3) SIGQUIT 4) SIGILL
5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE
9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2
13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT
17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU
25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH
29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN
35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4
39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12
47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14
51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10
55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6
59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX

其中前面31个信号ؓ不可靠信?非实时的Q可能会出现信号的丢?Q后面的信号为可靠信?实时的real_time,对信?br> 排队Q不会丢??/strong>

1) SIGHUP (挂v) 当运行进E的用户注销旉知该进E,使进E终?/strong>

2) SIGINT (中断) 当用h下时,通知前台q程l终止进E?/strong>

3) SIGQUIT (退? 用户按下或时通知q程Qɘq程l止

4) SIGILL (非法指o) 执行了非法指令,如可执行文g本n出现错误、试图执行数据段、堆栈溢?/strong>

5) SIGTRAP 由断Ҏ(gu)令或其它trap指o产生. 由debugger使用

6) SIGABRT (异常中止) 调用abort函数生成的信?/strong>

7) SIGBUS 非法地址, 包括内存地址寚w(alignment)出错. eg: 讉K一个四个字长的整数, 但其地址不是4的倍数.

8) SIGFPE (术异常) 发生致命术q算错误,包括点q算错误、溢出及除数?.

9) SIGKILL (认杀? 当用户通过kill -9命o向进E发送信hQ可靠的l止q程

10) SIGUSR1 用户使用

11) SIGSEGV (D越? 当进E尝试访问不属于自己的内存空间导致内存错误时Q终止进E?/strong>

12) SIGUSR2 用户使用

13) SIGPIPE 写至无读q程的管? 或者Socket通信SOCT_STREAM的读q程已经l止Q而再写入?/strong>

14) SIGALRM (时) alarm函数使用该信P旉定时器超时响?/strong>

15) SIGTERM (软中? 使用不带参数的kill命o时终止进E?/strong>

17) SIGCHLD (子进E结? 当子q程l止旉知父进E?/strong>

18) SIGCONT (暂停q程l箋) 让一个停?stopped)的进El执? 本信号不能被d.

19) SIGSTOP (停止) 作业控制信号,暂停停止(stopped)q程的执? 本信号不能被d, 处理或忽?

20) SIGTSTP (暂停/停止) 交互式停止信? Ctrl-Z 发出q个信号

21) SIGTTIN 当后C业要从用L(fng)端读数据? l端驱动E序产生SIGTTIN信号

22) SIGTTOU 当后C业要往用户l端写数据时, l端驱动E序产生SIGTTOU信号

23) SIGURG ?紧?数据或网l上带外数据到达socket时?

24) SIGXCPU 过CPU旉资源限制. q个限制可以由getrlimit/setrlimit来读?改变?/strong>

25) SIGXFSZ 当进E企图扩大文件以至于过文g大小资源限制?/strong>

26) SIGVTALRM 虚拟旉信号. cM于SIGALRM, 但是计算的是该进E占用的CPU旉.

27) SIGPROF (梗概旉时) setitimer(2)函数讄的梗概统计间隔计时器(profiling interval timer)

28) SIGWINCH H口大小改变时发?

29) SIGIO(异步I/O) 文g描述W准备就l? 可以开始进行输?输出操作.

30) SIGPWR 甉|失效/重启?/strong>

31) SIGSYS 非法的系l调用?/strong>

在以上列出的信号中,
E序不可捕获、阻塞或忽略的信hQSIGKILL,SIGSTOP
不能恢复至默认动作的信号有:SIGILL,SIGTRAP
默认会导致进E流产的信号有:SIGABRT,SIGBUS,SIGFPE,SIGILL,SIGIOT,SIGQUIT,SIGSEGV,SIGTRAP,SIGXCPU,SIGXFSZ
默认会导致进E退出的信号有:SIGALRM,SIGHUP,SIGINT,SIGKILL,SIGPIPE,SIGPOLL,SIGPROF,SIGSYS,SIGTERM,SIGUSR1,SIGUSR2,SIGVTALRM
默认会导致进E停止的信号有:SIGSTOP,SIGTSTP,SIGTTIN,SIGTTOU
默认q程忽略的信hQSIGCHLD,SIGPWR,SIGURG,SIGWINCH

此外QSIGIO在SVR4是退出,?.3BSD中是忽略QSIGCONT在进E挂h是l,否则是忽略,不能被阻塞?/strong>

在Unix/Linux中signal函数是比较复杂的一?其定义原型如?
void (*signal(int signo,void (*func)(int))) (int)
q个函数?最外层的函C
void (* XXX )(int)表明是一个指?指向一个函数XXX的指?XXX所代表的函数需要一个int型的参数,q回void
signal(int signo, void(*func)(int))是signal函数的主?
需要两个参数int型的signo以及一个指向函数的函数.
void (*func)(int).
正是׃其复杂?在[Plauger 1992]用typedef来对其进行简?br> typedef void Sigfuc(int);//q里可以看成一个返回?.
再对signal函数q行化就是这L(fng)?br> Sigfunc *signal(int,Sigfuc *);


在signal.h头文件中q有以下几个定义
#define SIG_ERR (void (*)())-1
#define SIG_DFL (void (*)())0
#define SIG_IGN (void (*)())1


本文来自CSDN博客Q{载请标明出处Q?/strong> http://blog.csdn.net/nevercgoodbye/archive/2008/11/25/3367853.aspx





叶子 2010-08-11 12:12 发表评论
]]>
gdb多线E调?http://www.shnenglu.com/elva/archive/2010/08/02/121940.html叶子叶子Mon, 02 Aug 2010 03:41:00 GMThttp://www.shnenglu.com/elva/archive/2010/08/02/121940.htmlhttp://www.shnenglu.com/elva/comments/121940.htmlhttp://www.shnenglu.com/elva/archive/2010/08/02/121940.html#Feedback0http://www.shnenglu.com/elva/comments/commentRss/121940.htmlhttp://www.shnenglu.com/elva/services/trackbacks/121940.html

gdb对于多线E程序的调试有如下的支持Q?br>  
  U程产生通知Q在产生新的U程? gdb会给出提CZ?br>  (gdb) r
  Starting program: /root/thread 
  [New Thread 1073951360 (LWP 12900)] 
  [New Thread 1082342592 (LWP 12907)]---以下三个为新产生的线E?br>  [New Thread 1090731072 (LWP 12908)]
  [New Thread 1099119552 (LWP 12909)]
  
  查看U程Q用info threads可以查看q行的线E?br>  (gdb) info threads
   4 Thread 1099119552 (LWP 12940) 0xffffe002 in ?? ()
   3 Thread 1090731072 (LWP 12939) 0xffffe002 in ?? ()
   2 Thread 1082342592 (LWP 12938) 0xffffe002 in ?? ()
  * 1 Thread 1073951360 (LWP 12931) main (argc=1, argv=0xbfffda04) at thread.c:21
  (gdb) 
  
  
  注意Q行首的蓝色文字为gdb分配的线E号Q对U程q行切换Ӟ使用该该L(fng)Q而不是上文标出的l色数字?br>  
  另外Q行首的U色星号标识了当前活动的U程
  
  切换U程Q?thread THREADNUMBER q行切换QTHREADNUMBER Z文提到的U程受下例显C将zdU程?1 切换?4?br>  (gdb) info threads
   4 Thread 1099119552 (LWP 12940) 0xffffe002 in ?? ()
   3 Thread 1090731072 (LWP 12939) 0xffffe002 in ?? ()
   2 Thread 1082342592 (LWP 12938) 0xffffe002 in ?? ()
  * 1 Thread 1073951360 (LWP 12931) main (argc=1, argv=0xbfffda04) at thread.c:21
  (gdb) thread 4
  [Switching to thread 4 (Thread 1099119552 (LWP 12940))]#0 0xffffe002 in ?? ()
  (gdb) info threads
  * 4 Thread 1099119552 (LWP 12940) 0xffffe002 in ?? ()
   3 Thread 1090731072 (LWP 12939) 0xffffe002 in ?? ()
   2 Thread 1082342592 (LWP 12938) 0xffffe002 in ?? ()
   1 Thread 1073951360 (LWP 12931) main (argc=1, argv=0xbfffda04) at thread.c:21
  (gdb) 
  
  
   以上即ؓ使用gdb提供的对多线E进行调试的一些基本命令。另外,gdb也提供对U程的断点设|以及对指定或所有线E发布命令的命o?br>  
   初次接触gdb下多U程的调试,往往会忽视gdb中活动线E的概念。一般来Ԍ在用gdb调试的时候,只有一个线EؓzdU程Q如果希望得到其他的U程的输出结果,必须使用thread命o切换x定的U程Q才能对该线E进行调试或观察输出l果?/p>


叶子 2010-08-02 11:41 发表评论
]]>
time命o详解http://www.shnenglu.com/elva/archive/2009/09/21/96829.html叶子叶子Mon, 21 Sep 2009 02:43:00 GMThttp://www.shnenglu.com/elva/archive/2009/09/21/96829.htmlhttp://www.shnenglu.com/elva/comments/96829.htmlhttp://www.shnenglu.com/elva/archive/2009/09/21/96829.html#Feedback0http://www.shnenglu.com/elva/comments/commentRss/96829.htmlhttp://www.shnenglu.com/elva/services/trackbacks/96829.html

【命令】time ?执行命oq计?/span>

【格式】time [-p] command [arguments...]

【说明?/span>

执行命o?command [arguments...]"Q命令行执行l束时在标准输出中打印执行该命o行的旉l计l果Q其l计l果包含以下数据Q?/font>

1)实际旉(real time): 从command命o行开始执行到q行l止的消逝时_

2)用户CPU旉(user CPU time): 命o执行完成p的用户CPU旉Q即命o在用h中执行旉dQ?/font>

3)pȝCPU旉(system CPU time): 命o执行完成p的系lCPU旉Q即命o在核心态中执行旉d?/font>

其中Q用户CPU旉和系lCPU旉之和为CPU旉Q即命o占用CPU执行的时间d。实际时间要大于CPU旉Q因为Linux是多d操作pȝQ往往在执行一条命令时Q系l还要处理其它Q务?/font>

另一个需要注意的问题是即使每ơ执行相同命令,但所p的时间也是不一P其花Ҏ(gu)间是与系l运行相关的?/font>

?Q?/font>

           1. # time date
             2. Sun Mar 26 22:45:34 GMT-8 2006
             3. 
             4. real    0m0.136s
             5. user    0m0.010s
             6. sys     0m0.070s
             7. #

在例1中,执行命o"time date"(见第1?。系l先执行命o"date"Q第2行ؓ命o"date"的执行结果。第3-6行ؓ执行命o"date"的时间统计结果,其中W? ?real"为实际时_W??user"为用户CPU旉Q第6?sys"为系lCPU旉。以上三U时间的昄格式均ؓ MMmNN[.FFF]s?/font>

在例1中,CPU旉 = 用户CPU旉 + pȝCPU旉 = 0m0.010s + 0m0.070s = 0m0.080sQ实际时间大于CPU旉Q说明在date命oq行的同Ӟq有其它d在运行?/font>

【参数说明?/span>

-p 以POSIX~省的时间格式打印时间统计结果,单位为秒。详l的输出格式见例2?/font>

?Q?/font>

            1. # time -p date
             2. Wed Mar 27 00:33:11 GMT-8 2006
             3. real 0.11
             4. user 0.00
             5. sys 0.02
             6. #

在例2中,同样执行命o"time date"(见第1?。系l先执行命o "date"Q第2行ؓ该命令的执行l果。第3-5行ؓ执行命o"date"的时间统计结果。注意本例的旉格式与例1中的旉格式差别Q?p 参数后的旉昄格式为NN.FFQ其单位为秒?/font>

【相关环境变量说明?/span>

TIMEFORMAT 自定义输出的旉格式?/font>

我们也可以通过环境变量TIMEFORMAT来自定义输出的时间格式[1]。格式中使用和标准C中的函数printf一致的转义W,以及使用以下的{义序列来指定输出的时间格式:

&lt;font size=&quot;3&quot;&gt; %[prec][l][RUS]&lt;br&gt;&lt;/font&gt;

其中Q选项prec为指定时间精度,卛_数点后面的位敎ͼ选项l表示使用分秒(具体格式为:MMmNN[.FFF]s)的格式;最后一个字W表C时间的cdQ其中R表示实际旉QU表示用户CPU旉QS表示pȝCPU 旉Q它们的单位均ؓU?/font>

time命o~省输出的时间格式同 TIMEFORMAT=$'\nreal\t%3lR\nuser\t%3lU\nsys\t%3lS'?/font>

使用-p参数的time命o输出的时间格式同 TIMEFORMAT=$'real %2R\nuser %2U\nsys %2S'?/font>

?Q?/font>

             1. # export TIMEFORMAT=$'real %2R\nuser %2U\nsys %2S'
             2. # time date
             3. Wed Mar 27 00:52:03 GMT-8 2006
             4. real 0.04
             5. user 0.00
             6. sys 0.01
             7. #

比较?和例3昄l果Q很Ҏ(gu)发现?虽然没有使用参数-pQ但其输出的l果和例2一模一栗?/font>

当然Q我们也可以修改ZQ何自己喜Ƣ的旉格式?/font>

?Q?/font>

             1. # export TIMEFORMAT=$'\nHello, ThinkerABC!\nreal time :       %lR\nuser CUP time :   %lU\nsystem CPU time : %lS'
             2. # time date
             3. Wed Mar 27 01:09:26 GMT-8 2006
             4.
             5. Hello, ThinkerABC!
             6. real time :       0m0.016s
             7. user CUP time :   0m0.006s
             8. system CPU time : 0m0.008s
             9. #

?的第4-8行正是我们自定义的输出格式?/font>

从以上介l了三种指定旉格式的方法,即缺省的旉格式、用参?p的POSIX~省的时间格式和讑֮环境变量TIMEFORMAT自定义的旉格式QLinuxpȝ使用的先后顺序如下:

1.参数-p的POSIX~省旉格式Q?/font>

2.环境变量TIMEFORMAT自定义的旉格式Q?/font>

3.~省的时间格式?/font>

【退出状态说明?/span>

如果能执行command命oQ则q回该命令的退出状态,否则q回如下的退出状态|

127 命o未找?/font>

126 命o扑ֈQ但不能执行

1-125 其它错误



叶子 2009-09-21 10:43 发表评论
]]>
在Debian中打造属于自qdeb?/title><link>http://www.shnenglu.com/elva/archive/2009/08/25/94373.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Tue, 25 Aug 2009 08:03:00 GMT</pubDate><guid>http://www.shnenglu.com/elva/archive/2009/08/25/94373.html</guid><wfw:comment>http://www.shnenglu.com/elva/comments/94373.html</wfw:comment><comments>http://www.shnenglu.com/elva/archive/2009/08/25/94373.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/elva/comments/commentRss/94373.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/elva/services/trackbacks/94373.html</trackback:ping><description><![CDATA[     摘要: 问题Q如果你要在Debianpȝ中发布一ƾY件或者一个包Q该如何做呢Q如果你的项目中有各U二q制包,该如何维护呢Q如果你自己做了一Ƒְ的实用软gQ该如何与朋友分享呢Q?#8230;….    案例Q假如我从网上下载了eclipse-SDK-3.1-linux-gtk.tar.gz压羃文gQ我x他安装到/opt/eclipse目录下,且菜单Apps-->...  <a href='http://www.shnenglu.com/elva/archive/2009/08/25/94373.html'>阅读全文</a><img src ="http://www.shnenglu.com/elva/aggbug/94373.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/elva/" target="_blank">叶子</a> 2009-08-25 16:03 <a href="http://www.shnenglu.com/elva/archive/2009/08/25/94373.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> [Pthread] LinuxE序调试的基??--Inside GDB http://www.shnenglu.com/elva/archive/2009/07/25/91148.html叶子叶子Sat, 25 Jul 2009 09:56:00 GMThttp://www.shnenglu.com/elva/archive/2009/07/25/91148.htmlhttp://www.shnenglu.com/elva/comments/91148.htmlhttp://www.shnenglu.com/elva/archive/2009/07/25/91148.html#Feedback0http://www.shnenglu.com/elva/comments/commentRss/91148.htmlhttp://www.shnenglu.com/elva/services/trackbacks/91148.htmlGDB是GNU发布的一个强大的E序调试工具Q用以调试C/C++E序。可以ɽE序员在E序q行的时候观察程序在内存/寄存器中的用情c它的实C是基于ptracepȝ调用来完成的?br>? 原理是利用ptracepȝ调用Q在被调试程序和gdb之间建立跟踪关系。然后所有发送给被调试程序的信号(除SIGKILL)都会被gdb截获Qgdb Ҏ(gu)截获的信P查看被调试程序相应的内存地址Qƈ控制被调试的E序l箋q行。GDB常用的用方法有断点讄和单步跟t,接下来我们来分析一下他们是? 何实现的?br>
3.1 建立调试关系
用gdb调试E序Q可以直接gdb ./test,也可以gdb <pid>(test的进E号)。这对应着使用ptrace建立跟踪关系的两U方?
1)fork: 利用fork+execve执行被测试的E序Q子q程在执行execve之前调用ptrace(PTRACE_TRACEME)Q徏立了与父q程(debugger)的跟t关pR如我们在分析strace时所C意的程序?br>2)attach: debugger可以调用ptrace(PTRACE_ATTACHQpid,...)Q徏立自׃q程号ؓpid的进E间的跟t关pR即利用 PTRACE_ATTACHQ自己变成被调试程序的父进E?用ps可以看到)。用attach建立h的跟t关p,可以调用ptrace (PTRACE_DETACHQpid,...)来解除。注意attachq程时的权限问题Q如一个非root权限的进E是不能attachC? rootq程上的?br>
3.2 断点原理
断点是大家在调试E序时常用的一个功?如break linenumberQ当执行到l(f)inenumber那一行的时候被调试E序会停止,{待debugger的进一步操作?
断点的实现原理,是在指定的位置插入断点指oQ当被调试的E序q行到断点的时候,产生SIGTRAP信号。该信号被gdb捕获q进行断点命中判定,当gdb判断ơSIGTRAP是断点命中之后就会{入等待用戯入进行下一步处理,否则l箋?br>断点的设|原? 在程序中讄断点Q就是先该位置的原来的指o保存Q然后向该位|写入int 3。当执行到int 3的时候,发生软中断,内核会给子进E发出SIGTRAP信号Q当然这个信号会被{发给父进E。然后用保存的指令替换int3,{待恢复q行?br>断点命中判定:gdb把所有的断点位置都存攑֜一个链表中Q命中判定即把被调试E序当前停止的位|和链表中的断点位置q行比较Q看是断点生的信号Q还是无关信受?br>
3.3 单步跟踪原理
单步跟踪是指在调试E序的时候,让程序运行一条指?语句后就停下。GDB中常用的命o有next, step, nexti, stepi。单步跟t又常分句单?next, step)和指令单?如nexti, stepi)?br>
在linux上,指o单步可以通过ptrace来实现。调用ptrace(PTRACE_SINGLESTEP,pid,...)可以使被调试的进E在每执行完一条指令后p发一个SIGTRAP信号Q让GDBq行。下面来看一个例?
    child = fork();
    if(child == 0) {
         execl("./HelloWorld", "HelloWorld", NULL);
    }
    else {
        ptrace(PTRACE_ATTACH,child,NULL,NULL);
        while(1){
        wait(&val);
        if(WIFEXITED(val))
            break;
        count++;
        ptrace(PTRACE_SINGLESTEP,child,NULL,NULL);
        }
    printf("Total Instruction number= %d\n",count);
    }
q? D늨序比较简单,子进E调用execve执行HelloWorld,而父q程则先调用ptrace(PTRACE_ATTACH,pid,...)建立? 子进E的跟踪关系。然后调用ptrace(PTRACE_SINGLESTEP, pid, ...)让子q程一步一停,以统计子q程一共执行了多少条指?你会发现一个简单的HelloWorld实际上也执行了好几万条指令才完成)。当然你也完 全可以在q个时候查看EIP寄存器中存放的指令,或者某个变量的|当然前提是你得知道这个变量在子进E内存镜像中的位|?br>指o单步可以依靠g 完成Q如x86架构处理器支持单步模?通过讄EFLAGS寄存器的TF标志实现)Q每执行一条指令,׃产生一ơ异?在Intel 80386以上的处理器上还提供了DRx调试寄存器以用于软g调试)。也可以通过软g完成Q即在每条指令后面都插入一条断Ҏ(gu)令,q样每执行一条指令都? 产生一ơY中断?br>语句单步Z指o单步实现Q即GDB好每条语句所对应的指令,从什么地方开始到什么地方结束。然后在l束的地Ҏ(gu)入断点,或者指令单步一步一步的走到l束点,再进行处理?br>
? 然gdb的实现远比今天我们所说的内容要复杂,它能让我们很Ҏ(gu)的监,修改被调试的q程Q比如通过行号Q函数名Q变量名。而要真正实现q些Q一是需要在 ~译的时候提供够的信息Q如在gcc时加?g选项Q这样gcc会把一些程序信息放到生成的ELF文g中,包括函数W号表,行号Q变量信息,宏定义等Q? 以便日后gdb调试Q当然生成的文g也会大一些。二是需要我们对ELF文g格式Q进E的内存镜像(布局)以及E序的指令码十分熟?zhn)。这h能保证在正确? 时机(断点发生Q单步?)扑ֈ正确的内存地址(代码Q数据?)q接回正确的程序代?q是哪个变量Q程序第几行Q?。感兴趣的同学可以找到相应的代码? l分析一下?br>
结:
ptrace可以实时监测和修改另一个进E的q行Q它是如此的强大以至于曾l因为它在unix-likeq_ (如Linux, *BSD)上生了各种漏洞。但换言之,只要我们能掌握它的用,p开发出很多以前在用h下不可能实现的应用。当然这可能需要我们掌握编译,文g? 式,E序内存布局{相当多的底层知识?br>
最后让我们来回一下ptrace的?
1)用PTRACE_ATTACH或者PTRACE_TRACEME 建立q程间的跟踪关系?br>2)PTRACE_PEEKTEXT, PTRACE_PEEKDATA, PTRACE_PEEKUSR{读取子q程内存/寄存器中保留的倹{?br>3)PTRACE_POKETEXT, PTRACE_POKEDATA, PTRACE_POKEUSR{把值写入到被跟t进E的内存/寄存器中?br>4)用PTRACE_CONTQPTRACE_SYSCALL, PTRACE_SINGLESTEP控制被跟t进E以何种方式l箋q行?br>5)PTRACE_DETACH, PTRACE_KILL qq程间的跟踪关系?br>
TIPS:
    1. q程状态TASK_TRACED用以表示当前q程因ؓ被父q程跟踪而被pȝ停止?br>    2. 如在子进E结束前Q父q程l束Q则trace关系解除?br>    3. 利用attach建立h的跟t关p,虽然ps看到双方为父子关p,但在"子进E?中调用getppid()仍会q回原来的父q程id?br>    4. 不能attach到自׃能跟t的q程Q如non-rootq程跟踪rootq程?br>    5. 已经被trace的进E,不能再次被attach?br>    6. 即是用PTRACE_TRACEME建立h的跟t关p,也可以用DETACH的方式予以解除?br>    7. 因ؓq入/退出系l调用都会触发一ơSIGTRAPQ所以通常的做法是在第一?q入)的时候读取系l调用的参数Q在W二?退?的时候读取系l调用的q回倹{但注意execve是个例外?br>    8. E序调试时的断点由int 3讄完成Q而单步跟t则可由ptrace(PTRACE_SINGLESTEP)实现?br>   
Pthread 08/01/14

原文地址Qhttp://blog.csdn.net/Javadino/archive/2008/09/06/2891434.aspx


叶子 2009-07-25 17:56 发表评论
]]>
[Pthread] Linux上程序调试的基石(一)--ptracehttp://www.shnenglu.com/elva/archive/2009/07/25/91147.html叶子叶子Sat, 25 Jul 2009 09:55:00 GMThttp://www.shnenglu.com/elva/archive/2009/07/25/91147.htmlhttp://www.shnenglu.com/elva/comments/91147.htmlhttp://www.shnenglu.com/elva/archive/2009/07/25/91147.html#Feedback0http://www.shnenglu.com/elva/comments/commentRss/91147.htmlhttp://www.shnenglu.com/elva/services/trackbacks/91147.html1.在Linuxpȝ中,q程状态除了我们所熟知的TASK_RUNNINGQTASK_INTERRUPTIBLEQTASK_STOPPED{,q有一个TASK_TRACED。这表明q个q程处于什么状态?
2.strace可以方便的帮助我们记录进E所执行的系l调用,它是如何跟踪到进E执行的Q?br>3.gdb是我们调试程序的利器Q可以设|断点,单步跟踪E序。它的实现原理又是什么?

所有这一切的背后都隐藏着Linux所提供的一个强大的pȝ调用ptrace().

1.ptracepȝ调用
ptrace pȝ调从名字上看是用于进E跟t的Q它提供了父q程可以观察和控制其子进E执行的能力Qƈ允许父进E检查和替换子进E的内核镜像(包括寄存?的倹{其? 本原理是: 当用了ptrace跟踪后,所有发送给被跟t的子进E的信号(除了SIGKILL)Q都会被转发l父q程Q而子q程则会被阻塞,q时子进E的状态就会被 pȝ标注为TASK_TRACED。而父q程收到信号后,可以对停止下来的子q程q行查和修改Q然后让子进El运行?nbsp;   
    其原型ؓQ?nbsp;   
    #include <sys/ptrace.h>
    long ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data);
    ptrace有四个参?
    1). enum __ptrace_request requestQ指CZptrace要执行的命o?br>    2). pid_t pid: 指示ptrace要跟t的q程?br>    3). void *addr: 指示要监控的内存地址?br>    4). void *data: 存放d出的或者要写入的数据?br>ptrace是如此的强大Q以至于有很多大家所常用的工具都Zptrace来实玎ͼ如strace和gdb。接下来Q我们借由对strace和gdb的实玎ͼ来看看ptrace是如何用的?br>
2. strace的实?br>strace常常被用来拦截和记录q程所执行的系l调用,以及q程所收到的信受如有这么一D늨序:
HelloWorld.c:
#include <stdio.h>
int main(){
    printf("Hello World!\n");
    return 0;
}
~译后,用strace跟踪Q?strace ./HelloWorld
可以看到形如:
execve("./HelloWorld", ["./HelloWorld"], [/* 67 vars */]) = 0
brk(0)                                  = 0x804a000
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f18000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/home/supperman/WorkSpace/lib/tls/i686/sse2/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory)
...
的一D输出,q就是在执行HelloWorld中,pȝ所执行的系l调用,以及他们的返回倹{?br>
下面我们用ptrace来研I一下它是怎么实现的?br>...
    switch(pid = fork())
    {
    case -1:
        return -1;
    case 0: //子进E?br>        ptrace(PTRACE_TRACEME,0,NULL,NULL);
        execl("./HelloWorld", "HelloWorld", NULL);
    default: //父进E?br>        wait(&val); //{待q记录execve
        if(WIFEXITED(val))
            return 0;
        syscallID=ptrace(PTRACE_PEEKUSER, pid, ORIG_EAX*4, NULL);
        printf("Process executed system call ID = %ld\n",syscallID);
        ptrace(PTRACE_SYSCALL,pid,NULL,NULL);
        while(1)
        {
            wait(&val); //{待信号
            if(WIFEXITED(val)) //判断子进E是否退?br>                return 0;
            if(flag==0) //W一?q入pȝ调用)Q获取系l调用的参数
            {
                syscallID=ptrace(PTRACE_PEEKUSER, pid, ORIG_EAX*4, NULL);
                printf("Process executed system call ID = %ld ",syscallID);
                flag=1;
            }
            else //W二?退出系l调?Q获取系l调用的q回?br>            {
                returnValue=ptrace(PTRACE_PEEKUSER, pid, EAX*4, NULL);
                printf("with return value= %ld\n", returnValue);
                flag=0;
            }
            ptrace(PTRACE_SYSCALL,pid,NULL,NULL);
        }
    }
...

? 上面的程序中Qfork出的子进E先调用了ptrace(PTRACE_TRACEME)表示子进E让父进E跟t自己。然后子q程调用execl加蝲执行 了HelloWorld。而在父进E中则用waitpȝ调用{待子进E的状态改变。子q程因ؓ讄了PTRACE_TRACEME而在执行pȝ调用被系 l停?讄为TASK_TRACED)Q这时父q程被唤醒,使用ptrace(PTRACE_PEEKUSER,pid,...)分别去读取子q程执行 的系l调用ID(攑֜ORIG_EAX?以及pȝ调用q回时的?攑֜EAX?。然后用ptrace(PTRACE_SYSCALL, pid,...)指示子进E运行到下一ơ执行系l调用的时?q入或者退?Q直到子q程退Zؓ止?br>
E序的执行结果如?
Process executed system call ID = 11
Process executed system call ID = 45 with return value= 134520832
Process executed system call ID = 192 with return value= -1208934400
Process executed system call ID = 33 with return value= -2
Process executed system call ID = 5 with return value= -2
...
? 中,11L(fng)l调用就是execveQ?5hbrk,192是mmap2,33是access,5是open...l过比对可以发现Q和strace? 输出l果一栗当然straceq行了更详尽和完善的处理Q我们这里只是揭C其原理Q感兴趣的同学可以去研究一下strace的实现?br>
PS:
    1). 在系l调用执行的时候,会执行pushl %eax # 保存pȝ调用号ORIG_EAX在程序用h中?br>    2). 在系l调用返回的时候,会执行movl %eax,EAX(%esp)系l调用的q回值放入寄存器%eax中?br>    3). WIFEXITED()宏用来判断子q程是否为正帔R出的Q如果是Q它会返回一个非零倹{?br>    4). 被跟t的E序在进入或者退出某ơ系l调用的时候都会触发一个SIGTRAP信号Q而被父进E捕莗?br>    5). execve()pȝ调用执行成功的时候ƈ没有q回|因ؓ它开始执行一D|的程序,q没?q回"的概c失败的时候会q回-1?br>    6). 在父q程q行q行操作的时候,用ps查看Q可以看到子q程的状态ؓT,表示子进E处于TASK_TRACED状态。当然ؓ了更h作性,你可以在父进E中加入sleep()?br>
(To Be Continued)

Pthread  08/01/13

原文地址Qhttp://blog.csdn.net/Javadino/archive/2008/09/06/2891413.aspx


叶子 2009-07-25 17:55 发表评论
]]>
Ptrace及其命ohttp://www.shnenglu.com/elva/archive/2009/07/25/91146.html叶子叶子Sat, 25 Jul 2009 09:52:00 GMThttp://www.shnenglu.com/elva/archive/2009/07/25/91146.htmlhttp://www.shnenglu.com/elva/comments/91146.htmlhttp://www.shnenglu.com/elva/archive/2009/07/25/91146.html#Feedback0http://www.shnenglu.com/elva/comments/commentRss/91146.htmlhttp://www.shnenglu.com/elva/services/trackbacks/91146.html在用h式中Q虽然只有一个函数可用,?/span>ptrace(int _request, pid_t _pid, caddr_t _addr, int _data)Q但是这个函数能做所有的事情Q如果你愿意Q也可以p几个时来编写自q调试器Q以解决特定的问题?/span>

ptrace函数?/span>_request参数是最重要的一个参敎ͼ因ؓ它确定你做什么?/span>BSD?/span>Linux的头文g使用不同的定义,q得将ptrace应用从一个^台移植到另一个^台变得很复杂。默认地Q我们?/span>BSD头文件中的定义?/span>

r  PT_TRACE_MEQ?/span>PTRACE_TRACEMEQ将当前q程切换到停止状态。它通常L?/span>fork/exec一起用,虽然也能遇到自我q踪的应用程序。对于每一个进E,PT_TRACE_ME只能被调用一ơ。追t一个正被追t的q程是会p|的(另一个较不重要的l果是进E不能追t它自己。如果要q样做,应该首先从自w派生一个进E)。大量的反调试技术都是以q一事实为基的。ؓ了克服这cL术,必须使用l过ptrace的调试器。一个信可发送到正被调试的进E,q将该进E切换到停止状态,该进E可以用从父进E上下文中调用的PT_CONTINUE?/span>PT_STEP命o从停止状态退出?/span>wait函数会gq父q程的执行,直到被调试的q程切换为停止状态或者终止ؓ止(l止Ӟq回gؓ1407Q。其他的所有参?span style="letter-spacing: 0.1pt;">都被忽略?/span>

r  PT_ATTACHQ?/span>PTRACE_ATTACHQ?/span>进E标志ؓpid的运行进E切换ؓ停止状态,在这U情形下Q调试器q程成ؓ“父进E?#8221;。其他的所有参数都被忽略。进E必d有与调试q程相同的用h志(UIDQ,q且不能?/span>setuid/setduidq程Q否则就要用root来调试)?/span>

r  PT_DETACHQ?/span>PTRACE_DETACHQ?/span>停止q程标志?/span>pidq程Q由PT_ATTACH?/span>PT_TRACE_ME指定Q的调试Qƈl箋其常态运行。其他的所有参数都被忽略?/span>

r  PT_CONTINUEQ?/span>PTRACE_CONTQ?/span>l箋q程标志?/span>pid的被调试q程的执行,而不中断与调试器q程的通信。如?/span>addr Q= 1Q在Linux中ؓ0Q,从上ơ停止的地址l箋执行Q否则,从指定的地址l箋执行。参?/span>_data指定发送到被调试进E的信号数量Q零说明没有信号Q?/span>

r  PT_STEPQ?/span>PTRACE_SINGLESTEPQ?/span>q行q程标志?/span>pid的进E的单步执行Q即执行下一条机器指令ƈ切换为停止状态(?/span>i386中,q是Ҏ(gu)讄q踪标志来实?span style="letter-spacing: -0.1pt;">的,虽然有些“黑客”函数库用硬件断点)?/span>BSD要求参?/span>addr1Q?/span>Linux要求该参数|ؓ0。其他的所有参数都被忽略?/span>

r  PT_READ_I?/span>PT_READ_DQ?/span>PTRACE_PEEKTEXT?/span>PTRACE_PEEKDATAQ分别从代码区和?/span>?/span>调试q程的地址I间取机器字。在许多当代的^CQ这两个指o是等L(fng)?/span>ptrace函数接收目标地址addrQƈq回d的结果?/span>

r  PT_WRITE_I?/span>PR_READ_DQ?/span>PTRACE_POKETEXT?/span>PTRACE_POKEDATAQ?/span>_data传入的机器字写入addr所指定的地址?/span>

r  PT_GETREGSQ?/span>PT_GETFPREGS?/span>PT_GETDBREGSQ?/span>PTRACE_GETREGSQ?/span>PTRACE_ FPREGS?/span>PT_GETFPXREGSQ?/span>一般用途寄存器、段寄存器和调试寄存器的D入到地址?/span>_addr指针所指定的调试器q程的内存区中。只?/span>i386q_接收q些与系l相关的命o。寄存器l构的描q放在头文gmachine/reg.h文g中?/span>

r  PT_SETREGSQ?/span>PT_SETFPREGS?/span>PT_SETDBREGSQ?/span>PTRACE_SETREGSQ?/span>PTRACE_ SETFPREGS?/span>PT_SETFPXREGSQ?/span>通过拯?/span>_addr指针所指定的内存区域的内容来设|被调试q程的寄存器的倹{?/span>

r  PT_KILLQ?/span>PTRACE_KILLQ?/span>?/span>sigkill发送到被调试进E,以终止其执行?/span>



叶子 2009-07-25 17:52 发表评论
]]>
Playing with ptrace, Part IIhttp://www.shnenglu.com/elva/archive/2009/07/25/91141.html叶子叶子Sat, 25 Jul 2009 09:45:00 GMThttp://www.shnenglu.com/elva/archive/2009/07/25/91141.htmlhttp://www.shnenglu.com/elva/comments/91141.htmlhttp://www.shnenglu.com/elva/archive/2009/07/25/91141.html#Feedback0http://www.shnenglu.com/elva/comments/commentRss/91141.htmlhttp://www.shnenglu.com/elva/services/trackbacks/91141.htmlIn Part I of this article [LJ, November 2002], we saw how ptrace can be used to trace system calls and change system call arguments. In this article, we investigate advanced techniques like setting breakpoints and injecting code into running programs. Debuggers use these methods to set up breakpoints and execute debugging handlers. As with Part I, all code in this article is i386 architecture-specific.

In Part I, we ran the process to be traced as a child after calling ptrace(PTRACE_TRACEME, ..). If you simply wanted to see how the process is making system calls and trace the program, this would be sufficient. If you want to trace or debug a process already running, then ptrace(PTRACE_ATTACH, ..) should be used.

When a ptrace(PTRACE_ATTACH, ..) is called with the pid to be traced, it is roughly equivalent to the process calling ptrace(PTRACE_TRACEME, ..) and becoming a child of the tracing process. The traced process is sent a SIGSTOP, so we can examine and modify the process as usual. After we are done with modifications or tracing, we can let the traced process continue on its own by calling ptrace(PTRACE_DETACH, ..).

The following is the code for a small example tracing program:

int main()
{ int i;
for(i = 0;i < 10; ++i) {
printf("My counter: %d\n", i);
sleep(2);
}
return 0;
}

Save the program as dummy2.c. Compile and run it:

gcc -o dummy2 dummy2.c
./dummy2 &
Now, we can attach to dummy2 by using the code below:
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <linux/user.h> /* For user_regs_struct
etc. */
int main(int argc, char *argv[])
{ pid_t traced_process;
struct user_regs_struct regs;
long ins;
if(argc != 2) {
printf("Usage: %s <pid to be traced>\n",
argv[0], argv[1]);
exit(1);
}
traced_process = atoi(argv[1]);
ptrace(PTRACE_ATTACH, traced_process,
NULL, NULL);
wait(NULL);
ptrace(PTRACE_GETREGS, traced_process,
NULL, &regs);
ins = ptrace(PTRACE_PEEKTEXT, traced_process,
regs.eip, NULL);
printf("EIP: %lx Instruction executed: %lx\n",
regs.eip, ins);
ptrace(PTRACE_DETACH, traced_process,
NULL, NULL);
return 0;
}
The above program simply attaches to a process, waits for it to stop, examines its eip (instruction pointer) and detaches.

To inject code use ptrace(PTRACE_POKETEXT, ..) and ptrace(PTRACE_POKEDATA, ..) after the traced process has stopped.

Setting Breakpoints

How do debuggers set breakpoints? Generally, they replace the instruction to be executed with a trap instruction, so that when the traced program stops, the tracing program, the debugger, can examine it. It will replace the original instruction once the tracing program continues the traced process. Here's an example:

#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <linux/user.h>
const int long_size = sizeof(long);
void getdata(pid_t child, long addr,
char *str, int len)
{ char *laddr;
int i, j;
union u {
long val;
char chars[long_size];
}data;
i = 0;
j = len / long_size;
laddr = str;
while(i < j) {
data.val = ptrace(PTRACE_PEEKDATA, child,
addr + i * 4, NULL);
memcpy(laddr, data.chars, long_size);
++i;
laddr += long_size;
}
j = len % long_size;
if(j != 0) {
data.val = ptrace(PTRACE_PEEKDATA, child,
addr + i * 4, NULL);
memcpy(laddr, data.chars, j);
}
str[len] = '\0';
}
void putdata(pid_t child, long addr,
char *str, int len)
{ char *laddr;
int i, j;
union u {
long val;
char chars[long_size];
}data;
i = 0;
j = len / long_size;
laddr = str;
while(i < j) {
memcpy(data.chars, laddr, long_size);
ptrace(PTRACE_POKEDATA, child,
addr + i * 4, data.val);
++i;
laddr += long_size;
}
j = len % long_size;
if(j != 0) {
memcpy(data.chars, laddr, j);
ptrace(PTRACE_POKEDATA, child,
addr + i * 4, data.val);
}
}
int main(int argc, char *argv[])
{ pid_t traced_process;
struct user_regs_struct regs, newregs;
long ins;
/* int 0x80, int3 */
char code[] = {0xcd,0x80,0xcc,0};
char backup[4];
if(argc != 2) {
printf("Usage: %s <pid to be traced>\n",
argv[0], argv[1]);
exit(1);
}
traced_process = atoi(argv[1]);
ptrace(PTRACE_ATTACH, traced_process,
NULL, NULL);
wait(NULL);
ptrace(PTRACE_GETREGS, traced_process,
NULL, &regs);
/* Copy instructions into a backup variable */
getdata(traced_process, regs.eip, backup, 3);
/* Put the breakpoint */
putdata(traced_process, regs.eip, code, 3);
/* Let the process continue and execute
the int 3 instruction */
ptrace(PTRACE_CONT, traced_process, NULL, NULL);
wait(NULL);
printf("The process stopped, putting back "
"the original instructions\n");
printf("Press <enter> to continue\n");
getchar();
putdata(traced_process, regs.eip, backup, 3);
/* Setting the eip back to the original
instruction to let the process continue */
ptrace(PTRACE_SETREGS, traced_process,
NULL, &regs);
ptrace(PTRACE_DETACH, traced_process,
NULL, NULL);
return 0;
}

Here we replace the three bytes with the code for a trap instruction, and when the process stops, we replace the original instructions and reset the eip to original location. Figures 1-4 clarify how the instruction stream looks when above program is executed.

Figure 1. After the Process Is Stopped

Figure 2. After the Trap Instruction Bytes Are Set

Figure 3. Trap Is Hit and Control Is Given to the Tracing Program

Figure 4. After the Original Instructions Are Replaced and eip Is Reset to the Original Location

Now that we have a clear idea of how breakpoints are set, let's inject some code bytes into a running program. These code bytes will print “hello world”.

The following program is a simple “hello world” program with modifications to fit our needs. Compile the following program with:

gcc -o hello hello.c
void main()
{
__asm__("
jmp forward
backward:
popl %esi # Get the address of
# hello world string
movl $4, %eax # Do write system call
movl $2, %ebx
movl %esi, %ecx
movl $12, %edx
int $0x80
int3 # Breakpoint. Here the
# program will stop and
# give control back to
# the parent
forward:
call backward
.string \"Hello World\\n\""
);
}

The jumping backward and forward here is required to find the address of the “hello world” string.

We can get the machine code for the above assembly from GDB. Fire up GDB and disassemble the program:

(gdb) disassemble main
Dump of assembler code for function main:
0x80483e0 <main>: push %ebp
0x80483e1 <main+1>: mov %esp,%ebp
0x80483e3 <main+3>: jmp 0x80483fa <forward>
End of assembler dump.
(gdb) disassemble forward
Dump of assembler code for function forward:
0x80483fa <forward>: call 0x80483e5 <backward>
0x80483ff <forward+5>: dec %eax
0x8048400 <forward+6>: gs
0x8048401 <forward+7>: insb (%dx),%es:(%edi)
0x8048402 <forward+8>: insb (%dx),%es:(%edi)
0x8048403 <forward+9>: outsl %ds:(%esi),(%dx)
0x8048404 <forward+10>: and %dl,0x6f(%edi)
0x8048407 <forward+13>: jb 0x8048475
0x8048409 <forward+15>: or %fs:(%eax),%al
0x804840c <forward+18>: mov %ebp,%esp
0x804840e <forward+20>: pop %ebp
0x804840f <forward+21>: ret
End of assembler dump.
(gdb) disassemble backward
Dump of assembler code for function backward:
0x80483e5 <backward>: pop %esi
0x80483e6 <backward+1>: mov $0x4,%eax
0x80483eb <backward+6>: mov $0x2,%ebx
0x80483f0 <backward+11>: mov %esi,%ecx
0x80483f2 <backward+13>: mov $0xc,%edx
0x80483f7 <backward+18>: int $0x80
0x80483f9 <backward+20>: int3
End of assembler dump.

We need to take the machine code bytes from main+3 to backward+20, which is a total of 41 bytes. The machine code can be seen with the x command in GDB:

(gdb) x/40bx main+3
<main+3>: eb 15 5e b8 04 00 00 00
<backward+6>: bb 02 00 00 00 89 f1 ba
<backward+14>: 0c 00 00 00 cd 80 cc
<forward+1>: e6 ff ff ff 48 65 6c 6c
<forward+9>: 6f 20 57 6f 72 6c 64 0a
Now we have the instruction bytes to be executed. Why wait? We can inject them using the same method as in the previous example. The following is the source code; only the main function is given here:
int main(int argc, char *argv[])
{ pid_t traced_process;
struct user_regs_struct regs, newregs;
long ins;
int len = 41;
char insertcode[] =
"\xeb\x15\x5e\xb8\x04\x00"
"\x00\x00\xbb\x02\x00\x00\x00\x89\xf1\xba"
"\x0c\x00\x00\x00\xcd\x80\xcc\xe8\xe6\xff"
"\xff\xff\x48\x65\x6c\x6c\x6f\x20\x57\x6f"
"\x72\x6c\x64\x0a\x00";
char backup[len];
if(argc != 2) {
printf("Usage: %s <pid to be traced>\n",
argv[0], argv[1]);
exit(1);
}
traced_process = atoi(argv[1]);
ptrace(PTRACE_ATTACH, traced_process,
NULL, NULL);
wait(NULL);
ptrace(PTRACE_GETREGS, traced_process,
NULL, &regs);
getdata(traced_process, regs.eip, backup, len);
putdata(traced_process, regs.eip,
insertcode, len);
ptrace(PTRACE_SETREGS, traced_process,
NULL, &regs);
ptrace(PTRACE_CONT, traced_process,
NULL, NULL);
wait(NULL);
printf("The process stopped, Putting back "
"the original instructions\n");
putdata(traced_process, regs.eip, backup, len);
ptrace(PTRACE_SETREGS, traced_process,
NULL, &regs);
printf("Letting it continue with "
"original flow\n");
ptrace(PTRACE_DETACH, traced_process,
NULL, NULL);
return 0;
}
Injecting the Code into Free Space

In the previous example we injected the code directly into the executing instruction stream. However, debuggers can get confused with this kind of behaviour, so let's find the free space in the process and inject the code there. We can find free space by examining the /proc/pid/maps file of the traced process. The following function will find the starting address of this map:

long freespaceaddr(pid_t pid)
{
FILE *fp;
char filename[30];
char line[85];
long addr;
char str[20];
sprintf(filename, "/proc/%d/maps", pid);
fp = fopen(filename, "r");
if(fp == NULL)
exit(1);
while(fgets(line, 85, fp) != NULL) {
sscanf(line, "%lx-%*lx %*s %*s %s", &addr,
str, str, str, str);
if(strcmp(str, "00:00") == 0)
break;
}
fclose(fp);
return addr;
}

Each line in /proc/pid/maps represents a mapped region of the process. An entry in /proc/pid/maps looks like this:

map start-mapend    protection  offset     device
inode process file
08048000-0804d000 r-xp 00000000 03:08
66111 /opt/kde2/bin/kdeinit
The following program injects code into free space. It's similar to the previous injection program except the free space address is used for keeping our new code. Here is the source code for the main function:
int main(int argc, char *argv[])
{ pid_t traced_process;
struct user_regs_struct oldregs, regs;
long ins;
int len = 41;
char insertcode[] =
"\xeb\x15\x5e\xb8\x04\x00"
"\x00\x00\xbb\x02\x00\x00\x00\x89\xf1\xba"
"\x0c\x00\x00\x00\xcd\x80\xcc\xe8\xe6\xff"
"\xff\xff\x48\x65\x6c\x6c\x6f\x20\x57\x6f"
"\x72\x6c\x64\x0a\x00";
char backup[len];
long addr;
if(argc != 2) {
printf("Usage: %s <pid to be traced>\n",
argv[0], argv[1]);
exit(1);
}
traced_process = atoi(argv[1]);
ptrace(PTRACE_ATTACH, traced_process,
NULL, NULL);
wait(NULL);
ptrace(PTRACE_GETREGS, traced_process,
NULL, &regs);
addr = freespaceaddr(traced_process);
getdata(traced_process, addr, backup, len);
putdata(traced_process, addr, insertcode, len);
memcpy(&oldregs, &regs, sizeof(regs));
regs.eip = addr;
ptrace(PTRACE_SETREGS, traced_process,
NULL, &regs);
ptrace(PTRACE_CONT, traced_process,
NULL, NULL);
wait(NULL);
printf("The process stopped, Putting back "
"the original instructions\n");
putdata(traced_process, addr, backup, len);
ptrace(PTRACE_SETREGS, traced_process,
NULL, &oldregs);
printf("Letting it continue with "
"original flow\n");
ptrace(PTRACE_DETACH, traced_process,
NULL, NULL);
return 0;
}
Behind the Scenes

So what happens within the kernel now? How is ptrace implemented? This section could be an article on its own; however, here's a brief description of what happens.

When a process calls ptrace with PTRACE_TRACEME, the kernel sets up the process flags to reflect that it is being traced:

Source: arch/i386/kernel/ptrace.c
if (request == PTRACE_TRACEME) {
/* are we already being traced? */
if (current->ptrace & PT_PTRACED)
goto out;
/* set the ptrace bit in the process flags. */
current->ptrace |= PT_PTRACED;
ret = 0;
goto out;
}

When a system call entry is done, the kernel checks this flag and calls the trace system call if the process is being traced. The gory assembly details can be found in arch/i386/kernel/entry.S.

Now, we are in the sys_trace() function as defined in arch/i386/kernel/ptrace.c. It stops the child and sends a signal to the parent notifying that the child is stopped. This wakes up the waiting parent, and it does the ptrace magic. Once the parent is done, and it calls ptrace(PTRACE_CONT, ..) or ptrace(PTRACE_SYSCALL, ..), it wakes up the child by calling the scheduler function wake_up_process(). Some other architectures can implement this by sending a SIGCHLD to child.

Conclusion

ptrace may appear to be magic to some people, because it can examine and modify a running program. It is generally used by debuggers and system call tracing programs, such as ptrace. It opens up interesting possibilities for doing user-mode extensions as well. There have been a lot of attempts to extend the operating system on the user level. See Resources to read about UFO, a user-level extension to filesystems. ptrace also is used to employ security mechanisms.

All example code from this article and from Part I is available as a tar archive on the Linux Journal FTP site [ftp.ssc.com/pub/lj/listings/issue104/6210.tgz].


原文Q?br>

http://www.linuxjournal.com/article/6210



叶子 2009-07-25 17:45 发表评论
]]>玩{ptrace(一)http://www.shnenglu.com/elva/archive/2009/07/25/91140.html叶子叶子Sat, 25 Jul 2009 09:45:00 GMThttp://www.shnenglu.com/elva/archive/2009/07/25/91140.htmlhttp://www.shnenglu.com/elva/comments/91140.htmlhttp://www.shnenglu.com/elva/archive/2009/07/25/91140.html#Feedback0http://www.shnenglu.com/elva/comments/commentRss/91140.htmlhttp://www.shnenglu.com/elva/services/trackbacks/91140.html阅读全文

叶子 2009-07-25 17:45 发表评论
]]>
SIGPIPED的程序退?/title><link>http://www.shnenglu.com/elva/archive/2009/07/21/90761.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Tue, 21 Jul 2009 10:56:00 GMT</pubDate><guid>http://www.shnenglu.com/elva/archive/2009/07/21/90761.html</guid><wfw:comment>http://www.shnenglu.com/elva/comments/90761.html</wfw:comment><comments>http://www.shnenglu.com/elva/archive/2009/07/21/90761.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/elva/comments/commentRss/90761.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/elva/services/trackbacks/90761.html</trackback:ping><description><![CDATA[<span id="nqzusvu" class=Apple-style-span style="WORD-SPACING: 0px; FONT: 16px simsun; TEXT-TRANSFORM: none; COLOR: rgb(0,0,0); TEXT-INDENT: 0px; WHITE-SPACE: normal; LETTER-SPACING: normal; BORDER-COLLAPSE: separate; orphans: 2; widows: 2; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span id="lsbhjqe" class=Apple-style-span style="FONT-SIZE: 12px; LINE-HEIGHT: 18px; FONT-FAMILY: Arial"> <table style="TABLE-LAYOUT: fixed"> <tbody> <tr> <td style="FONT-SIZE: 12px; FILTER: none; VISIBILITY: visible! important; WORD-BREAK: break-all; LINE-HEIGHT: 18px; ZOOM: 1! important; FONT-FAMILY: Arial; WORD-WRAP: break-word"> <div id="tdxsxes" class=cnt id=blog_text style="OVERFLOW-Y: hidden; FONT-SIZE: 14px; FILTER: none; VISIBILITY: visible! important; OVERFLOW-X: hidden; COLOR: rgb(51,51,51); WORD-BREAK: normal; LINE-HEIGHT: 20px; ZOOM: 1! important; FONT-FAMILY: Arial; POSITION: static; WORD-WRAP: break-word"> <p style="LINE-HEIGHT: normal">当服务器close一个连接时Q若client端接着发数据。根据TCP协议的规定,会收C个RST响应Qclient再往q个服务器发送数据时Q系l会发出一个SIGPIPE信号l进E,告诉q程q个q接已经断开了,不要再写了?br style="LINE-HEIGHT: normal">    Ҏ(gu)信号的默认处理规则SIGPIPE信号的默认执行动作是terminate(l止、退?,所以client会退出。若不想客户端退出可以把SIGPIPE设ؓSIG_IGN</p> <p style="LINE-HEIGHT: normal">    ?    signal(SIGPIPE,SIG_IGN);<br style="LINE-HEIGHT: normal">    q时SIGPIPE交给了系l处理?/p> <p style="LINE-HEIGHT: normal">服务器采用了fork的话Q要攉垃圾q程Q防止僵进E的产生Q可以这样处理:<br style="LINE-HEIGHT: normal">signal(SIGCHLD,SIG_IGN); 交给pȝinitd收?br style="LINE-HEIGHT: normal">   q里子进E就不会产生僵尸q程了?/p> <p style="LINE-HEIGHT: normal"><br style="LINE-HEIGHT: normal"><a style="LINE-HEIGHT: normal" ><u><font color=#0000ff>http://www.cublog.cn/u/31357/showart_242605.html</font></u></a></p> <p style="LINE-HEIGHT: normal"><br style="LINE-HEIGHT: normal">好久没做qC开发了Q最q重操旧业?span class=Apple-converted-space> </span><br style="LINE-HEIGHT: normal">听说另外一个项目组socket开发遇到问题,发送端和接受端数据大小不一致。徏议他们采用writen的重发机Ӟ以避免信号中断错误。采用后q是有问题。PM让我帮忙研究下?span class=Apple-converted-space> </span><br style="LINE-HEIGHT: normal">UNP nq以前看q,很久没做q底层开发,手边也没有UNP vol1q本书,所以做了个试E序Q研I下实际可能发生的情况了?span class=Apple-converted-space> </span><br style="LINE-HEIGHT: normal"><br style="LINE-HEIGHT: normal">试环境QAS3和redhat 9(~省没有nc)<span id="srezied" class=Apple-converted-space> </span><br style="LINE-HEIGHT: normal"><br style="LINE-HEIGHT: normal">先下载unp源码:<span id="awulyma" class=Apple-converted-space> </span><br style="LINE-HEIGHT: normal">wget<span id="birxkvu" class=Apple-converted-space> </span><a style="LINE-HEIGHT: normal" ><u><font color=#0000ff>http://www.unpbook.com/unpv13e.tar.gz</font></u></a><span id="iayerux" class=Apple-converted-space> </span><br style="LINE-HEIGHT: normal">tar xzvf *.tar.gz;<span id="pwfhfta" class=Apple-converted-space> </span><br style="LINE-HEIGHT: normal">configure;make lib.<span id="thbwuqt" class=Apple-converted-space> </span><br style="LINE-HEIGHT: normal">然后参考str_cli.c和tcpcli01.cQ写了测试代码client.c<span id="vgevtlz" class=Apple-converted-space> </span><br style="LINE-HEIGHT: normal"><br style="LINE-HEIGHT: normal">#include    "unp.h"</p> <p style="LINE-HEIGHT: normal">#define MAXBUF 40960<br style="LINE-HEIGHT: normal">void processSignal(int signo)<br style="LINE-HEIGHT: normal">{<br style="LINE-HEIGHT: normal">    printf("Signal is %d\n", signo);<br style="LINE-HEIGHT: normal">    signal(signo, processSignal);<br style="LINE-HEIGHT: normal">}<br style="LINE-HEIGHT: normal">void<br style="LINE-HEIGHT: normal">str_cli(FILE *fp, int sockfd)<br style="LINE-HEIGHT: normal">{<br style="LINE-HEIGHT: normal">    char    sendline[MAXBUF], recvline[MAXBUF];</p> <p style="LINE-HEIGHT: normal">    while (1) {</p> <p style="LINE-HEIGHT: normal">        memset(sendline, 'a', sizeof(sendline));<br style="LINE-HEIGHT: normal">        printf("Begin send %d data\n", MAXBUF);<br style="LINE-HEIGHT: normal">        Writen(sockfd, sendline, sizeof(sendline));<br style="LINE-HEIGHT: normal">        sleep(5);</p> <p style="LINE-HEIGHT: normal">    }<br style="LINE-HEIGHT: normal">}</p> <p style="LINE-HEIGHT: normal">int<br style="LINE-HEIGHT: normal">main(int argc, char **argv)<br style="LINE-HEIGHT: normal">{<br style="LINE-HEIGHT: normal">    int                    sockfd;<br style="LINE-HEIGHT: normal">    struct sockaddr_in    servaddr;</p> <p style="LINE-HEIGHT: normal">    signal(SIGPIPE, SIG_IGN);<br style="LINE-HEIGHT: normal">    //signal(SIGPIPE, processSignal);</p> <p style="LINE-HEIGHT: normal">    if (argc != 2)<br style="LINE-HEIGHT: normal">        err_quit("usage: tcpcli [port]");</p> <p style="LINE-HEIGHT: normal">    sockfd = Socket(AF_INET, SOCK_STREAM, 0);</p> <p style="LINE-HEIGHT: normal">    bzero(&servaddr, sizeof(servaddr));<br style="LINE-HEIGHT: normal">    servaddr.sin_family = AF_INET;<br style="LINE-HEIGHT: normal">    servaddr.sin_port = htons(atoi(argv[1]));<br style="LINE-HEIGHT: normal">    Inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);</p> <p style="LINE-HEIGHT: normal">    Connect(sockfd, (SA *) &servaddr, sizeof(servaddr));</p> <p style="LINE-HEIGHT: normal">    str_cli(stdin, sockfd);        /* do it all */</p> <p style="LINE-HEIGHT: normal">    exit(0);<br style="LINE-HEIGHT: normal">}</p> <p style="LINE-HEIGHT: normal"></p> <p style="LINE-HEIGHT: normal"></p> <p style="LINE-HEIGHT: normal">Z方便观察错误输出Qlib/writen.c也做了修改,加了些日志:</p> <p style="LINE-HEIGHT: normal"></p> <p style="LINE-HEIGHT: normal"></p> <p style="LINE-HEIGHT: normal">/* include writen */<br style="LINE-HEIGHT: normal">#include    "unp.h"</p> <p style="LINE-HEIGHT: normal">ssize_t        &nbs <table class=FCK__ShowTableBorders style="TABLE-LAYOUT: auto; LINE-HEIGHT: normal"> <tbody style="LINE-HEIGHT: normal"> <tr style="LINE-HEIGHT: normal"> <td style="FONT-SIZE: 12px; FILTER: none; VISIBILITY: visible! important; WORD-BREAK: break-all; LINE-HEIGHT: normal; ZOOM: 1! important; FONT-FAMILY: Arial; WORD-WRAP: break-word"> <p style="LINE-HEIGHT: normal"><font style="LINE-HEIGHT: normal" size=+0><span style="LINE-HEIGHT: normal">p;               <span style="COLOR: rgb(255,153,0); LINE-HEIGHT: normal">/* Write "n" bytes to a descriptor. */</span><br style="LINE-HEIGHT: normal">writen<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">(</span><span style="COLOR: rgb(0,0,255); LINE-HEIGHT: normal">int</span><span id="oyntrjb" class=Apple-converted-space> </span>fd<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">,</span><span id="sgxdfps" class=Apple-converted-space> </span><span style="COLOR: rgb(0,0,255); LINE-HEIGHT: normal">const</span><span id="xpfwjqa" class=Apple-converted-space> </span><span style="COLOR: rgb(0,0,255); LINE-HEIGHT: normal">void</span><span id="vuduldr" class=Apple-converted-space> </span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">*</span>vptr<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">,</span><span id="poisqew" class=Apple-converted-space> </span><span style="COLOR: rgb(255,0,0); LINE-HEIGHT: normal">size_t</span><span id="wrezbed" class=Apple-converted-space> </span>n<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">)</span><br style="LINE-HEIGHT: normal"><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">{</span><br style="LINE-HEIGHT: normal">    <span style="COLOR: rgb(255,0,0); LINE-HEIGHT: normal">size_t</span>         nleft<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">;</span><br style="LINE-HEIGHT: normal">     ssize_t         nwritten<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">;</span><br style="LINE-HEIGHT: normal">    <span style="COLOR: rgb(0,0,255); LINE-HEIGHT: normal">const</span><span id="sravtaz" class=Apple-converted-space> </span><span style="COLOR: rgb(0,0,255); LINE-HEIGHT: normal">char</span>    <span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">*</span>ptr<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">;</span><br style="LINE-HEIGHT: normal"><br style="LINE-HEIGHT: normal">     ptr<span id="hoxobxw" class=Apple-converted-space> </span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">=</span><span id="wdbhjbt" class=Apple-converted-space> </span>vptr<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">;</span><br style="LINE-HEIGHT: normal">     nleft<span id="bajayxp" class=Apple-converted-space> </span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">=</span><span id="ehqwqih" class=Apple-converted-space> </span>n<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">;</span><br style="LINE-HEIGHT: normal">    <span style="COLOR: rgb(0,0,255); LINE-HEIGHT: normal">while</span><span id="admsuxw" class=Apple-converted-space> </span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">(</span>nleft<span id="wgavpsg" class=Apple-converted-space> </span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">></span><span id="gyhclon" class=Apple-converted-space> </span>0<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">)</span><span id="lobdqth" class=Apple-converted-space> </span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">{</span><br style="LINE-HEIGHT: normal">        <span style="COLOR: rgb(255,0,0); LINE-HEIGHT: normal">printf</span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">(</span><span style="COLOR: rgb(255,0,255); LINE-HEIGHT: normal">"Begin Writen %d\n"</span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">,</span><span id="kgikxph" class=Apple-converted-space> </span>nleft<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">)</span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">;</span><br style="LINE-HEIGHT: normal">        <span style="COLOR: rgb(0,0,255); LINE-HEIGHT: normal">if</span><span id="fpyacft" class=Apple-converted-space> </span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">(</span><span id="hvtdbes" class=Apple-converted-space> </span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">(</span>nwritten<span id="wvevilo" class=Apple-converted-space> </span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">=</span><span id="vnhceho" class=Apple-converted-space> </span><span style="COLOR: rgb(255,0,0); LINE-HEIGHT: normal">write</span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">(</span>fd<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">,</span><span id="vrpkxes" class=Apple-converted-space> </span>ptr<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">,</span><span id="vrlctwz" class=Apple-converted-space> </span>nleft<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">)</span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">)</span><span id="ezfhjma" class=Apple-converted-space> </span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal"><</span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">=</span><span id="iwnikcq" class=Apple-converted-space> </span>0<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">)</span><span id="tljerux" class=Apple-converted-space> </span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">{</span><br style="LINE-HEIGHT: normal">            <span style="COLOR: rgb(0,0,255); LINE-HEIGHT: normal">if</span><span id="mlulryf" class=Apple-converted-space> </span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">(</span>nwritten<span id="pdfwyqt" class=Apple-converted-space> </span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal"><</span><span id="qajpcyq" class=Apple-converted-space> </span>0<span id="wrarihk" class=Apple-converted-space> </span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">&</span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">&</span><span id="mhboqib" class=Apple-converted-space> </span><span style="COLOR: rgb(255,0,0); LINE-HEIGHT: normal">errno</span><span id="gbgqskj" class=Apple-converted-space> </span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">=</span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">=</span><span id="xhuprfp" class=Apple-converted-space> </span>EINTR<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">)</span><span id="ocekadk" class=Apple-converted-space> </span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">{</span><br style="LINE-HEIGHT: normal">                <span style="COLOR: rgb(255,0,0); LINE-HEIGHT: normal">printf</span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">(</span><span style="COLOR: rgb(255,0,255); LINE-HEIGHT: normal">"intterupt\n"</span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">)</span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">;</span><br style="LINE-HEIGHT: normal">                 nwritten<span id="gfouloy" class=Apple-converted-space> </span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">=</span><span id="niciorf" class=Apple-converted-space> </span>0<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">;</span>        <span style="COLOR: rgb(255,153,0); LINE-HEIGHT: normal">/* and call write() again */</span><br style="LINE-HEIGHT: normal">            <span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">}</span><br style="LINE-HEIGHT: normal">            <span style="COLOR: rgb(0,0,255); LINE-HEIGHT: normal">else</span><br style="LINE-HEIGHT: normal">                <span style="COLOR: rgb(0,0,255); LINE-HEIGHT: normal">return</span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">(</span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">-</span>1<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">)</span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">;</span>            <span style="COLOR: rgb(255,153,0); LINE-HEIGHT: normal">/* error */</span><br style="LINE-HEIGHT: normal">        <span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">}</span><br style="LINE-HEIGHT: normal"><br style="LINE-HEIGHT: normal">         nleft<span id="xactvyb" class=Apple-converted-space> </span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">-</span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">=</span><span id="znsjwdc" class=Apple-converted-space> </span>nwritten<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">;</span><br style="LINE-HEIGHT: normal">         ptr<span id="jusuwdc" class=Apple-converted-space> </span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">+</span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">=</span><span id="rbdcadc" class=Apple-converted-space> </span>nwritten<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">;</span><br style="LINE-HEIGHT: normal">        <span style="COLOR: rgb(255,0,0); LINE-HEIGHT: normal">printf</span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">(</span><span style="COLOR: rgb(255,0,255); LINE-HEIGHT: normal">"Already write %d, left %d, errno=%d\n"</span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">,</span><span id="kjojwoc" class=Apple-converted-space> </span>nwritten<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">,</span><span id="adisuxw" class=Apple-converted-space> </span>nleft<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">,</span><span id="akiobps" class=Apple-converted-space> </span><span style="COLOR: rgb(255,0,0); LINE-HEIGHT: normal">errno</span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">)</span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">;</span><br style="LINE-HEIGHT: normal">    <span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">}</span><br style="LINE-HEIGHT: normal">    <span style="COLOR: rgb(0,0,255); LINE-HEIGHT: normal">return</span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">(</span>n<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">)</span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">;</span><br style="LINE-HEIGHT: normal"><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">}</span><br style="LINE-HEIGHT: normal"><span style="COLOR: rgb(255,153,0); LINE-HEIGHT: normal">/* end writen */</span><br style="LINE-HEIGHT: normal"><br style="LINE-HEIGHT: normal"><span style="COLOR: rgb(0,0,255); LINE-HEIGHT: normal">void</span><br style="LINE-HEIGHT: normal">Writen<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">(</span><span style="COLOR: rgb(0,0,255); LINE-HEIGHT: normal">int</span><span id="ybfacqi" class=Apple-converted-space> </span>fd<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">,</span><span id="mdqlnbe" class=Apple-converted-space> </span><span style="COLOR: rgb(0,0,255); LINE-HEIGHT: normal">void</span><span id="ahfpnbw" class=Apple-converted-space> </span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">*</span>ptr<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">,</span><span id="tdbhfxa" class=Apple-converted-space> </span><span style="COLOR: rgb(255,0,0); LINE-HEIGHT: normal">size_t</span><span id="nbkbkcu" class=Apple-converted-space> </span>nbytes<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">)</span><br style="LINE-HEIGHT: normal"><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">{</span><br style="LINE-HEIGHT: normal">    <span style="COLOR: rgb(0,0,255); LINE-HEIGHT: normal">if</span><span id="thjpgyq" class=Apple-converted-space> </span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">(</span>writen<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">(</span>fd<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">,</span><span id="kudjasg" class=Apple-converted-space> </span>ptr<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">,</span><span id="adxhumw" class=Apple-converted-space> </span>nbytes<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">)</span><span id="jxgfhzn" class=Apple-converted-space> </span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">!</span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">=</span><span id="admoqxa" class=Apple-converted-space> </span>nbytes<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">)</span><br style="LINE-HEIGHT: normal">         err_sys<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">(</span><span style="COLOR: rgb(255,0,255); LINE-HEIGHT: normal">"writen error"</span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">)</span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">;</span><br style="LINE-HEIGHT: normal"><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">}</span><br style="LINE-HEIGHT: normal"></span></font></p> </td> </tr> </tbody> </table> </p> <p style="LINE-HEIGHT: normal"></p> <p style="LINE-HEIGHT: normal">client.c攑֜tcpclieserv目录下,修改了MakefileQ增加了client.c的编译目?/p> <p style="LINE-HEIGHT: normal"></p> <p style="LINE-HEIGHT: normal"> <table style="TABLE-LAYOUT: auto; LINE-HEIGHT: normal; BORDER-COLLAPSE: collapse" borderColor=#999999 cellSpacing=0 cellPadding=0 width="95%" bgColor=#f1f1f1 border=1> <tbody style="LINE-HEIGHT: normal"> <tr style="LINE-HEIGHT: normal"> <td style="FONT-SIZE: 12px; FILTER: none; VISIBILITY: visible! important; WORD-BREAK: break-all; LINE-HEIGHT: normal; ZOOM: 1! important; FONT-FAMILY: Arial; WORD-WRAP: break-word"> <p style="MARGIN: 5px; LINE-HEIGHT: 18px"><code style="LINE-HEIGHT: normal"><span style="COLOR: rgb(0,0,0); LINE-HEIGHT: normal"><br style="LINE-HEIGHT: normal"><font style="LINE-HEIGHT: normal" face=新宋?client<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">:</span><span id="uerqdku" class=Apple-converted-space> </span>client<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">.</span>c<br style="LINE-HEIGHT: normal">                 $<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">{</span>CC<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">}</span><span id="ekprphk" class=Apple-converted-space> </span>$<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">{</span>CFLAGS<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">}</span><span id="ldfwjbe" class=Apple-converted-space> </span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">-</span>o $@ $<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal"><</span><span id="dgpvtwo" class=Apple-converted-space> </span>$<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">{</span>LIBS<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">}</span><br style="LINE-HEIGHT: normal"></font></span></code></p> </td> </tr> </tbody> </table> </p> <p style="LINE-HEIGHT: normal"></p> <p style="LINE-HEIGHT: normal">接着可以开始测试了?/p> <h2 style="LINE-HEIGHT: normal">试1 忽略SIGPIPE信号Qwriten之前Q对方关闭接受进E?/h2> <p style="LINE-HEIGHT: normal">本机服务端:</p> <p style="LINE-HEIGHT: normal"><br style="LINE-HEIGHT: normal">nc -l -p 30000<span id="nudqdrf" class=Apple-converted-space> </span><br style="LINE-HEIGHT: normal"><br style="LINE-HEIGHT: normal">本机客户?<span id="xiyerfe" class=Apple-converted-space> </span><br style="LINE-HEIGHT: normal">./client 30000<span id="izpzies" class=Apple-converted-space> </span><br style="LINE-HEIGHT: normal">Begin send 40960 data<br style="LINE-HEIGHT: normal">Begin Writen 40960<br style="LINE-HEIGHT: normal">Already write 40960, left 0, errno=0<br style="LINE-HEIGHT: normal">Begin send 40960 data<br style="LINE-HEIGHT: normal">Begin Writen 40960<br style="LINE-HEIGHT: normal">Already write 40960, left 0, errno=0<br style="LINE-HEIGHT: normal"><font style="LINE-HEIGHT: normal" color=#ff0000>执行C步停止服务端,client会l显C?</font><span id="lvtkxes" class=Apple-converted-space> </span><br style="LINE-HEIGHT: normal">Begin send 40960 data<br style="LINE-HEIGHT: normal">Begin Writen 40960<br style="LINE-HEIGHT: normal">writen error: Broken pipe(32)<br style="LINE-HEIGHT: normal"><strong style="LINE-HEIGHT: normal">l论:可见write之前Q对方socket中断Q发送端write会返?1,errno号ؓEPIPE(32)</strong></p> <h2 style="LINE-HEIGHT: normal">试2 catch SIGPIPE信号Qwriten之前Q对方关闭接受进E?/h2> <p style="LINE-HEIGHT: normal">修改客户端代码,catch sigpipe信号</p> <p style="LINE-HEIGHT: normal"> <table style="TABLE-LAYOUT: auto; LINE-HEIGHT: normal; BORDER-COLLAPSE: collapse" borderColor=#999999 cellSpacing=0 cellPadding=0 width="95%" bgColor=#f1f1f1 border=1> <tbody style="LINE-HEIGHT: normal"> <tr style="LINE-HEIGHT: normal"> <td style="FONT-SIZE: 12px; FILTER: none; VISIBILITY: visible! important; WORD-BREAK: break-all; LINE-HEIGHT: normal; ZOOM: 1! important; FONT-FAMILY: Arial; WORD-WRAP: break-word"> <p style="MARGIN: 5px; LINE-HEIGHT: 18px"><code style="LINE-HEIGHT: normal"><span style="COLOR: rgb(0,0,0); LINE-HEIGHT: normal"><font style="LINE-HEIGHT: normal" face=新宋?<span style="COLOR: rgb(255,153,0); LINE-HEIGHT: normal"><font style="LINE-HEIGHT: normal" color=#000000>        </font>//signal(SIGPIPE, SIG_IGN);<br style="LINE-HEIGHT: normal"></span><br style="LINE-HEIGHT: normal">        <span style="COLOR: rgb(255,0,0); LINE-HEIGHT: normal">signal</span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">(</span>SIGPIPE<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">,</span><span id="bmkqskn" class=Apple-converted-space> </span>processSignal<span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">)</span><span style="COLOR: rgb(0,0,204); LINE-HEIGHT: normal">;</span></font><br style="LINE-HEIGHT: normal"></span></code></p> </td> </tr> </tbody> </table> </p> <p style="LINE-HEIGHT: normal">本机服务端:</p> <p style="LINE-HEIGHT: normal"><br style="LINE-HEIGHT: normal">nc -l -p 30000<span id="xwflfml" class=Apple-converted-space> </span><br style="LINE-HEIGHT: normal"><br style="LINE-HEIGHT: normal">本机客户?<span id="cqoqhkj" class=Apple-converted-space> </span><br style="LINE-HEIGHT: normal">make client<span id="wsuwuma" class=Apple-converted-space> </span><br style="LINE-HEIGHT: normal">./client 30000<span id="vcesphz" class=Apple-converted-space> </span><br style="LINE-HEIGHT: normal"><br style="LINE-HEIGHT: normal">Begin send 40960 data<br style="LINE-HEIGHT: normal">Begin Writen 40960<br style="LINE-HEIGHT: normal">Already write 40960, left 0, errno=0<br style="LINE-HEIGHT: normal">Begin send 40960 data<br style="LINE-HEIGHT: normal">Begin Writen 40960<br style="LINE-HEIGHT: normal">Already write 40960, left 0, errno=0<br style="LINE-HEIGHT: normal"><font style="LINE-HEIGHT: normal" color=#ff0000>执行C步停止服务端,client会l显C?</font><span id="azxdftl" class=Apple-converted-space> </span><br style="LINE-HEIGHT: normal">Begin send 40960 data<br style="LINE-HEIGHT: normal">Begin Writen 40960<br style="LINE-HEIGHT: normal">Signal is 13<br style="LINE-HEIGHT: normal">writen error: Broken pipe(32)<br style="LINE-HEIGHT: normal"><strong style="LINE-HEIGHT: normal">l论:可见write之前Q对方socket中断Q发送端writeӞ会先调用SIGPIPE响应函数Q然后writeq回-1,errno号ؓEPIPE(32)</strong><span id="wkikipz" class=Apple-converted-space> </span><br style="LINE-HEIGHT: normal"></p> <h2 style="LINE-HEIGHT: normal">试3 writenq程中,Ҏ(gu)关闭接受q程</h2> <p style="LINE-HEIGHT: normal">Z方便操作Q加?ơwrite的数据量Q修改MAXBUF?096000</p> <p style="LINE-HEIGHT: normal">本机服务端:</p> <p style="LINE-HEIGHT: normal"><br style="LINE-HEIGHT: normal">nc -l -p 30000<span id="phfsmew" class=Apple-converted-space> </span><br style="LINE-HEIGHT: normal"><br style="LINE-HEIGHT: normal">本机客户?<span id="baulubl" class=Apple-converted-space> </span><br style="LINE-HEIGHT: normal">make client<span id="gboqsoh" class=Apple-converted-space> </span><br style="LINE-HEIGHT: normal">./client 30000<span id="iwuaclo" class=Apple-converted-space> </span><br style="LINE-HEIGHT: normal"><br style="LINE-HEIGHT: normal">Begin send 4096000 data<br style="LINE-HEIGHT: normal">Begin Writen 4096000<br style="LINE-HEIGHT: normal"><font style="LINE-HEIGHT: normal" color=#ff0000>执行C步停止服务端,client会l显C?</font><span id="wdfwuxw" class=Apple-converted-space> </span><br style="LINE-HEIGHT: normal">Already write 589821, left 3506179, errno=0<br style="LINE-HEIGHT: normal">Begin Writen 3506179<br style="LINE-HEIGHT: normal">writen error: Connection reset by peer(104)<br style="LINE-HEIGHT: normal"><br style="LINE-HEIGHT: normal"><strong style="LINE-HEIGHT: normal">l论:可见socket write中,Ҏ(gu)socket中断Q发送端write会先q回已经发送的字节?再次write时返?1,errno号ؓECONNRESET(104)</strong></p> <p style="LINE-HEIGHT: normal">Z么以上测试,都是Ҏ(gu)已经中断socket后,发送端再次writeQ结果会有所不同呢。从后来扑ֈ的UNP5.12,5.13能找到答?/p> <p style="LINE-HEIGHT: normal"> <table style="TABLE-LAYOUT: auto; LINE-HEIGHT: normal; BORDER-COLLAPSE: collapse" borderColor=#999999 cellSpacing=0 cellPadding=0 width="95%" bgColor=#f1f1f1 border=1> <tbody style="LINE-HEIGHT: normal"> <tr style="LINE-HEIGHT: normal"> <td style="FONT-SIZE: 12px; FILTER: none; VISIBILITY: visible! important; WORD-BREAK: break-all; LINE-HEIGHT: normal; ZOOM: 1! important; FONT-FAMILY: Arial; WORD-WRAP: break-word"> <p style="MARGIN: 5px; LINE-HEIGHT: 18px">The client's call to readline may happen before the server's RST is received by the client, or it may happen after. If the readline happens before the RST is received, as we've shown in our example, the result is an unexpected EOF in the client. But if the RST arrives first, the result is an ECONNRESET ("Connection reset by peer") error return from readline.</p> </td> </tr> </tbody> </table> </p> <p style="LINE-HEIGHT: normal">以上解释了测?的现象,writeӞ收到RST.</p> <p style="LINE-HEIGHT: normal"> <table style="TABLE-LAYOUT: auto; LINE-HEIGHT: normal; BORDER-COLLAPSE: collapse" borderColor=#999999 cellSpacing=0 cellPadding=0 width="95%" bgColor=#f1f1f1 border=1> <tbody style="LINE-HEIGHT: normal"> <tr style="LINE-HEIGHT: normal"> <td style="FONT-SIZE: 12px; FILTER: none; VISIBILITY: visible! important; WORD-BREAK: break-all; LINE-HEIGHT: normal; ZOOM: 1! important; FONT-FAMILY: Arial; WORD-WRAP: break-word"> <p style="MARGIN: 5px; LINE-HEIGHT: 18px">What happens if the client ignores the error return from readline and writes more data to the server? This can happen, for example, if the client needs to perform two writes to the server before reading anything back, with the first write eliciting the RST.</p> <p style="MARGIN: 5px; LINE-HEIGHT: 18px">The rule that applies is: When a process writes to a socket that has received an RST, the SIGPIPE signal is sent to the process. The default action of this signal is to terminate the process, so the process must catch the signal to avoid being involuntarily terminated.</p> <p style="MARGIN: 5px; LINE-HEIGHT: 18px">If the process either catches the signal and returns from the signal handler, or ignores the signal, the write operation returns EPIPE.</p> </td> </tr> </tbody> </table> </p> <p style="LINE-HEIGHT: normal">以上解释了测?Q?的现?write一个已l接受到RST的socketQ系l内怼发送SIGPIPEl发送进E,如果q程catch/ignoreq个信号Qwrite都返回EPIPE错误.</p> <p style="LINE-HEIGHT: normal">因此,UNP应用Ҏ(gu)需要处理SIGPIPE信号Q至不要用pȝ~省的处理方式处理这个信Ppȝ~省的处理方式是退E,q样你的应用很难查处处理进Eؓ什么退出?/p> <p style="LINE-HEIGHT: normal"><br style="LINE-HEIGHT: normal"><font style="LINE-HEIGHT: normal" color=#0000ff>http://blog.csdn.net/shcyd/archive/2006/10/28/1354577.aspx</font></p> <p style="LINE-HEIGHT: normal">在Unixpȝ下,如果send在等待协议传送数据时|络断开的话Q调用send的进E会接收C个SIGPIPE信号Q进E对该信L(fng)默认处理是进E终止?br style="LINE-HEIGHT: normal">在Unixpȝ下,如果recv函数在等待协议接收数据时|络断开了,那么调用recv的进E会接收C个SIGPIPE信号Q进E对该信L(fng)默认处理是进E终止?/p> <p style="LINE-HEIGHT: normal">处理Ҏ(gu)Q?br style="LINE-HEIGHT: normal">在初始化时调?strong style="LINE-HEIGHT: normal"><font style="LINE-HEIGHT: normal" color=#333399>signal(SIGPIPE,SIG_IGN)</font></strong>忽略该信P只需一ơ)<br style="LINE-HEIGHT: normal">其时send或recv函数返?1Qerrno为EPIPEQ可视情况关闭socket或其他处?/p> <p style="LINE-HEIGHT: normal">gdbQ?br style="LINE-HEIGHT: normal">gdb默认收到sigpipe时中断程序,可调?strong style="LINE-HEIGHT: normal"><font style="LINE-HEIGHT: normal" color=#333399>handle SIGPIPE nostop print</font></strong></p> <p style="LINE-HEIGHT: normal"><font style="LINE-HEIGHT: normal" color=#993300>相关</font></p> <p style="LINE-HEIGHT: normal"><strong style="LINE-HEIGHT: normal">(1)SIG_DFL信号专用的默认动?</strong><br style="LINE-HEIGHT: normal">  (a)如果默认动作是暂停线E,则该U程的执行被暂时挂v。当U程暂停期间Q发送给U程的Q何附加信号都不交付,直到该线E开始执行,但是SIGKILL除外?br style="LINE-HEIGHT: normal">  (b)把挂起信L(fng)信号动作讄成SIG_DFLQ且光认动作是忽略信号 (SIGCHLD)?/p> <p style="LINE-HEIGHT: normal"><strong style="LINE-HEIGHT: normal">(2)SIG_IGN忽略信号</strong><br style="LINE-HEIGHT: normal">  (a)该信L(fng)交付对线E没有媄?br style="LINE-HEIGHT: normal">  (b)pȝ不允许把SIGKILL或SIGTOP信号的动作设|ؓSIG_DFL</p> <p style="LINE-HEIGHT: normal"><strong style="LINE-HEIGHT: normal">(3)指向函数的指?-捕获信号</strong><br style="LINE-HEIGHT: normal">  (a)信号一l交付,接收U程在指定地址上执行信hL(fng)序。在信号?获函数返回后Q接受线E必d被中断点恢复执行?br style="LINE-HEIGHT: normal">  (b)用C语言函数调用的方法进入信h捉程?<br style="LINE-HEIGHT: normal">    void func (signo)<br style="LINE-HEIGHT: normal">    int signo;<br style="LINE-HEIGHT: normal">    func( )是指定的信号捕捉函数Qsigno是正被交付信L(fng)~码<br style="LINE-HEIGHT: normal">  (c)如果SIGFPE,SIGILL或SIGSEGV信号不是由C标准定义的kill( )或raise( )函数所生成Q则从信号SIGFPE,SIGILL,SIGSEGV的信h获函数正常返回后U程的行为是未定义的?br style="LINE-HEIGHT: normal">  (d)pȝ不允许线E捕获SIGKILL和SIGSTOP信号?br style="LINE-HEIGHT: normal">  (e)如果U程为SIGCHLD信号建立信号捕获函数Q而该U程有未被等待的以终止的子线E时Q没有规定是否要生成SIGCHLD信号来指明那个子U程?/p> <p style="LINE-HEIGHT: normal">每一U信号都被OSKitl予了一个符号名Q对?2位的i386q_而言Q一个字32位,因而信h32U。下面的表给Z常用的符号名、描q和它们的信号倹{?/p> <p style="LINE-HEIGHT: normal">W号名  信号?描述                是否W合POSIX<br style="LINE-HEIGHT: normal">SIGHUP  1   在控制终端上到挂断或控制线E死亡  ?br style="LINE-HEIGHT: normal">SIGINT  2   交互注意信号              ?br style="LINE-HEIGHT: normal">SIGQUIT  3   交互中止信号              ?br style="LINE-HEIGHT: normal">SIGILL  4   到非法g的指令          ?br style="LINE-HEIGHT: normal">SIGTRAP  5   从陷׃回朔              ?br style="LINE-HEIGHT: normal">SIGABRT  6   异常l止信号              ?br style="LINE-HEIGHT: normal">SIGEMT  7   EMT 指o                ?br style="LINE-HEIGHT: normal">SIGFPE  8   不正的术操作信号          ?br style="LINE-HEIGHT: normal">SIGKILL  9   l止信号                ?br style="LINE-HEIGHT: normal">SIGBUS  10   ȝ错误                ?br style="LINE-HEIGHT: normal">SIGSEGV  11   到非法的内存调用          ?br style="LINE-HEIGHT: normal">SIGSYS  12   pȝcall的错误参数           ?br style="LINE-HEIGHT: normal">SIGPIPE  13   在无读者的道上写           ?br style="LINE-HEIGHT: normal">SIGALRM  14   报时信号                ?br style="LINE-HEIGHT: normal">SIGTERM  15   l止信号                ?br style="LINE-HEIGHT: normal">SIGURG  16   IO信道紧急信受            ?br style="LINE-HEIGHT: normal">SIGSTOP  17   暂停信号                ?br style="LINE-HEIGHT: normal">SIGTSTP  18   交互暂停信号              ?br style="LINE-HEIGHT: normal">SIGCONT  19   如果暂停则l             ?br style="LINE-HEIGHT: normal">SIGCHLD  20   子线E终止或暂停            ?br style="LINE-HEIGHT: normal">SIGTTIN  21   后台U程l一成员试图从控制终端上d  ?br style="LINE-HEIGHT: normal">SIGTTOU  22   后台U程l的成员试图写到控制l端上   ?br style="LINE-HEIGHT: normal">SIGIO   23   允许I/O信号               ?br style="LINE-HEIGHT: normal">SIGXCPU  24   出CPU旉               ?br style="LINE-HEIGHT: normal">SIGXFSZ  25   出文g大小限制            ?br style="LINE-HEIGHT: normal">SIGVTALRM 26   虚时间警报器              ?br style="LINE-HEIGHT: normal">SIGPROF  27   侧面旉警报器             ?br style="LINE-HEIGHT: normal">SIGWINCH 28   H口大小的更攏V            ?br style="LINE-HEIGHT: normal">SIGINFO  29   消息h                ?br style="LINE-HEIGHT: normal"><clk style="LINE-HEIGHT: normal"></clk>SIGUSR1  30   保留作ؓ<nobr style="COLOR: rgb(102,0,255); LINE-HEIGHT: normal; BORDER-BOTTOM: rgb(102,0,255) 1px dotted; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline">用户</nobr>自定义的信号1        ?br style="LINE-HEIGHT: normal">SIGUSR2  31   保留作ؓ用户自定义的信号        ?span class=Apple-converted-space> </span><br style="LINE-HEIGHT: normal"><br style="LINE-HEIGHT: normal"><font style="LINE-HEIGHT: normal" color=#ff6600>注意</font>QLinux信号机制基本上是从Unixpȝ中承过来的。早期Unixpȝ中的信号机制比较单和原始Q后来在实践中暴露出一些问题,因此Q把那些建立在早期机制上的信号叫?不可靠信?Q信号值小于SIGRTMIN(Red hat 7.2中,SIGRTMIN=32QSIGRTMAX=63)的信号都是不可靠信号。这是"不可靠信?的来源。它的主要问题是Q进E每ơ处理信号后Q就对信号的响应设|ؓ默认动作。在某些情况下,导致对信号的错误处理;因此Q用户如果不希望q样的操作,那么p在信号处理函数结ֆ一ơ调用signal()Q重新安装该信号?/p> <p style="LINE-HEIGHT: normal"><br style="LINE-HEIGHT: normal"></p> <p style="LINE-HEIGHT: normal"></p> <p style="LINE-HEIGHT: normal">另外Q我再做一些补充,产生RST响应以至于系l发出SIGPIPE信号Q应该分ZU情?</p> <p style="LINE-HEIGHT: normal">1. 客户端到服务端之间网l断掉,或者服务端断电(sh){,物理q接断掉了,q种情况下客L(fng)不会退出,send函数正常执行Q不会感觉到自己出错。因为由于物理网l断开Q服务端不会l客L(fng)回应错误消息Q没有RST响应Q自然也不会产生SIGPIPE信号。但是当服务端再恢复正常的时候,对客L(fng)send来的消息会生RST响应Q客L(fng)收到SIGPIPE信号了,E序退出,但是q时send函数是能够返?-1的。可以进行异常处理?/p> <p style="LINE-HEIGHT: normal">2.客户端到服务端的|络能通,服务E序挂掉Q客L(fng)E序会马上退出,因ؓ服务端能正常q回错误消息Q客L(fng)收到QSIGPIPE信号׃生了。不q我不确定此时服务端q回是的RST响应Q抓包来看没有RST标志。水qx限,只写到这了?/p> <p style="LINE-HEIGHT: normal"><br style="LINE-HEIGHT: normal"></p> <p style="LINE-HEIGHT: normal">文章出处Q?a style="LINE-HEIGHT: normal" ><u><font color=#0000ff>http://www.diybl.com/course/6_system/linux/Linuxjs/20081020/150832.html</font></u></a></p> </div> </td> </tr> </tbody> </table> </span></span><br class=Apple-interchange-newline> <img src ="http://www.shnenglu.com/elva/aggbug/90761.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/elva/" target="_blank">叶子</a> 2009-07-21 18:56 <a href="http://www.shnenglu.com/elva/archive/2009/07/21/90761.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于SIGPIPED的程序退?/title><link>http://www.shnenglu.com/elva/archive/2008/09/10/61544.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Wed, 10 Sep 2008 14:49:00 GMT</pubDate><guid>http://www.shnenglu.com/elva/archive/2008/09/10/61544.html</guid><wfw:comment>http://www.shnenglu.com/elva/comments/61544.html</wfw:comment><comments>http://www.shnenglu.com/elva/archive/2008/09/10/61544.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/elva/comments/commentRss/61544.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/elva/services/trackbacks/61544.html</trackback:ping><description><![CDATA[<p>攉一些网上的资料Q以便参考:<br><br><a >http://blog.chinaunix.net/u2/69143/showart_1087349.html</a><br><br>     当服务器close一个连接时Q若client端接着发数据。根据TCP协议的规定,会收C个RST响应Qclient再往q个服务器发送数据时Q系l会发出一个SIGPIPE信号l进E,告诉q程q个q接已经断开了,不要再写了?br>    Ҏ(gu)信号的默认处理规则SIGPIPE信号的默认执行动作是terminate(l止、退?,所以client会退出。若不想客户端退出可以把SIGPIPE设ؓSIG_IGN<br><br>    ?    signal(SIGPIPE,SIG_IGN);<br>    q时SIGPIPE交给了系l处理?br><br>  服务器采用了fork的话Q要攉垃圾q程Q防止僵进E的产生Q可以这样处理:<br>  signal(SIGCHLD,SIG_IGN); 交给pȝinitd收?br>   q里子进E就不会产生僵尸q程了?br><br><br>http://www.cublog.cn/u/31357/showart_242605.html</p> <br>好久没做qC开发了Q最q重操旧业? <div>听说另外一个项目组socket开发遇到问题,发送端和接受端数据大小不一致。徏议他们采用writen的重发机Ӟ以避免信号中断错误。采用后q是有问题。PM让我帮忙研究下?/div> <div>UNP nq以前看q,很久没做q底层开发,手边也没有UNP vol1q本书,所以做了个试E序Q研I下实际可能发生的情况了?/div> <div> </div> <div>试环境QAS3和redhat 9(~省没有nc)</div> <div> </div> <div>先下载unp源码:</div> <div>wget http://www.unpbook.com/unpv13e.tar.gz</div> <div>tar xzvf *.tar.gz;</div> <div>configure;make lib.</div> <div>然后参考str_cli.c和tcpcli01.cQ写了测试代码client.c</div> <div> </div> <div> </div> <table style="border-collapse: collapse;" bgcolor="#f1f1f1" border="1" bordercolor="#999999" cellpadding="0" cellspacing="0" width="95%"> <tbody> <tr> <td> <p style="margin: 5px; line-height: 150%;"><code><span style="color: #000000;"><span style="color: #0000cc;">#</span><span style="color: #ff0000;">include</span>    <span style="color: #ff00ff;">"unp.h"</span><br><br><span style="color: #0000cc;">#</span><span style="color: #ff0000;">define</span> MAXBUF 40960<br><span style="color: #0000ff;">void</span> processSignal<span style="color: #0000cc;">(</span><span style="color: #0000ff;">int</span> signo<span style="color: #0000cc;">)</span><br><span style="color: #0000cc;">{</span><br>    <span style="color: #ff0000;">printf</span><span style="color: #0000cc;">(</span><span style="color: #ff00ff;">"Signal is %d\n"</span><span style="color: #0000cc;">,</span> signo<span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>    <span style="color: #ff0000;">signal</span><span style="color: #0000cc;">(</span>signo<span style="color: #0000cc;">,</span> processSignal<span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br><span style="color: #0000cc;">}</span><br><span style="color: #0000ff;">void</span><br>str_cli<span style="color: #0000cc;">(</span><span style="color: #ff0000;">FILE</span> <span style="color: #0000cc;">*</span>fp<span style="color: #0000cc;">,</span> <span style="color: #0000ff;">int</span> sockfd<span style="color: #0000cc;">)</span><br><span style="color: #0000cc;">{</span><br>    <span style="color: #0000ff;">char</span>    sendline<span style="color: #0000cc;">[</span>MAXBUF<span style="color: #0000cc;">]</span><span style="color: #0000cc;">,</span> recvline<span style="color: #0000cc;">[</span>MAXBUF<span style="color: #0000cc;">]</span><span style="color: #0000cc;">;</span><br><br>    <span style="color: #0000ff;">while</span> <span style="color: #0000cc;">(</span>1<span style="color: #0000cc;">)</span> <span style="color: #0000cc;">{</span><br><br>        <span style="color: #ff0000;">memset</span><span style="color: #0000cc;">(</span>sendline<span style="color: #0000cc;">,</span> <span style="color: #ff00ff;">'a'</span><span style="color: #0000cc;">,</span> <span style="color: #0000ff;">sizeof</span><span style="color: #0000cc;">(</span>sendline<span style="color: #0000cc;">)</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>        <span style="color: #ff0000;">printf</span><span style="color: #0000cc;">(</span><span style="color: #ff00ff;">"Begin send %d data\n"</span><span style="color: #0000cc;">,</span> MAXBUF<span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>        Writen<span style="color: #0000cc;">(</span>sockfd<span style="color: #0000cc;">,</span> sendline<span style="color: #0000cc;">,</span> <span style="color: #0000ff;">sizeof</span><span style="color: #0000cc;">(</span>sendline<span style="color: #0000cc;">)</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>        <span style="color: #ff0000;">sleep</span><span style="color: #0000cc;">(5</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br><br>    <span style="color: #0000cc;">}</span><br><span style="color: #0000cc;">}</span><br><br><span style="color: #0000ff;">int</span><br>main<span style="color: #0000cc;">(</span><span style="color: #0000ff;">int</span> argc<span style="color: #0000cc;">,</span> <span style="color: #0000ff;">char</span> <span style="color: #0000cc;">*</span><span style="color: #0000cc;">*</span>argv<span style="color: #0000cc;">)</span><br><span style="color: #0000cc;">{</span><br>    <span style="color: #0000ff;">int</span>                    sockfd<span style="color: #0000cc;">;</span><br>    <span style="color: #0000ff;">struct</span> <span style="color: #ff0000;">sockaddr_in</span>    servaddr<span style="color: #0000cc;">;</span><br><br>    <span style="color: #ff0000;">signal</span><span style="color: #0000cc;">(</span>SIGPIPE<span style="color: #0000cc;">,</span> <span style="color: #ff0000;">SIG_IGN</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>    <span style="color: #ff9900;">//signal(SIGPIPE, processSignal);<br></span><br>    <span style="color: #0000ff;">if</span> <span style="color: #0000cc;">(</span>argc <span style="color: #0000cc;">!</span><span style="color: #0000cc;">=</span> 2<span style="color: #0000cc;">)</span><br>        err_quit<span style="color: #0000cc;">(</span><span style="color: #ff00ff;">"usage: tcpcli [port]"</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br><br>    sockfd <span style="color: #0000cc;">=</span> <span style="color: #ff0000;">Socket</span><span style="color: #0000cc;">(</span><span style="color: #ff0000;">AF_INET</span><span style="color: #0000cc;">,</span> <span style="color: #ff0000;">SOCK_STREAM</span><span style="color: #0000cc;">,</span> 0<span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br><br>    bzero<span style="color: #0000cc;">(</span><span style="color: #0000cc;">&</span>servaddr<span style="color: #0000cc;">,</span> <span style="color: #0000ff;">sizeof</span><span style="color: #0000cc;">(</span>servaddr<span style="color: #0000cc;">)</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>    servaddr<span style="color: #0000cc;">.</span>sin_family <span style="color: #0000cc;">=</span> <span style="color: #ff0000;">AF_INET</span><span style="color: #0000cc;">;</span><br>    servaddr<span style="color: #0000cc;">.</span>sin_port <span style="color: #0000cc;">=</span> <span style="color: #ff0000;">htons</span><span style="color: #0000cc;">(</span><span style="color: #ff0000;">atoi</span><span style="color: #0000cc;">(</span>argv<span style="color: #0000cc;">[</span>1<span style="color: #0000cc;">]</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>    Inet_pton<span style="color: #0000cc;">(</span><span style="color: #ff0000;">AF_INET</span><span style="color: #0000cc;">,</span> <span style="color: #ff00ff;">"127.0.0.1"</span><span style="color: #0000cc;">,</span> <span style="color: #0000cc;">&</span>servaddr<span style="color: #0000cc;">.</span>sin_addr<span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br><br>    <span style="color: #ff0000;">Connect</span><span style="color: #0000cc;">(</span>sockfd<span style="color: #0000cc;">,</span> <span style="color: #0000cc;">(</span>SA <span style="color: #0000cc;">*</span><span style="color: #0000cc;">)</span> <span style="color: #0000cc;">&</span>servaddr<span style="color: #0000cc;">,</span> <span style="color: #0000ff;">sizeof</span><span style="color: #0000cc;">(</span>servaddr<span style="color: #0000cc;">)</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br><br>    str_cli<span style="color: #0000cc;">(</span><span style="color: #ff0000;">stdin</span><span style="color: #0000cc;">,</span> sockfd<span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span>        <span style="color: #ff9900;">/* do it all */</span><br><br>    <span style="color: #ff0000;">exit</span><span style="color: #0000cc;">(</span>0<span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br><span style="color: #0000cc;">}</span><br></span></code></p> </td> </tr> </tbody> </table> <p> </p> <p>Z方便观察错误输出Qlib/writen.c也做了修改,加了些日志:</p> <p> </p> <p> </p> <table style="border-collapse: collapse;" bgcolor="#f1f1f1" border="1" bordercolor="#999999" cellpadding="0" cellspacing="0" width="95%"> <tbody> <tr> <td> <p style="margin: 5px; line-height: 150%;"><code><span style="color: #000000;"><span style="color: #ff9900;">/* include writen */</span><br><span style="color: #0000cc;">#</span><span style="color: #ff0000;">include</span>    <span style="color: #ff00ff;">"unp.h"</span><br><br>ssize_t                        <span style="color: #ff9900;">/* Write "n" bytes to a descriptor. */</span><br>writen<span style="color: #0000cc;">(</span><span style="color: #0000ff;">int</span> fd<span style="color: #0000cc;">,</span> <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">void</span> <span style="color: #0000cc;">*</span>vptr<span style="color: #0000cc;">,</span> <span style="color: #ff0000;">size_t</span> n<span style="color: #0000cc;">)</span><br><span style="color: #0000cc;">{</span><br>    <span style="color: #ff0000;">size_t</span>        nleft<span style="color: #0000cc;">;</span><br>    ssize_t        nwritten<span style="color: #0000cc;">;</span><br>    <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span>    <span style="color: #0000cc;">*</span>ptr<span style="color: #0000cc;">;</span><br><br>    ptr <span style="color: #0000cc;">=</span> vptr<span style="color: #0000cc;">;</span><br>    nleft <span style="color: #0000cc;">=</span> n<span style="color: #0000cc;">;</span><br>    <span style="color: #0000ff;">while</span> <span style="color: #0000cc;">(</span>nleft <span style="color: #0000cc;">></span> 0<span style="color: #0000cc;">)</span> <span style="color: #0000cc;">{</span><br>        <span style="color: #ff0000;">printf</span><span style="color: #0000cc;">(</span><span style="color: #ff00ff;">"Begin Writen %d\n"</span><span style="color: #0000cc;">,</span> nleft<span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>        <span style="color: #0000ff;">if</span> <span style="color: #0000cc;">(</span> <span style="color: #0000cc;">(</span>nwritten <span style="color: #0000cc;">=</span> <span style="color: #ff0000;">write</span><span style="color: #0000cc;">(</span>fd<span style="color: #0000cc;">,</span> ptr<span style="color: #0000cc;">,</span> nleft<span style="color: #0000cc;">)</span><span style="color: #0000cc;">)</span> <span style="color: #0000cc;"><</span><span style="color: #0000cc;">=</span> 0<span style="color: #0000cc;">)</span> <span style="color: #0000cc;">{</span><br>            <span style="color: #0000ff;">if</span> <span style="color: #0000cc;">(</span>nwritten <span style="color: #0000cc;"><</span> 0 <span style="color: #0000cc;">&</span><span style="color: #0000cc;">&</span> <span style="color: #ff0000;">errno</span> <span style="color: #0000cc;">=</span><span style="color: #0000cc;">=</span> EINTR<span style="color: #0000cc;">)</span> <span style="color: #0000cc;">{</span><br>                <span style="color: #ff0000;">printf</span><span style="color: #0000cc;">(</span><span style="color: #ff00ff;">"intterupt\n"</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>                nwritten <span style="color: #0000cc;">=</span> 0<span style="color: #0000cc;">;</span>        <span style="color: #ff9900;">/* and call write() again */</span><br>            <span style="color: #0000cc;">}</span><br>            <span style="color: #0000ff;">else</span><br>                <span style="color: #0000ff;">return</span><span style="color: #0000cc;">(</span><span style="color: #0000cc;">-</span>1<span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span>            <span style="color: #ff9900;">/* error */</span><br>        <span style="color: #0000cc;">}</span><br><br>        nleft <span style="color: #0000cc;">-</span><span style="color: #0000cc;">=</span> nwritten<span style="color: #0000cc;">;</span><br>        ptr <span style="color: #0000cc;">+</span><span style="color: #0000cc;">=</span> nwritten<span style="color: #0000cc;">;</span><br>        <span style="color: #ff0000;">printf</span><span style="color: #0000cc;">(</span><span style="color: #ff00ff;">"Already write %d, left %d, errno=%d\n"</span><span style="color: #0000cc;">,</span> nwritten<span style="color: #0000cc;">,</span> nleft<span style="color: #0000cc;">,</span> <span style="color: #ff0000;">errno</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>    <span style="color: #0000cc;">}</span><br>    <span style="color: #0000ff;">return</span><span style="color: #0000cc;">(</span>n<span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br><span style="color: #0000cc;">}</span><br><span style="color: #ff9900;">/* end writen */</span><br><br><span style="color: #0000ff;">void</span><br>Writen<span style="color: #0000cc;">(</span><span style="color: #0000ff;">int</span> fd<span style="color: #0000cc;">,</span> <span style="color: #0000ff;">void</span> <span style="color: #0000cc;">*</span>ptr<span style="color: #0000cc;">,</span> <span style="color: #ff0000;">size_t</span> nbytes<span style="color: #0000cc;">)</span><br><span style="color: #0000cc;">{</span><br>    <span style="color: #0000ff;">if</span> <span style="color: #0000cc;">(</span>writen<span style="color: #0000cc;">(</span>fd<span style="color: #0000cc;">,</span> ptr<span style="color: #0000cc;">,</span> nbytes<span style="color: #0000cc;">)</span> <span style="color: #0000cc;">!</span><span style="color: #0000cc;">=</span> nbytes<span style="color: #0000cc;">)</span><br>        err_sys<span style="color: #0000cc;">(</span><span style="color: #ff00ff;">"writen error"</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br><span style="color: #0000cc;">}</span><br></span></code></p> </td> </tr> </tbody> </table> <p> </p> <p>client.c攑֜tcpclieserv目录下,修改了MakefileQ增加了client.c的编译目?/p> <p> </p> <table style="border-collapse: collapse;" bgcolor="#f1f1f1" border="1" bordercolor="#999999" cellpadding="0" cellspacing="0" width="95%"> <tbody> <tr> <td> <p style="margin: 5px; line-height: 150%;"><code><span style="color: #000000;"><br>client<span style="color: #0000cc;">:</span> client<span style="color: #0000cc;">.</span>c<br>                $<span style="color: #0000cc;">{</span>CC<span style="color: #0000cc;">}</span> $<span style="color: #0000cc;">{</span>CFLAGS<span style="color: #0000cc;">}</span> <span style="color: #0000cc;">-</span>o $@ $<span style="color: #0000cc;"><</span> $<span style="color: #0000cc;">{</span>LIBS<span style="color: #0000cc;">}</span><br></span></code></p> </td> </tr> </tbody> </table> <p> </p> <p>接着可以开始测试了?/p> <h2>试1 忽略SIGPIPE信号Qwriten之前Q对方关闭接受进E?/h2> <p>本机服务端:</p> <div>nc -l -p 30000</div> <div> </div> <div>本机客户?</div> <div>./client 30000</div> <div>Begin send 40960 data<br>Begin Writen 40960<br>Already write 40960, left 0, errno=0<br>Begin send 40960 data<br>Begin Writen 40960<br>Already write 40960, left 0, errno=0<br><font color="#ff0000">执行C步停止服务端,client会l显C?</font></div> <div>Begin send 40960 data<br>Begin Writen 40960<br>writen error: Broken pipe(32)<br><strong>l论:可见write之前Q对方socket中断Q发送端write会返?1,errno号ؓEPIPE(32)</strong></div> <div> <h2>试2 catch SIGPIPE信号Qwriten之前Q对方关闭接受进E?/h2> <p>修改客户端代码,catch sigpipe信号</p> <p> <table style="border-collapse: collapse;" bgcolor="#f1f1f1" border="1" bordercolor="#999999" cellpadding="0" cellspacing="0" width="95%"> <tbody> <tr> <td> <p style="margin: 5px; line-height: 150%;"><code><span style="color: #000000;"><font face="新宋?><span style="color: #ff9900;"><font color="#000000">        </font>//signal(SIGPIPE, SIG_IGN);<br></span><br>        <span style="color: #ff0000;">signal</span><span style="color: #0000cc;">(</span>SIGPIPE<span style="color: #0000cc;">,</span> processSignal<span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span></font><br></span></code></p> </td> </tr> </tbody> </table> </p> <p>本机服务端:</p> <div>nc -l -p 30000</div> <div> </div> <div>本机客户?</div> <div>make client</div> <div>./client 30000</div> </div> <div> <div>Begin send 40960 data<br>Begin Writen 40960<br>Already write 40960, left 0, errno=0<br>Begin send 40960 data<br>Begin Writen 40960<br>Already write 40960, left 0, errno=0<br><font color="#ff0000">执行C步停止服务端,client会l显C?</font></div> <div>Begin send 40960 data<br>Begin Writen 40960<br>Signal is 13<br>writen error: Broken pipe(32)<br><strong>l论:可见write之前Q对方socket中断Q发送端writeӞ会先调用SIGPIPE响应函数Q然后writeq回-1,errno号ؓEPIPE(32)</strong></div> <div><strong></strong> </div> <div> <h2>试3 writenq程中,Ҏ(gu)关闭接受q程</h2> <p>Z方便操作Q加?ơwrite的数据量Q修改MAXBUF?096000</p> <p>本机服务端:</p> <div>nc -l -p 30000</div> <div> </div> <div>本机客户?</div> <div>make client</div> <div>./client 30000</div> <div> <div>Begin send 4096000 data<br>Begin Writen 4096000<br><font color="#ff0000">执行C步停止服务端,client会l显C?</font></div> <div>Already write 589821, left 3506179, errno=0<br>Begin Writen 3506179<br>writen error: Connection reset by peer(104)<br><br><strong>l论:可见socket write中,Ҏ(gu)socket中断Q发送端write会先q回已经发送的字节?再次write时返?1,errno号ؓECONNRESET(104)</strong></div> </div> <p>Z么以上测试,都是Ҏ(gu)已经中断socket后,发送端再次writeQ结果会有所不同呢。从后来扑ֈ的UNP5.12,5.13能找到答?/p> </div> </div> <table style="border-collapse: collapse;" bgcolor="#f1f1f1" border="1" bordercolor="#999999" cellpadding="0" cellspacing="0" width="95%"> <tbody> <tr> <td> <p style="margin: 5px; line-height: 150%;">The client's call to readline may happen before the server's RST is received by the client, or it may happen after. If the readline happens before the RST is received, as we've shown in our example, the result is an unexpected EOF in the client. But if the RST arrives first, the result is an ECONNRESET ("Connection reset by peer") error return from readline. </p> </td> </tr> </tbody> </table> <p>以上解释了测?的现象,writeӞ收到RST.</p> <table style="border-collapse: collapse;" bgcolor="#f1f1f1" border="1" bordercolor="#999999" cellpadding="0" cellspacing="0" width="95%"> <tbody> <tr> <td> <p style="margin: 5px; line-height: 150%;">What happens if the client ignores the error return from readline and writes more data to the server? This can happen, for example, if the client needs to perform two writes to the server before reading anything back, with the first write eliciting the RST.</p> <p style="margin: 5px; line-height: 150%;">The rule that applies is: When a process writes to a socket that has received an RST, the SIGPIPE signal is sent to the process. The default action of this signal is to terminate the process, so the process must catch the signal to avoid being involuntarily terminated.</p> <p style="margin: 5px; line-height: 150%;">If the process either catches the signal and returns from the signal handler, or ignores the signal, the write operation returns EPIPE. </p> </td> </tr> </tbody> </table> <p>以上解释了测?Q?的现?write一个已l接受到RST的socketQ系l内怼发送SIGPIPEl发送进E,如果q程catch/ignoreq个信号Qwrite都返回EPIPE错误.</p> <p>因此,UNP应用Ҏ(gu)需要处理SIGPIPE信号Q至不要用pȝ~省的处理方式处理这个信Ppȝ~省的处理方式是退E,q样你的应用很难查处处理进Eؓ什么退出?/p> <br><a >http://blog.csdn.net/shcyd/archive/2006/10/28/1354577.aspx</a><br><br> <p>在Unixpȝ下,如果send在等待协议传送数据时|络断开的话Q调用send的进E会接收C个SIGPIPE信号Q进E对该信L(fng)默认处理是进E终止?br>在Unixpȝ下,如果recv函数在等待协议接收数据时|络断开了,那么调用recv的进E会接收C个SIGPIPE信号Q进E对该信L(fng)默认处理是进E终止?/p> <p>处理Ҏ(gu)Q?br>在初始化时调?strong><font color="#333399">signal(SIGPIPE,SIG_IGN)</font></strong>忽略该信P只需一ơ)<br>其时send或recv函数返?1Qerrno为EPIPEQ可视情况关闭socket或其他处?/p> <p>gdbQ?br>gdb默认收到sigpipe时中断程序,可调?strong><font color="#333399">handle SIGPIPE nostop print</font></strong></p> <p><font color="#993300">相关</font><br></p> <p><strong>(1)SIG_DFL信号专用的默认动?</strong><br>  (a)如果默认动作是暂停线E,则该U程的执行被暂时挂v。当U程暂停期间Q发送给U程的Q何附加信号都不交付,直到该线E开始执行,但是SIGKILL除外?br>  (b)把挂起信L(fng)信号动作讄成SIG_DFLQ且光认动作是忽略信号 (SIGCHLD)?</p> <p><strong>(2)SIG_IGN忽略信号</strong><br>  (a)该信L(fng)交付对线E没有媄?br>  (b)pȝ不允许把SIGKILL或SIGTOP信号的动作设|ؓSIG_DFL </p> <p><strong>(3)指向函数的指?-捕获信号</strong><br>  (a)信号一l交付,接收U程在指定地址上执行信hL(fng)序。在信号?获函数返回后Q接受线E必d被中断点恢复执行?br>  (b)用C语言函数调用的方法进入信h捉程?<br>    void func (signo)<br>    int signo;<br>    func( )是指定的信号捕捉函数Qsigno是正被交付信L(fng)~码<br>  (c)如果SIGFPE,SIGILL或SIGSEGV信号不是由C标准定义的kill( )或raise( )函数所生成Q则从信号SIGFPE,SIGILL,SIGSEGV的信h获函数正常返回后U程的行为是未定义的?br>  (d)pȝ不允许线E捕获SIGKILL和SIGSTOP信号?br>  (e)如果U程为SIGCHLD信号建立信号捕获函数Q而该U程有未被等待的以终止的子线E时Q没有规定是否要生成SIGCHLD信号来指明那个子U程?br><br></p> <p>每一U信号都被OSKitl予了一个符号名Q对?2位的i386q_而言Q一个字32位,因而信h32U。下面的表给Z常用的符号名、描q和它们的信号倹{?</p> <p>W号名  信号?描述                是否W合POSIX<br>SIGHUP  1   在控制终端上到挂断或控制线E死亡  ?br>SIGINT  2   交互注意信号              ?br>SIGQUIT  3   交互中止信号              ?br>SIGILL  4   到非法g的指令          ?br>SIGTRAP  5   从陷׃回朔              ?br>SIGABRT  6   异常l止信号              ?br>SIGEMT  7   EMT 指o                ?br>SIGFPE  8   不正的术操作信号          ?br>SIGKILL  9   l止信号                ?br>SIGBUS  10   ȝ错误                ?br>SIGSEGV  11   到非法的内存调用          ?br>SIGSYS  12   pȝcall的错误参数           ?br>SIGPIPE  13   在无读者的道上写           ?br>SIGALRM  14   报时信号                ?br>SIGTERM  15   l止信号                ?br>SIGURG  16   IO信道紧急信受            ?br>SIGSTOP  17   暂停信号                ?br>SIGTSTP  18   交互暂停信号              ?br>SIGCONT  19   如果暂停则l             ?br>SIGCHLD  20   子线E终止或暂停            ?br>SIGTTIN  21   后台U程l一成员试图从控制终端上d  ?br>SIGTTOU  22   后台U程l的成员试图写到控制l端上   ?br>SIGIO   23   允许I/O信号               ?br>SIGXCPU  24   出CPU旉               ?br>SIGXFSZ  25   出文g大小限制            ?br>SIGVTALRM 26   虚时间警报器              ?br>SIGPROF  27   侧面旉警报器             ?br>SIGWINCH 28   H口大小的更攏V            ?br>SIGINFO  29   消息h                ?br>SIGUSR1  30   保留作ؓ用户自定义的信号1        ?br>SIGUSR2  31   保留作ؓ用户自定义的信号        ?nbsp;<br><br><font color="#ff6600">注意</font>QLinux信号机制基本上是从Unixpȝ中承过来的。早期Unixpȝ中的信号机制比较单和原始Q后来在实践中暴露出一些问题,因此Q把那些建立在早期机制上的信号叫?不可靠信?Q信号值小于SIGRTMIN(Red hat 7.2中,SIGRTMIN=32QSIGRTMAX=63)的信号都是不可靠信号。这是"不可靠信?的来源。它的主要问题是Q进E每ơ处理信号后Q就对信号的响应设|ؓ默认动作。在某些情况下,导致对信号的错误处理;因此Q用户如果不希望q样的操作,那么p在信号处理函数结ֆ一ơ调用signal()Q重新安装该信号?/p> <br> <p><br></p> <p>另外Q我再做一些补充,产生RST响应以至于系l发出SIGPIPE信号Q应该分ZU情?</p> <p>1. 客户端到服务端之间网l断掉,或者服务端断电(sh){,物理q接断掉了,q种情况下客L(fng)不会退出,send函数正常执行Q不会感觉到自己出错。因为由于物理网l断开Q服务端不会l客L(fng)回应错误消息Q没有RST响应Q自然也不会产生SIGPIPE信号。但是当服务端再恢复正常的时候,对客L(fng)send来的消息会生RST响应Q客L(fng)收到SIGPIPE信号了,E序退出,但是q时send函数是能够返?-1的。可以进行异常处理?/p> <p>2.客户端到服务端的|络能通,服务E序挂掉Q客L(fng)E序会马上退出,因ؓ服务端能正常q回错误消息Q客L(fng)收到QSIGPIPE信号׃生了。不q我不确定此时服务端q回是的RST响应Q抓包来看没有RST标志。水qx限,只写到这了?br></p><img src ="http://www.shnenglu.com/elva/aggbug/61544.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/elva/" target="_blank">叶子</a> 2008-09-10 22:49 <a href="http://www.shnenglu.com/elva/archive/2008/09/10/61544.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>perl 把xml文g转换成csv文g http://www.shnenglu.com/elva/archive/2008/08/11/58549.html叶子叶子Mon, 11 Aug 2008 11:34:00 GMThttp://www.shnenglu.com/elva/archive/2008/08/11/58549.htmlhttp://www.shnenglu.com/elva/comments/58549.htmlhttp://www.shnenglu.com/elva/archive/2008/08/11/58549.html#Feedback0http://www.shnenglu.com/elva/comments/commentRss/58549.htmlhttp://www.shnenglu.com/elva/services/trackbacks/58549.html#!/usr/local/bin/perl

# use module
use XML::Simple;
use Data::Dumper;

# create object
$xml = new XML::Simple;

# read XML file
$data = $xml->XMLin("DebugInfo.xml", ForceArray => 1);

# print output
#print Dumper($data);
#print Dumper($data->{'employee'}[0]);
#print Dumper($data->{'employee'}[1]);

$data1=$data->{'DebugInfo'};

#print @{$data1};
open FILE,">>debug.log";
foreach $item (@{$data1}){
print FILE "${$item}{UID}[0],";
print FILE "${$item}{ChannelID}[0],";
print FILE "${$item}{IPAddress}[0],";
if (${$item}{BufferMapString}[0] =~/^HASH/)
{print FILE ",n";}
else{print FILE "${$item}{BufferMapString}[0]n"};
}
close FILE;



叶子 2008-08-11 19:34 发表评论
]]>
Linux对稀疏(SparseQ文件的支持http://www.shnenglu.com/elva/archive/2008/06/26/54662.html叶子叶子Thu, 26 Jun 2008 05:47:00 GMThttp://www.shnenglu.com/elva/archive/2008/06/26/54662.htmlhttp://www.shnenglu.com/elva/comments/54662.htmlhttp://www.shnenglu.com/elva/archive/2008/06/26/54662.html#Feedback1http://www.shnenglu.com/elva/comments/commentRss/54662.htmlhttp://www.shnenglu.com/elva/services/trackbacks/54662.html

E疏(SparseQ文件的创徏

  1. 在EXT2/EXT3文gpȝ上可以用dd创徏E疏文Ӟ

    $ dd if=/dev/zero of=fs.img bs=1M seek=1024 count=0
    0+0 records in
    0+0 records out
    $ ls -lh fs.img
    -rw-rw-r--  1 zhigang zhigang 1.0G Feb  5 19:50 fs.img
    $ du -sh fs.img
    0       fs.img

  2. 使用C语言来创Z个稀疏文件的Ҏ(gu)如下Q?br>
    $ cat sparse.c
    #include 
    <sys/types.h>
    #include 
    <sys/stat.h>
    #include 
    <fcntl.h>
    #include 
    <unistd.h>

    int main(int argc, char *argv[])
    {
        
    int fd = open("sparse.file", O_RDWR|O_CREAT);
        lseek(fd, 
    1024, SEEK_CUR);
        write(fd, 
    "\0"1);

        
    return 0;
    }


    $ gcc 
    -o sparse sparse.c
    $ .
    /sparse
    $ ls 
    -l sparse.file
    -r-x--x---  1 zhigang zhigang 1025 Feb  5 23:12 sparse.file
    ]$ du sparse.file
    4       sparse.file

  3.  使用python来创Z个稀疏文件的Ҏ(gu)如下Q?

    $ cat sparse.py
    #!/usr/bin/env python

    = open('fs.img''w')
    f.seek(
    1023)
    f.write(
    '\n')

    $ python sparse.py
    $ ls 
    -l fs.img
    -rw-rw-r--  1 zhigang zhigang 1024 Feb  5 20:15 fs.img
    $ du fs.img
    4       fs.img


    文gE疏化QsparsifyQ?/strong>

    下面的方法都可以一个文件稀疏化?br>
    1. cp:

    $ cp --sparse=always file file.sparse


    cp~省使用--sparse=autoQ会自动探测源文件中是否有空z,以决定目标文件是否ؓE疏文Ӟ使用--sparse=never会禁止创建稀疏文件?br>
    2. cpio:

    $ find file |cpio -pdmuv --sparse /tmp


    如果不加--sparse参数Q稀疏文件中的空z将被填满?

    3. tar:

    $ tar cSf - file | (cd /tmp/tt; tar xpSf -)


    如果不加 -S --sparse参数Q稀疏文件中的空z将被填满?

    文gE疏化QsparsifyQ效率比?/strong>

    下面我们创徏一?00M的稀疏文Ӟ比较一下几U文件稀疏化Ҏ(gu)的效率?

    $ dd if=/dev/zero of=file count=100 bs=1M seek=400
    100+0 records in
    100+0 records out
    $ time cp --sparse=always file file.sparse
    real    0m0.626s
    user    0m0.205s
    sys     0m0.390s

    $ time tar cSf - file | (cd /tmp; tar xpSf -)
    real    0m2.732s
    user    0m1.706s
    sys     0m0.915s

    $ time find file |cpio -pdmuv --sparse /tmp
    /tmp/file
    1024000 blocks
    real    0m2.763s
    user    0m1.793s
    sys     0m0.946s


    由此可见Q上面几U文件稀疏化的方法中Qcp的效率最高;tar和cpio׃使用道Q效率下降?

    使EXT2/EXT3文gpȝE疏化QsparsifyQ?/strong>

    如何是一个文件系l的映像文gE疏化QRon Yorston为大家提供了几种Ҏ(gu)Q我觉得下面的方法最单:

    1. 使用Ron Yorston?a >zerofree文件系l中未用的块清零?br>

    $ gcc -o zerofree zerofree.c -lext2fs
    $ ./zerofree fs.img


    2.使用cp命o使映像文件稀疏化Q?

    $ cp --sparse=always fs.img fs_sparse.img


     

    EXT2/EXT3文gpȝ的sparse_super参数

    q个参数与EXT2/EXT3是否支持Sparse文g无关Q当打开该参数时Q文件系l将使用更少的超U块QSuper blockQ备份,以节省空间?/p>

    如下的命令可以查看该参数Q?br>

    # echo stats | debugfs /dev/hda2 | grep -i features
    Filesystem features:      has_journal ext_attr resize_inode dir_index filetype needs_recovery sparse_super large_file


    或者:

    # tune2fs -l /dev/hda2 |grep "Filesystem features"
    Filesystem features:      has_journal ext_attr resize_inode dir_index filetype needs_recovery sparse_super large_file


    可以通过使用Q?

    # tune2fs -O sparse_super


    或者:

    # tune2fs -s [0|1]


    来设|该参数?

    参考资?br>

    1. Keeping filesystem images sparse:

              http://intgat.tigress.co.uk/rmy/uml/sparsify.html.



叶子 2008-06-26 13:47 发表评论
]]>
GDB调试_a及用实?/title><link>http://www.shnenglu.com/elva/archive/2008/06/18/53848.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Wed, 18 Jun 2008 05:30:00 GMT</pubDate><guid>http://www.shnenglu.com/elva/archive/2008/06/18/53848.html</guid><wfw:comment>http://www.shnenglu.com/elva/comments/53848.html</wfw:comment><comments>http://www.shnenglu.com/elva/archive/2008/06/18/53848.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/elva/comments/commentRss/53848.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/elva/services/trackbacks/53848.html</trackback:ping><description><![CDATA[ 一Q列文g清单 <br>1Q?List <br>(gdb) list line1,line2 <br>二:执行E序 <br>要想q行准备调试的程序,可用run命oQ在它后面可以跟随发l该E序的Q何参敎ͼ包括标准输入和标准输明符()和外壳通配W(*、?、[、]Q在内?<br>如果你用不带参数的run命oQgdb再ơ用你l予前一条run命o的参敎ͼq是很有用的?<br>利用set args 命o可以修改发送给E序的参敎ͼ而用show args 命o可以查看其~省参数的列表?<br>QgdbQset args –b –x <br>(gdb) show args <br>backtrace命o为堆栈提供向后跟t功能?<br>Backtrace 命o产生一张列表,包含着从最q的q程开始的所以有效过E和调用q些q程的参数?<br>三:昄数据 <br>利用print 命o可以查各个变量的倹{?<br>(gdb) print p (p为变量名) <br>whatis 命o可以昄某个变量的类?<br>(gdb) whatis p <br>type = int * <br>print 是gdb的一个功能很强的命oQ利用它可以昄被调试的语言中Q何有效的表达式。表辑ּ除了包含你程序中的变量外Q还可以包含以下内容Q?<br>l 对程序中函数的调?<br>(gdb) print find_entry(1,0) <br>l 数据l构和其他复杂对?<br>(gdb) print *table_start <br>$8={e=reference=’\000’,location=0x0,next=0x0} <br>l 值的历史成分 <br>(gdb)print $1 ($1为历史记录变?在以后可以直接引?$1 的? <br>l Zؓ数组 <br>Zؓ数组提供了一U去昄存储器块Q数l节或动态分配的存储区)内容的方法。早期的调试E序没有很好的方法将L的指针换成一个数l。就像对待参CP让我们查看内存中在变量h后面?0个整敎ͼ一个动态数l的语法如下所C: <br>base@length <br>因此Q要xC在h后面?0个元素,可以使用h@10Q?<br>(gdb)print h@10 <br>$13=(-1,345,23,-234,0,0,0,98,345,10) <br>四:<br><a target=_blank><font color=#00229c><u>断点</u></font></a><br>(breakpoint) <br>break命oQ可以简写ؓbQ可以用来在调试的程序中讄断点Q该命o有如下四UŞ式: <br>l break line-number 使程序恰好在执行l定行之前停止?<br>l break function-name 使程序恰好在q入指定的函C前停止?<br>l break line-or-function if condition 如果conditionQ条Ӟ是真Q程序到达指定行或函数时停止?<br>l break routine-name 在指定例E的入口处设|断?<br>如果该程序是由很多原文g构成的,你可以在各个原文件中讄断点Q而不是在当前的原文g中设|断点,其方法如下: <br>(gdb) break filename:line-number <br>(gdb) break filename:function-name <br>要想讄一个条件断点,可以利用break if命oQ如下所C: <br>(gdb) break line-or-function if expr <br>例: <br>(gdb) break 46 if testsize==100 <br>从断点l运行:countinue 命o <br>五.断点的管?<br>1Q?昄当前gdb的断点信息: <br>(gdb) info break <br>他会以如下的形式昄所有的断点信息Q?<br>Num Type Disp Enb Address What <br>1 breakpoint keep y 0x000028bc in init_random at qsort2.c:155 <br>2 breakpoint keep y 0x0000291c in init_organ at qsort2.c:168 <br>(gdb) <br>2.删除指定的某个断点: <br>(gdb) delete breakpoint 1 <br>该命令将会删除编号ؓ1的断点,如果不带~号参数Q将删除所有的断点 <br>(gdb) delete breakpoint <br>3.止使用某个断点 <br>(gdb) disable breakpoint 1 <br>该命令将止断点 1,同时断点信息?(Enb)域将变ؓ n <br>4Q允怋用某个断?<br>(gdb) enable breakpoint 1 <br>该命令将允许断点 1,同时断点信息?(Enb)域将变ؓ y <br>5Q清除原文g中某一代码行上的所有断?<br>(gdb)clean number <br>注:number 为原文g的某个代码行的行?<br>六.变量的检查和赋?<br>l whatis:识别数组或变量的cd <br>l ptype:比whatis的功能更强,他可以提供一个结构的定义 <br>l set variable:D予变?<br>l print 除了昄一个变量的值外Q还可以用来赋?<br>七.单步执行 <br>l next <br>不进入的单步执行 <br>l step <br>q入的单步执?<br>如果已经q入了某函数Q而想退函数q回到它的调用函CQ可使用命ofinish <br>八.函数的调?<br>l call name 调用和执行一个函?<br>(gdb) call gen_and_sork( 1234,1,0 ) <br>(gdb) call printf(“abcd”) <br>$1=4 <br>l finish l束执行当前函数Q显C其q回|如果有的话) <br>?ji).机器语言工具 <br>有一l专用的gdb变量可以用来查和修改计算机的通用寄存器,gdb提供了目前每一台计机中实际用的4个寄存器的标准名字: <br>l $pc Q?E序计数?<br>l $fp Q?帧指针(当前堆栈帧) <br>l $sp Q?栈指?<br>l $ps Q?处理器状?<br>十.信号 <br>gdb<br>通常可以捕捉到发送给它的大多CP通过捕捉信号Q它?yu)可军_对于正在q行的进E要做些什么工作。例如,按CTRL-C中断信号发送给gdbQ通常?br>会终止gdb。但是你或许不想中断gdbQ真正的目的是要中断gdb正在q行的程序,因此Qgdb要抓住该信号q停止它正在q行的程序,q样可以执行某<br>些调试操作?<br>Handle命o可控制信L(fng)处理Q他有两个参敎ͼ一个是信号名,另一个是接受Ch该作什么。几U可能的参数是: <br>l nostop 接收ChQ不要将它发送给E序Q也不要停止E序?<br>l stop 接受Ch停止E序的执行,从而允许程序调试;昄一条表C已接受CL(fng)消息Q禁止用消息除外) <br>l print 接受Ch昄一条消?<br>l noprint 接受Ch不要昄消息Q而且隐含着不停止程序运行) <br>l pass 信号发送给E序Q从而允怽的程序去处理它、停止运行或采取别的动作?<br>l nopass 停止E序q行Q但不要信号发送给E序?<br>例如Q假定你截获SIGPIPE信号Q以防止正在调试的程序接受到该信P而且只要该信号一到达Q就要求该程序停止,q知你。要完成q一dQ可利用如下命oQ?<br>(gdb) handle SIGPIPE stop print <br>h意,UNIX的信号名L采用大写字母Q你可以用信L(fng)h代信号名 <br>?br>果你的程序要执行M信号处理操作Q就需要能够测试其信号处理E序Qؓ此,需要一U能信号发送给E序的简便方法,q就是signal命o的Q务。该<br>命o的参数是一个数字或者一个名字,如SIGINT。假定你的程序已一个专用的SIGINTQ键盘输入,或CTRL-CQ信?Q信号处理程序设|成?br>取某个清理动作,要想试该信号处理程序,你可以设|一个断点ƈ使用如下命oQ?<br>QgdbQ?signal 2 <br>continuing with signal SIGINT(2) <br>该程序l执行,但是立即传输该信P而且处理E序开始运? <br>十一. 原文件的搜烦 <br>search text:该命令可昄在当前文件中包含text串的下一行?<br>Reverse-search text:该命令可以显C包含text 的前一行?<br>十二.UNIX接口 <br>shell 命o可启动UNIX外壳QCTRL-D退出外壻Iq回?gdb. <br>十三.命o的历?<br>Z允许使用历史命oQ可使用 set history expansion on 命o <br>(gdb) set history expansion on <br>结Q常用的gdb命o <br>backtrace 昄E序中的当前位置和表C如何到辑ֽ前位|的栈跟t(同义词:whereQ?<br>breakpoint 在程序中讄一个断?<br>cd 改变当前工作目录 <br>clear 删除刚才停止处的断点 <br>commands 命中断点Ӟ列出要执行的命?<br>continue 从断点开始l执?<br>delete 删除一个断Ҏ(gu)监测点;也可与其他命令一起?<br>display E序停止时显C变量和表达?<br>down 下移栈Q得另一个函数成为当前函?<br>frame 选择下一条continue命o的 <br>info 昄与该E序有关的各U信?<br>jump 在源E序中的另一点开始运?<br>kill 异常l止在gdb 控制下运行的E序 <br>list 列出相应于正在执行的E序的原文g内容 <br>next 执行下一个源E序行,从而执行其整体中的一个函?<br>print 昄变量或表辑ּ的?<br>pwd 昄当前工作目录 <br>pype 昄一个数据结构(如一个结构或C++c)的内?<br>quit 退出gdb <br>reverse-search 在源文g中反向搜索正规表辑ּ <br>run 执行该程?<br>search 在源文g中搜索正规表辑ּ <br>set variable l变量赋?<br>signal 一个信号发送到正在q行的进E?<br>step 执行下一个源E序行,必要时进入下一个函?<br>undisplay display命o的反命oQ不要显C辑ּ <br>until l束当前循环 <br>up 上移栈Q另一函数成ؓ当前函数 <br>watch 在程序中讄一个监点Q即数据断点Q?<br>whatis 昄变量或函数类?<br>**************************************************** <br> GNU的调试器UCؓgdbQ该E序是一个交互式工具Q工作在字符模式。在 X Window pȝ中,有一个gdb的前端图形工PUCؓxxgdb。gdb 是功能强大的调试E序Q可完成如下的调试Q务: <br>  * 讄断点Q?<br>  * 监视E序变量的| <br>  * E序的单步执行; <br>  * 修改变量的倹{?<br>  在可以?gdb 调试E序之前Q必M?-g 选项~译源文件。可?makefile 中如下定?CFLAGS 变量Q?<br>   CFLAGS = -g <br>   q行 gdb 调试E序旉常使用如下的命令: <br>   gdb progname <br>  ?gdb 提示W处键入helpQ将列出命o的分c,主要的分cLQ?<br>  * aliasesQ命令别?<br>  * breakpointsQ断点定义; <br>  * dataQ数据查看; <br>  * filesQ指定ƈ查看文gQ?<br>  * internalsQ维护命令; <br>  * runningQ程序执行; <br>  * stackQ调用栈查看Q?<br>  * statuQ状态查看; <br>  * tracepointsQ跟t程序执行?<br>  键入 help 后跟命o的分cdQ可获得该类命o的详l清单?<br>gdb 的常用命?<br>命o 解释 <br>  break NUM 在指定的行上讄断点?<br>  bt 昄所有的调用栈。该命o可用来显C函数的调用序?<br>  clear 删除讄在特定源文g、特定行上的断点。其用法为clear FILENAME:NUM <br>  continue l箋执行正在调试的程序。该命o用在E序׃处理信号或断点?D停止q行时?<br>  display EXPR 每次E序停止后显C辑ּ的倹{表辑ּq序定义的变量l成?<br>  file FILE 装蝲指定的可执行文gq行调试?<br>  help NAME 昄指定命o的帮助信息?<br>  info break 昄当前断点清单Q包括到达断点处的次数等?<br>  info files 昄被调试文件的详细信息?<br>  info func 昄所有的函数名称?<br>  info local 昄当函C的局部变量信息?<br>  info prog 昄被调试程序的执行状态?<br>  info var 昄所有的全局和静态变量名U?<br>  kill l止正被调试的程序?<br>  list 昄源代码段?<br>  make 在不退?gdb 的情况下q行 make 工具?<br>  next 在不单步执行q入其他函数的情况下Q向前执行一行源代码?<br>  print EXPR 昄表达?EXPR 的倹{?<br>******gdb 使用范例************************ <br>----------------- <br>清单 一个有错误?C 源程?bugging.c <br>代码: <br>----------------- <br>1 Qi nclude <br>2 <br>3 static char buff [256]; <br>4 static char* string; <br>5 int main () <br>6 { <br>7   printf ("Please input a string: "); <br>8   gets (string);   <br>9   printf ("\nYour string is: %s\n", string); <br>10 } <br>----------------- <br>  上面q个E序非常单,其目的是接受用户的输入,然后用L(fng)输入打印出来。该E序使用了一个未l过初始化的字符串地址 stringQ因此,~译q运行之后,出?Segment Fault 错误Q?<br>$ gcc -o bugging -g bugging.c <br>$ ./bugging <br>Please input a string: asfd <br>Segmentation fault (core dumped) <br>Z查找该程序中出现的问题,我们利用 gdbQƈ按如下的步骤q行Q?<br>1Q运?gdb bugging 命oQ装?bugging 可执行文Ӟ <br>2Q执行装入的 bugging 命o runQ?<br>3Q?where 命o查看E序出错的地方; <br>4Q利?list 命o查看调用 gets 函数附近的代码; <br>5Q唯一能够D gets 函数出错的因素就是变?string。用print命o查看 string 的| <br>6Q在 gdb 中,我们可以直接修改变量的|只要?string 取一个合法的指针值就可以了,为此Q我们在W?行处讄断点 break 8Q?<br>7Q程序重新运行到W?8行处停止Q这Ӟ我们可以?set variable 命o修改 string 的取| <br>8Q然后l运行,看到正的E序q行l果?br><br><br><strong>本文来自ChinaUnix博客Q如果查看原文请点:</strong><a target=_blank><u><font color=#0000ff>http://blog.chinaunix.net/u1/40912/showart_318499.html</font></u></a> <img src ="http://www.shnenglu.com/elva/aggbug/53848.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/elva/" target="_blank">叶子</a> 2008-06-18 13:30 <a href="http://www.shnenglu.com/elva/archive/2008/06/18/53848.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>包末安装完全Ӟ出错信息解决办法http://www.shnenglu.com/elva/archive/2008/04/02/46069.html叶子叶子Wed, 02 Apr 2008 09:35:00 GMThttp://www.shnenglu.com/elva/archive/2008/04/02/46069.htmlhttp://www.shnenglu.com/elva/comments/46069.htmlhttp://www.shnenglu.com/elva/archive/2008/04/02/46069.html#Feedback0http://www.shnenglu.com/elva/comments/commentRss/46069.htmlhttp://www.shnenglu.com/elva/services/trackbacks/46069.html

You might want to run `apt-get -f install' to correct these:
The following packages have unmet dependencies:
sun-java6-jre: Depends: sun-java6-bin (= 6-00-2ubuntu2) but it is not going to be installed or
                          ia32-sun-java6-bin (= 6-00-2ubuntu2) but it is not installable
E: Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution).

解决Ҏ(gu)Q?br> sudo apt-get install -f


apt-get使用参考:

apt-cache search # —?package 搜烦?
apt-cache show #—?package 获取包的相关信息Q如说明、大、版本等)
sudo apt-get install # —?package 安装?
sudo apt-get install # ?#8211;(package - - reinstall 重新安装?
sudo apt-get -f install # ?#8211;(强制安装?#”-f = –fix-missing”当是修复安装?#8230;)
sudo apt-get remove #?#8211;(package 删除?
sudo apt-get remove - - purge # —?package 删除包,包括删除配置文g{?
sudo apt-get autoremove –purge # ?(package 删除包及其依赖的软g?配置文g{(只对6.10有效Q强烈推荐))
sudo apt-get update #——更新源
sudo apt-get upgrade #——更新已安装的包
sudo apt-get dist-upgrade # ———升U系l?br> sudo apt-get dselect-upgrade #——?dselect 升
apt-cache depends #—?(package 了解使用依赖)
apt-cache rdepends # —?package 了解某个具体的依?#当是查看该包被哪些包依赖?#8230;)
sudo apt-get build-dep # —?package 安装相关的编译环?
apt-get source #—?package 下蝲该包的源代码)
sudo apt-get clean && sudo apt-get autoclean # —?#8211;清理下蝲文g的存?&& 只清理过时的?br> sudo apt-get check #—?查是否有损坏的依?/p>


叶子 2008-04-02 17:35 发表评论
]]>
Linux-C-Socket~程 http://www.shnenglu.com/elva/archive/2007/05/24/24733.html叶子叶子Wed, 23 May 2007 17:53:00 GMThttp://www.shnenglu.com/elva/archive/2007/05/24/24733.htmlhttp://www.shnenglu.com/elva/comments/24733.htmlhttp://www.shnenglu.com/elva/archive/2007/05/24/24733.html#Feedback0http://www.shnenglu.com/elva/comments/commentRss/24733.htmlhttp://www.shnenglu.com/elva/services/trackbacks/24733.html
实用套接字的四个步骤:
1 分配I间和初始化
2 q接
3 传送数?br>4 关闭

具体法:

服务器端:
#include <sys/socket.h>
#include <netinet/in.h>

int socket_descriptor;
socket_descriptor = socket(AF_INET, SOCK_STREAM, 0);

int port = 8000;
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
pin.sin_port = htons(port);

bind(socket_descriptor,(struct socketaddr *)&sin, sizeof(sin) );

listen(socket_descriptor, 1024);

struct sockaddr_in pin;
int address_size;
int temp_socket_descriptor;

while(1) {
  temp_socket_descriptor = accept(socket_descriptor,(struct socketaddr *)&pin,  sizeof(address_size));
  ......
  close(temp_socket_descriptor);
}


客户?
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>     //直接影响sockaddr_in.sin_addr的填?br>
char * host_name = "127.0.0.1";
struct hostent * server_host_name;
server_host_name = gethostbyname(host_name);

int port = 8000;
struct sockaddr_in pin;
pin.sin_family = AF_INET;
pin.sin_addr.s_addr = htol(INADDR_ANY);
pin.sin_addr.s_addr = ((struct in_addr *)(server_host_name->h_addr))->s_addr; 或?pin.sin_addr = *(struct in_addr *) server_host_name->h_addr;
pin.sin_port = htons(port);

int socket_descriptor;
socket_descriptor = socket(AF_INET, SOCK_STREAM, 0);
connect(socket_descriptor, (void *)&pin, sizeof(pin));
.......
close(socket_descriptor);


叶子 2007-05-24 01:53 发表评论
]]>
openssh配置说明 http://www.shnenglu.com/elva/archive/2007/05/24/24734.html叶子叶子Wed, 23 May 2007 17:53:00 GMThttp://www.shnenglu.com/elva/archive/2007/05/24/24734.htmlhttp://www.shnenglu.com/elva/comments/24734.htmlhttp://www.shnenglu.com/elva/archive/2007/05/24/24734.html#Feedback0http://www.shnenglu.com/elva/comments/commentRss/24734.htmlhttp://www.shnenglu.com/elva/services/trackbacks/24734.html主题Qopenssh配置说明

相关文gQ?br>  openssh-clients-2.9p2-7.rpm
  openssh-2.9p-7.rpm
  openssh-server-2.9p2-7

内容Q?br>SSH的英文全U是Secure SHell。通过使用SSHQ你可以把所有传输的数据q行加密Q这?中间?q种d方式׃可能实现了,而且也能够防止DNS和IPƺ骗。还有一个额外的好处是传输的数据是l过压羃的,所以可以加快传输的速度。SSH有很多功能,它既可以代替telnetQ又可以为ftp、pop、甚至ppp提供一个安全的"通道"?/p>

1.什么是SSHQ?br>传统的网l服务程序,如:ftp、pop和telnet在本质上都是不安全的Q因为它们在|络上用明文传送口令和数据Q别有用心的人非常容易就可以截获q些口o和数据。而且Q这些服务程序的安全验证方式也是有其q的,是很容易受?中间?Qman-in-the-middleQ这U方式的d。所?中间?的攻?yn)L式,是"中间?冒充真正的服务器接收你的传给服务器的数据Q然后再冒充你把数据传给真正的服务器。服务器和你之间的数据传送被"中间?一转手做了手脚之后Q就会出现很严重的问题?br>SSH的英文全U是Secure SHell。通过使用SSHQ你可以把所有传输的数据q行加密Q这?中间?q种d方式׃可能实现了,而且也能够防止DNS和IPƺ骗。还有一个额外的好处是传输的数据是l过压羃的,所以可以加快传输的速度。SSH有很多功能,它既可以代替telnetQ又可以为ftp、pop、甚至ppp提供一个安全的"通道"?br>最初SSH是由芬兰的一家公司开发的。但是因为受版权和加密算法的限制Q现在很多h都{而用OpenSSH。OpenSSH是SSH的替代YӞ而且是免费的Q可以预计将来会有越来越多的Z用它而不是SSH?br>SSH是由客户端和服务端的软gl成的,有两个不兼容的版本分别是Q?.x?.x。用SSH 2.x的客L(fng)序是不能q接到SSH 1.x的服务程序上ȝ。OpenSSH 2.x同时支持SSH 1.x?.x?/p>

2.SSH的安全验证是如何工作?br>从客L(fng)来看QSSH提供两种U别的安全验证?br>W一U别(Z口o的安全验证)只要你知道自己帐号和口oQ就可以d到远E主机。所有传输的数据都会被加密,但是不能保证你正在连接的服务器就是你惌接的服务器。可能会有别的服务器在冒充真正的服务器,也就是受?中间?q种方式的攻凅R?br>W二U别(Z密匙的安全验证)需要依靠密匙,也就是你必须己创Z对密匙,q把公用密匙攑֜需要访问的服务器上。如果你要连接到SSH服务器上Q客L(fng)软g׃向服务器发出hQ请求用你的密匙q行安全验证。服务器收到h之后Q先在你在该服务器的家目录下L你的公用密匙Q然后把它和你发送过来的公用密匙q行比较。如果两个密匙一_服务器就用公用密匙加?质询"QchallengeQƈ把它发送给客户端Y件。客L(fng)软g收到"质询"之后可以用你的Uh密匙解密再把它发送给服务器?br>用这U方式,你必ȝ道自己密匙的口o。但是,与第一U别相比,W二U别不需要在|络上传送口令?br>W二U别不仅加密所有传送的数据Q而且"中间?q种d方式也是不可能的Q因Z没有你的Uh密匙Q。但是整个登录的q程可能需?0U?/p>

3.安装q测试OpenSSH
因ؓ受到国法律的限Ӟ在很多Linux的发行版中都没有包括OpenSSH。但是,可以从网l上下蝲q安装OpenSSH
安装完OpenSSH之后Q用下面命o试一下:
ssh -l [your accountname on the remote host] [address of the remote host]

如果OpenSSH工作正常Q你会看C面的提示信息Q?br>The authenticity of host [hostname] can't be established.
Key fingerprint is 1024 5f:a0:0b:65:d3:82:df:ab:44:62:6d:98:9c:fe:e9:52.
Are you sure you want to continue connecting (yes/no)?
OpenSSH告诉你它不知道这C机,但是你不用担心这个问题,因ؓ你是W一ơ登录这C机。键?yes"。这把q台L?识别标记"加到"~/.ssh/know_hosts"文g中。第二次讉Kq台L的时候就不会再显C条提CZ息了?br>然后QSSH提示你输入远E主Z你的帐号的口令。输入完口o之后Q就建立了SSHq接Q这之后可以象使用telnet那样使用SSH了?/p>

4.SSH的密?br>4.1 生成你自q密匙?br>生成q分发你自己的密匙有两个好处Q?br>可以防止"中间?q种d方式
可以只用一个口令就d到所有你想登录的服务器上
用下面的命o可以生成密匙Q?br>ssh-keygen如果q程L使用的是SSH 2.xp用这个命令:

ssh-keygen -d在同一CZ同时有SSH1和SSH2的密匙是没有问题的,因ؓ密匙是存成不同的文g的?/p>

ssh-keygen命oq行之后会显CZ面的信息Q?br>Generating RSA keys: ............................ooooooO......ooooooO
Key generation complete.
Enter file in which to save the key (/home/[user]/.ssh/identity):
[按下ENTERp了]
Created directory '/home/[user]/.ssh'.
Enter passphrase (empty for no passphrase):
[输入的口令不会显C在屏幕上]
Enter same passphrase again:
[重新输入一遍口令,如果忘记了口令就只能重新生成一ơ密匙了]
Your identification has been saved in /home/[user]/.ssh/identity.
[q是你的Uh密匙]
Your public key has been saved in /home/[user]/.ssh/identity.pub.
The key fingerprint is: 2a:dc:71:2f:27:84:a2:e4:a1:1e:a9:63:e2:fa:a5:89 [user]@[local machine]
"ssh-keygen -d"做的是几乎同L(fng)事,但是把一对密匙存为(默认情况下)"/home/[user]/.ssh/id_dsa"Q私人密匙)?/home/[user]/.ssh/id_dsa.pub"Q公用密匙)?/p>

现在你有一对密匙了Q公用密匙要分发到所有你想用sshd的远E主Z去;Uh密匙要好好地保管防止别h知道你的Uh密匙。用"ls -l ~/.ssh/identity"?ls -l ~/.ssh/id_dsa"所昄的文件的讉K权限必须?-rw-------"?br>如果你怀疑自q密匙已经被别人知道了Q不要迟疑马上生成一Ҏ(gu)的密匙。当Ӟ你还要重新分发一ơ公用密匙?/p>

4.2 分发公用密匙
在每一个你需要用SSHq接的远E服务器上,你要在自q家目录下创徏一?.ssh"的子目录Q把你的公用密匙"identity.pub" 拯到这个目录下q把它重命名?authorized_keys"。然后执行:
chmod 644 .ssh/authorized_keys
q一步是必不可少的。如果除了你之外别h?authorized_keys"文g也有写的权限QSSH׃会工作?br>如果你想从不同的计算机登录到q程LQ?authorized_keys"文g也可以有多个公用密匙。在q种情况下,必须在新的计机上重新生成一对密匙,然后把生成的"identify.pub"文g拯q粘贴到q程L?authorized_keys"文g里。当然在新的计算Z你必L一个帐P而且密匙是用口o保护的。有一点很重要Q就是当你取消了q个帐号之后Q别忘了把这一对密匙删掉?/p>

5.配置SSH
5.1 配置客户端的软g
OpenSSH有三U配|方式:命o行参数、用户配|文件和pȝU的配置文gQ?/etc/ssh/ssh_config"Q。命令行参数优先于配|文Ӟ用户配置文g优先于系l配|文件。所有的命o行的参数都能在配|文件中讄。因为在安装的时候没有默认的用户配置文gQ所以要?/etc/ssh/ssh_config"拯q新命名ؓ"~/.ssh/config"?br>标准的配|文件大概是q样的:
[lots of explanations and possible options listed]
# Be paranoid by default
Host *
ForwardAgent no
ForwardX11 no
FallBackToRsh no
q有很多选项的设|可以用"man ssh"查看"CONFIGURATION FILES"q一章?br>配置文g是按序d的。先讄的选项先生效?br>假定你在Host *fbc
HostName
www.foobar.com
User bilbo
ForwardAgent yes
Compression yes
# Be paranoid by default
Host *
ForwardAgent no
ForwardX11 no
FallBackToRsh no
你输?ssh fbc"之后QSSH会自动地从配|文件中扑ֈL的全名,用你的用户名dq且?ssh-agent"理的密匙进行安全验证。这样很方便吧!
用SSHq接到其它远E计机用的q是"paranoidQ偏执)"默认讄。如果有些选项没有在配|文件或命o行中讄Q那么还是用默认的"paranoid"讄?br>在我们上面D的那个例子中Q对于到其它q有一些需要仔l看一看的讄选项是:
CheckHostIP yes   q个选项用来q行IP地址的检查以防止DNSƺ骗?/p>

CompressionLevel  压羃的别从"1"Q最快)?9"Q压~率最高)。默认gؓ"6"?/p>

ForwardX11 yes  Z在本地运行远E的XE序必须讄q个选项?/p>

LogLevel DEBUG  当SSH出现问题的时候,q选项很有用了。默认gؓ"INFO"?/p>

5.2 配置服务端的软g
SSH服务器的配置使用的是"/etc/ssh/sshd_config"配置文gQ这些选项的设|在配置文g中已l有了一些说明而且?man sshd"也可以查看帮助。请注意OpenSSH对于SSH 1.x?.x没有不同的配|文件?br>在默认的讄选项中需要注意的有:
PermitRootLogin yes   最好把q个选项讄?PermitRootLogin without-password"Q这?root"用户׃能从没有密匙的计机上登录。把q个选项讄?no"禁?root"用户dQ只能用"su"命o从普通用戯{?root"?br>X11Forwarding no   把这个选项讄?yes"允许用户q行q程L上的XE序。就禁止这个选项也不能提高服务器的安全因为用户可以安装他们自q转发器(forwarderQ,请参?man sshd"?br>PasswordAuthentication yes  把这个选项讄?no"只允许用L(fng)Z密匙的方式登录。这当然会给那些l常需要从不同Ld的用户带来麻烦,但是q能够在很大E度上提高系l的安全性。基于口令的d方式有很大的q?br># Subsystem /usr/local/sbin/sftpd   把最前面的#号去掉ƈ且把路径名设|成"/usr/bin/sftpserv"Q用户就能?sftp"Q安全的FTPQ了Qsftpserv在sftp软g包中Q。因为很多用户对FTP比较熟?zhn)而且"scp"用v来也有一些麻烦,所?sftp"q是很有用的。而且2.0.7版本以后的图形化的ftp工具"gftp"也支?sftp"?/p>

6.拯文g
6.1 ?scp"拯文g
SSH提供了一些命令和shell用来dq程服务器。在默认情况下它不允怽拯文gQ但是还是提供了一?scp"命o?br>假定你想把本地计机当前目录下的一个名?dumb"的文件拷贝到q程服务?a ?br>可以用这个命令:scp dumb
bilbo@www.foobar.com:.
把文件拷贝回来用q个命oQscp bilbo@www.foobar.com:dumb .
"scp"调用SSHq行dQ然后拷贝文Ӟ最后调用SSH关闭q个q接?br>如果在你?~/.ssh/config"文g中已lؓwww.foobar.com做了q样的配|:
Host *fbc
HostName www.foobar.com
User bilbo
ForwardAgent yes
那么你就可以?fbc"来代?bilbo@www.foobar.com"Q命令就化ؓ"scp dumb fbc:."?br>"scp"假定你在q程L上的家目录ؓ你的工作目录。如果你使用相对目录p相对于家目录?br>?scp"命o?-r"参数允许递归地拷贝目录?scp"也可以在两个不同的远E主Z间拷贝文件?br>有时候你可能会试图作q样的事Q用SSHd?a scp [local machine]:dumb ."想用它把本地?dumb"文g拯C当前d的远E服务器上。这时候你会看C面的出错信息Q?br>ssh: secure connection to [local machine] refused
之所以会出现q样的出错信息是因ؓ你运行的是远E的"scp"命oQ它试图d到在你本地计机上运行的SSH服务E序……所以最好在本地q行"scp"除非你的本地计算Zq行SSH服务E序?/p>

6.2 ?sftp"拯文g
如果你习(fn)惯用ftp的方式拷贝文Ӟ可以试着?sftp"?sftp"建立用SSH加密的安全的FTPq接通道Q允怋用标准的ftp命o。还有一个好处就?sftp"允许你通过"exec"命oq行q程的程序。从2.0.7版以后,囑Ş化的ftp客户软g"gftp"支?sftp"?br>如果q程的服务器没有安装sftp服务器Y?sftpserv"Q可以把"sftpserv"的可执行文g拯C的远E的家目录中Q或者在q程计算机的$PATH环境变量中设|的路径Q?sftp"会自动激z这个服务YӞ你没有必要在q程服务器上有什么特D的权限?/p>

6.3 ?rsync"拯文g
"rsync"是用来拷贝、更新和Udq程和本地文件的一个有用的工具Q很Ҏ(gu)可以用"-e ssh"参数和SSHl合h使用?rsync"的一个优点就是,不会拯全部的文Ӟ只会拯本地目录和远E目录中有区别的文g。而且它还使用很高效的压羃法Q这h贝的速度很快?/p>

6.4 ?加密通道"的ftp拯文g
如果你坚持要用传l的FTP客户软g。SSH可以为几乎所有的协议提供"安全通道"。FTP是一个有一点奇怪的协议Q例如需要两个端口)而且不同的服务程序和服务E序之间、客L(fng)序和客户E序之间q有一些差别?br>实现"加密通道"的方法是使用"端口转发"。你可以把一个没有用到的本地端口Q通常大于1000Q设|成转发C个远E服务器上,然后只要q接本地计算Z的这个端口就行了。有一点复杂是吗?
其实一个基本的x是Q{发一个端口,让SSH在后台运行,用下面的命oQ?br>ssh [user@remote host] -f -L 1234:[remote host]:21 tail -f /etc/motd
接着q行FTP客户Q把它设|到指定的端口:
lftp -u [username] -p 1234 localhost
当然Q用q种Ҏ(gu)很麻烦而且很容易出错。所以最好用前三种Ҏ(gu)?/p>

7.用SSH讄"加密通道"
7.1 "加密通道"的基知识
SSH?加密通道"是通过"端口转发"来实现的。你可以在本地端口(没有用到的)和在q程服务器上q行的某个服务的端口之间建立"加密通道"。然后只要连接到本地端口。所有对本地端口的请求都被SSH加密q且转发到远E服务器的端口。当然只有远E服务器上运行SSH服务器Y件的时?加密通道"才能工作。可以用下面命o查一些远E服务器是否q行SSH服务Q?br>telnet [full name of remote host] 22

如果收到q样的出错信息:telnet: Unable to connect to remote host: Connection refused

p明远E服务器上没有运行SSH服务软g?/p>

端口转发使用q样的命令语法:
ssh -f [username@remote host] -L [local port]:[full name of remote host]:[remote port] [some command]
你不仅可以{发多个端口而且可以?~/.ssh/config"文g中用"LocalForward"讄l常使用的一些{发端口?/p>

7.2 为POP加上"加密通道"
你可以用POP协议从服务器上取email。ؓPOP加上"加密通道"可以防止POP的密码被|络监听器(snifferQ监听到。还有一个好处就是SSH的压~方式可以让邮g传输得更快?br>假定你在pop.foobar.com上有一个POP帐号Q你的用户名?bilbo"你的POP口o?topsecret"。用来徏立SSH"加密通道"的命令是Q?br>ssh -f -C bilbo@pop.foobar.com -L 1234:pop.foobar.com:110 sleep 5
Q如果要试Q可以把"sleep"的值加?00Q。运行这个命令之后会提示你输入POP口oQ?br>bilbo@pop.foobar.com's password:
输入口o之后可以用"telnet"q接到本地的转发端口了?br>telnet localhost 1234
你会收到q程mail服务器的"READY"消息?br>当然Q这个方法要求你手工输入所有的POP命oQ这是很不方便的。可以用FetchmailQ参考how to configure FetchmailQ。Secure POP via SSH mini-HOWTO、man fetchmail和在"/usr/doc/fetchmail-[…]"目录下的Fetchmail的FAQ都提供了一些具体的例子?br>h意IMAP协议使用的是不同的端口:IMAP v2的端口号?43而IMAP v3的端口号?20?/p>

7.3 为X加上"加密通道"
如果你打在本地计算Zq行q程SSH服务器上的XE序Q那么登录到q程的计机上,创徏一个名?~/.ssh/environment"的文件ƈ加上q一行:
XAUTHORITY=/home/[remote user name]/.Xauthority

Q如果在q程L上你的家目录下不存在".Xauthority"q个文gQ那么当用SSHd的时候就会自动创建)?br>比如启动一个XE序QxtermQ可以这个命令:
ssh -f -X -l [remote user name] [remote machine] xterm
q将在远E运行xtermq个E序。其它的XE序也是用相同的Ҏ(gu)?/p>

7.4 为linuxconf加上"加密通道"
Linuxconf(http://www.solucorp.qc.ca/linuxconf/)是Linux的配|工P它支持远E管理。Linuxconf的FAQ重说明了如何通过SSH使用linuxconfQ?br>其命令ؓQremadmin --exec [link_command] linuxconf --guiproto
如果你想在两台计机之间用加密的方式传送信息,那么最好用ssh。命令是Q?br>remadmin --exec ssh -l [account] linuxconf --guiproto
q是非常有效的而且q行用图形界面管理计机?br>q种Ҏ(gu)需要在客户端安装linuxconf。其它的Ҏ(gu)q有直接d到服务器上用"X11Forwarding"或字W界面运行linuxconf?/p>

7.5 为Webmin加上"加密通道"
Webmin(ssh -f -l [remote user name] [remote host] -L 1234:[remote host]:10000 tail -f /etc/motd
把浏览器指向
http://localhost:1234




叶子 2007-05-24 01:53 发表评论
]]>
ƷþþþӰԺɫ| ŷ㽶þۺվ| ޹ƷۺϾþһ| ŷƷһþ| ޹պŷþ| þav߳avav紵| ɫۺϾžþ| Ʒŷþþþ޹| þþۺ| 91þþһȫ| ɫۺϾþþþ | Ʒþþþþù| 99þһa| ŷպĻþ| ޾ƷŮþþ| Ʒþþþþþ | һ97ձ˾þۺӰԺ| Ʒþþþþø69| ھƷþþþav| þ99ƷþֻоƷ| VVþþ| 97þó˾Ʒվ| þó˹Ʒ| ھƷþþþӰԺ޹²| þùѹۿƷ| þĻȫ| 51þҹɫƷ| þþAVɫۺ| þþþþ޾Ʒ| 97þþƷһ| һþ㽶߿ۿ | ھƷþþþþþ97ţţ| WWWAVþþӰƬ| þþƷһ| ƷȾþav| ۿþ| Ʒþ»| پþþƷþ| þۺav| þþù׮| ŷþۺ|