﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-beautykingdom-随笔分类-Linux_Coding</title><link>http://www.cppblog.com/beautykingdom/category/12915.html</link><description /><language>zh-cn</language><lastBuildDate>Sun, 01 Jul 2012 21:57:08 GMT</lastBuildDate><pubDate>Sun, 01 Jul 2012 21:57:08 GMT</pubDate><ttl>60</ttl><item><title>Linux core dump file详解 &lt;转&gt;</title><link>http://www.cppblog.com/beautykingdom/archive/2012/06/30/180911.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Sat, 30 Jun 2012 12:08:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2012/06/30/180911.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/180911.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2012/06/30/180911.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/180911.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/180911.html</trackback:ping><description><![CDATA[<span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">1. 前言: 有的程序可以通过编译, 但在运行时会出现Segment fault(段错误). 这通常都是指针错误引起的. 但这不像编译错误一样会提示到文件-&gt;行, 而是没有任何信息, 使得我们的调试变得困难起来.</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">&nbsp;&nbsp;&nbsp; 2. gdb: 有一种办法是, 我们用gdb的step, 一步一步寻找. 这放在短小的代码中是可行的, 但要让你step一个上万行的代码, 我想你会从此厌恶程序员这个名字, 而把他叫做调试员. 我们还有更好的办法, 这就是core file.</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">&nbsp;&nbsp;&nbsp; 3. ulimit: 如果想让系统在信号中断造成的错误时产生core文件, 我们需要在shell中按如下设置: #设置core大小为无限 ulimit -c unlimited #设置文件大小为无限 ulimit unlimited 这些需要有root权限, 在ubuntu下每次重新打开中断都需要重新输入上面的第一条命令, 来设置core大小为无限.</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">&nbsp;&nbsp;&nbsp; 4. 用gdb查看core文件: 下面我们可以在发生运行时信号引起的错误时发生core dump了. 发生core dump之后, 用gdb进行查看core文件的内容, 以定位文件中引发core dump的行. gdb [exec file] [core file] 如: gdb ./test test.core 在进入gdb后, 用bt命令查看backtrace以检查发生程序运行到哪里, 来定位core dump的文件-&gt;行.</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">1. 什么是Core：</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">Sam之前一直以为Core Dump中Core是 Linux Kernel的意思. 今天才发现在这里，Core是另一种意思：</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">在使用半导体作为内存的材料前，人类是利用线圈当作内存的材料（发明者为王安），线圈就叫作 core ，用线圈做的内存就叫作 core memory。如今 ，半导体工业澎勃发展，已经没有人用 core memory 了，不过，在许多情况下， 人们还是把记忆体叫作 core 。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">2. 什么是Core Dump：</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">我们在开发（或使用）一个程序时，最怕的就是程序莫明其妙地当掉。虽然系统没事，但我们下次仍可能遇到相同的问题。于是这时操作系统就会把程序当掉 时的内存内容 dump 出来（现在通常是写在一个叫 core 的 file 里面），让 我们或是 debugger 做为参考。这个动作就叫作 core dump。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">3. Core Dump时会生成何种文件：</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">Core Dump时，会生成诸如 core.进程号 的文件。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">4. 为何有时程序Down了，却没生成 Core文件。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">Linux下，有一些设置，标明了resources available to the shell and to processes。 可以使用#ulimit -a&nbsp; 来看这些设置。 (ulimit是bash built-in Command)</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -a&nbsp;&nbsp;&nbsp;&nbsp; All current limits are reported</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -c&nbsp;&nbsp;&nbsp;&nbsp; The maximum size of core files created</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -d&nbsp;&nbsp;&nbsp;&nbsp; The maximum size of a process鈥檚 data segment</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -e&nbsp;&nbsp;&nbsp;&nbsp; The maximum scheduling priority ("nice")</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -f&nbsp;&nbsp;&nbsp;&nbsp; The maximum size of files written by the shell and its children</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -i&nbsp;&nbsp;&nbsp;&nbsp; The maximum number of pending signals</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -l&nbsp;&nbsp;&nbsp;&nbsp; The maximum size that m ay be locked into memory</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -m&nbsp;&nbsp;&nbsp;&nbsp; The maximum resident set size (has no effect on Linux)</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -n&nbsp;&nbsp;&nbsp;&nbsp; The maximum number of open file descriptors (most systems do not allow this value to be set)</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -p&nbsp;&nbsp;&nbsp;&nbsp; The pipe size in 512-byte blocks (this may not be set)</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -q&nbsp;&nbsp;&nbsp;&nbsp; The maximum number of bytes in POSIX message queues</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -r&nbsp;&nbsp;&nbsp;&nbsp; The maximum real-time scheduling priority</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -s&nbsp;&nbsp;&nbsp;&nbsp; The maximum stack size</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -t&nbsp;&nbsp;&nbsp;&nbsp; The maximum amount of cpu time in seconds</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -u&nbsp;&nbsp;&nbsp;&nbsp; The maximum number of processes available to a single user</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -v&nbsp;&nbsp;&nbsp;&nbsp; The maximum amount of virtual memory available to the shell</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -x&nbsp;&nbsp;&nbsp;&nbsp; The maximum number of file locks</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">&nbsp;从这里可以看出，如果 -c是显示：core file size&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (blocks, -c)&nbsp; 如果这个值为0，则无法生成core文件。所以可以使用：</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">#ulimit -c 1024&nbsp;&nbsp; 或者 #ulimit -c unlimited&nbsp;&nbsp; 来使能 core文件。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">如果程序出错时生成Core 文件，则会显示Segmentation fault (core dumped) 。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">5. Core Dump的核心转储文件目录和命名规则:</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">/proc/sys/kernel /core_uses_pid可以控制产生的core文件的文件名中是否添加pid作为扩展，如果添加则文件内容为1，否则为0</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">6. 如何使用Core文件：</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">在Linux下，使用：</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">#gdb -c core.pid program_name</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">就可以进入gdb模式。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">输入where，就可以指出是在哪一行被Down掉，哪个function内，由谁调用等等。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">(gdb) where</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">或者输入 bt。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">(gdb) bt</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">7. 如何让一个正常的程序down:</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">#kill -s SIGSEGV pid</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">8. 察看Core文件输出在何处：</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">存放Coredump的目录即进程的当前目录，一般就是当初发出命令启动该进程时所在的目录。但如果是通过脚本启动，则脚本可能会修改当前目录，这时进程真正的当前目录就会与当初执行脚本所在目录不同。这时可以查看&#8221;/proc/&lt;进程pid&gt;/cwd&#8220;符号链接的目标来确定进程真正的当前目录地址。通过系统服务启动的进程也可通过这一方法查看。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">9. 嵌入式设备下如何使用Core dump:</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">linux coredump配置与调试</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">Linux</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">Core Dump 配置与调试</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">1.core文件的生成开关和大小限制</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">---------------------------------</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">1）使用ulimit -c 命令可查看core文件的生成开关。若结果为0，则表示关闭了此功能，不会生成core文件。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">2）使用ulimit -c filesize命令，可以限制core文件的大小（filesize的单位为kbyte）。若ulimit -c unlimited，则表示core文件的大小不受限制。如果生成的信息超过此大小，将会被裁剪，最终生成一个不完整的core文件。在调试此core文件的时候，gdb会提示错误。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">2.core文件的名称和生成路径</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">----------------------------</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">若系统生成的core文件不带其它任何扩展名称，则全部命名为core。新的core文件生成将覆盖原来的core文件 。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">1）/proc/sys /kernel/core_uses_pid可以控制core文件的文件名中是否添加pid作为扩展。文件内容为1，表示添加pid作为扩展名，生成的 core文件格式为core.xxxx；为0则表示生成的core文件同一命名为core。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">可通过以下命令修改此文件：</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">echo"1" &gt;/proc/sys/kernel/core_uses_pid</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">2）proc/sys/kernel/core_pattern可以控制core文件保存位置和文件名格式。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">可通过以下命令修改此文件：</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">echo"/corefile/core-%e-%p-%t" &gt;core_pattern，可以将core文件统一生成到/corefile目录下，产生的文件名为core-命令名-pid-时间戳</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">以下是参数列表:</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">%p - insert pid into filename 添加pid</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">%u - insert current uid into filename 添加当前uid</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">%g - insert current gid into filename 添加当前gid</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">%s - insert signal that caused the coredump into the filename&nbsp; 添加导致产生core的信号</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">%t - insert UNIX time that the coredump occurred into filename&nbsp; 添加core文件生成时的unix时间</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">%h - insert hostname where the coredump happened into filename&nbsp; 添加主机名</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">%e - insert coredumping executable name into filename&nbsp; 添加命令名</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">3.用gdb查看core文件:</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">下面我们可以在发生运行时信号引起的错误时发生core dump了.</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">发生 core dump之后,用gdb进行查看core文件的内容,以定位文件中引发core dump的行.</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">gdb [exec file] [core file]</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">如:gdb ./test test.core</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">在进入gdb后,用 bt命令查看backtrace以检查发生程序运行到哪里,来定位core dump的文件-&gt;行.</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">4.开发板上使用core文件调试</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">-----------------------------</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">如果开发板的操作系统也是linux，core调试方法依然适用。如果开发板上不支持gdb，可将开发板的环境（头文件、库）、可执行文件和core文件拷贝到PC的linux下，运行相关命令即可。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">注意：待调试的可执行文件，在编译的时候需要加-g，core文件才能正常显示出错信息！</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">注意的问题：</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">在Linux下要保证程序崩溃时生成 Coredump要注意这些问题：</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">　　一、要保证存放Coredump的目录存在且进程对该目录有写权限。存放Coredump 的目录即进程的当前目录，一般就是当初发出命令启动该进程时所在的目录。但如果是通过脚本启动，则脚本可能会修改当前目录，这时进程真正的当前目录就会与当初执行脚本所在目录不同。这时可以查看&#8221;/proc/进程pid&gt;/cwd&#8220;符号链接的目标来确定进程真正的当前目录地址。通过系统服务启动的进程也可通过这一方法查看。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">　　二、若程序调用了seteuid()/setegid()改变了进程的有效用户或组，则在默认情况下系统不会为这些进程生成Coredump。很多服务程序都会调用seteuid()，如MySQL，不论你用什么用户运行 mysqld_safe启动MySQL，mysqld进行的有效用户始终是msyql用户。如果你当初是以用户A运行了某个程序，但在ps里看到的</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">这个程序的用户却是B的话，那么这些进程就是调用了seteuid了。为了能够让这些进程生成core dump，需要将/proc/sys/fs/suid_dumpable 文件的内容改为1（一般默认是0）。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">　　三、这个一般都知道，就是要设置足够大的Core文件大小限制了。程序崩溃时生成的 Core文件大小即为程序运行时占用的内存大小。但程序崩溃时的行为不可按平常时的行为来估计，比如缓冲区溢出等错误可能导致堆栈被破坏，因此经常会出现某个变量的值被修改成乱七八糟的，然后程序用这个大小去申请内存就可能导致程序比平常时多占用很多内存。因此无论程序正常运行时占用的内存多么少，要保证生成Core文件还是将大小限制设为unlimited为好。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">ulimit -- 用户资源限制命令</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">1、说明 :ulimit用于shell启动进程所占用的资源.</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">2、类别 :shell内建命令</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">3、语法格式 :ulimit [-acdfHlmnpsStvw] [size]</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">4、参数介绍 :</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">-H 设置硬件资源限制.</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">-S 设置软件资源限制.</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">-a 显示当前所有的资源限制.</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">-c size:设置core文件的最大值.单位:blocks</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">-d size:设置数据段的最大值.单位:kbytes</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">-f size:设置创建文件的最大值.单位:blocks</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">-l size:设置在内存中锁定进程的最大值.单位:kbytes</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">-m size:设置可以使用的常驻内存的最大值.单位:kbytes</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">-n size:设置内核可以同时打开的文件描述符的最大值.单位:n</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">-p size:设置管道缓冲区的最大值.单位:kbytes</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">-s size:设置堆栈的最大值.单位:kbytes</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">-t size:设置CPU使用时间的最大上限.单位:seconds</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">-v size:设置虚拟内存的最大值.单位:kbytes 5,简单实例:&nbsp;</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">5、举例</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">在Linux下写程序的时候，如果程序比较大，经常会遇到&#8220;段错误&#8221;（segmentationfault）这样的问题，这主要就是由于Linux系统初始的堆栈大小（stack size）太小的缘故，一般为10M。我一般把stacksize设置成256M，这样就没有段错误了！命令为：ulimit&nbsp;&nbsp; -s 262140</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">如果要系统自动记住这个配置，就编辑/etc/profile文件，在 &#8220;ulimit -S -c 0 &gt; /dev/null 2&gt;&amp;1&#8221;行下，添加&#8220;ulimit&nbsp;&nbsp; -s 262140&#8221;，保存重启系统就可以了！</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">1]在RH8的环境文件/etc/profile中,我们可以看到系统是如何配置ulimit的:</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">#grep ulimit /etc/profile</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">ulimit -S -c 0 &gt; /dev/null 2&gt;&amp;1</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">这条语句设置了对软件资源和对core文件大小的设置</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">2]如果我们想要对由shell创建的文件大小作些限制,如:</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">#ll h</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">-rw-r--r-- 1 lee lee 150062 7月 22 02:39 h</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">#ulimit -f 100 #设置创建文件的最大块(一块=512字节)</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">#cat h&gt;newh</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">File size limit exceeded</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">#ll newh</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">-rw-r--r-- 1 lee lee 51200 11月 8 11:47 newh</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">文件h的大小是150062字节,而我们设定的创建文件的大小是512字节x100块=51200字节，当然系统就会根据你的设置生成了51200字节的newh文件.</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">3]可以像实例1]一样,把你要设置的ulimit放在/etc/profile这个环境文件中.</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">用途：设置或报告用户资源极限。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">语法：ulimit [ -H ] [ -S ] [ -a ] [ -c ] [ -d ] [ -f ] [ -m ] [ -n ] [ -s ] [ -t ] [ Limit ]</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">描述：ulimit 命令设置或报告用户进程资源极限，如 /etc/security/limits 文件所定义。文件包含以下缺省值极限：</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">fsize = 2097151</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">core = 2097151</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">cpu = -1</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">data = 262144</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">rss = 65536</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">stack = 65536</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">nofiles = 2000</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">当新用户添加到系统中时，这些值被作为缺省值使用。当向系统中添加用户时，以上值通过 mkuser 命令设置，或通过 chuser 命令更改。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">极限分为软性或硬性。通过 ulimit 命令，用户可将软极限更改到硬极限的最大设置值。要更改资源硬极限，必须拥有 root 用户权限。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">很多系统不包括以上一种或数种极限。 特定资源的极限在指定 Limit 参数时设定。Limit 参数的值可以是每个资源中指定单元中的数字，或者为值 unlimited。要将特定的 ulimit 设置为 unlimited，可使用词 unlimited。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">&nbsp;&nbsp;&nbsp; 注：在 /etc/security/limits 文件中设置缺省极限就是设置了系统宽度极限， 而不仅仅是创建用户时用户所需的极限。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">省略 Limit 参数时，将会打印出当前资源极限。除非用户指定 -H 标志，否则打印出软极限。当用户指定一个以上资源时，极限名称和单元在值之前打印。如果未给予选项，则假定带有了 -f 标志。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">由于 ulimit 命令影响当前 shell 环境，所以它将作为 shell 常规内置命令提供。如果在独立的命令执行环境中调用该命令，则不影响调用者环境的文件大小极限。以下示例中正是这种情况：</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">nohup ulimit -f 10000</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">env ulimit 10000</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">一旦通过进程减少了硬极限，若无 root 特权则无法增加，即使返回到原值也不可能。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">关于用户和系统资源极限的更多信息，请参见 AIX 5L Version 5.3 Technical Reference: BaseOperating System and Extensions Volume 1 中的 getrlimit、setrlimit 或vlimit 子例程。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">标志</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">-a&nbsp;&nbsp;&nbsp;&nbsp; 列出所有当前资源极限。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">-c&nbsp;&nbsp;&nbsp;&nbsp; 以 512 字节块为单位，指定核心转储的大小。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">-d&nbsp;&nbsp;&nbsp;&nbsp; 以 K 字节为单位指定数据区域的大小。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">-f&nbsp;&nbsp;&nbsp;&nbsp; 使用 Limit 参数时设定文件大小极限（以块计），或者在未指定参数时报告文件大小极限。缺省值为 -f 标志。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">-H&nbsp;&nbsp;&nbsp;&nbsp; 指定设置某个给定资源的硬极限。如果用户拥有 root 用户权限，可以增大硬极限。任何用户均可减少硬极限。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">-m&nbsp;&nbsp;&nbsp;&nbsp; 以 K 字节为单位指定物理存储器的大小。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">-n&nbsp;&nbsp;&nbsp;&nbsp; 指定一个进程可以拥有的文件描述符的数量的极限。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">-s&nbsp;&nbsp;&nbsp;&nbsp; 以 K 字节为单位指定堆栈的大小。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">-S&nbsp;&nbsp;&nbsp;&nbsp; 指定为给定的资源设置软极限。软极限可增大到硬极限的值。如果 -H 和 -S 标志均未指定，极限适用于以上二者。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">-t&nbsp;&nbsp;&nbsp;&nbsp; 指定每个进程所使用的秒数 。</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">退出状态</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">返回以下退出值：</span><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><br style="font-family: 宋体, Arial; background-color: #f5f7f8; " /><span style="font-family: 宋体, Arial; background-color: #f5f7f8; ">0&nbsp;&nbsp;&nbsp;&nbsp; 成功完成。</span>&nbsp;<br /><br /><br />from:<br /><a href="http://blog.chinaunix.net/uid-26707720-id-3256694.html">http://blog.chinaunix.net/uid-26707720-id-3256694.html</a>&nbsp;<img src ="http://www.cppblog.com/beautykingdom/aggbug/180911.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2012-06-30 20:08 <a href="http://www.cppblog.com/beautykingdom/archive/2012/06/30/180911.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ifconf.c《转载》</title><link>http://www.cppblog.com/beautykingdom/archive/2011/05/20/146806.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Fri, 20 May 2011 04:30:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2011/05/20/146806.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/146806.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2011/05/20/146806.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/146806.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/146806.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: #include&nbsp;&lt;sys/types.h&gt;&nbsp;&nbsp;&nbsp;#include&nbsp;&lt;sys/socket.h&gt;&nbsp;&nbsp;&nbsp;#include&nbsp;&lt;sys/ioctl.h&gt;&nbsp;&nbsp;&nbsp;#include&nbsp;&lt;netinet/in.h&gt;&nbsp;&nbsp;...&nbsp;&nbsp;<a href='http://www.cppblog.com/beautykingdom/archive/2011/05/20/146806.html'>阅读全文</a><img src ="http://www.cppblog.com/beautykingdom/aggbug/146806.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2011-05-20 12:30 <a href="http://www.cppblog.com/beautykingdom/archive/2011/05/20/146806.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>什么是段错误</title><link>http://www.cppblog.com/beautykingdom/archive/2011/03/20/142281.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Sun, 20 Mar 2011 08:32:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2011/03/20/142281.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/142281.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2011/03/20/142281.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/142281.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/142281.html</trackback:ping><description><![CDATA[<br>所谓的段错误就是指访问的内存超出了系统所给这个程序的内存空间，通常这个值是由gdtr来保存的，<br>他是一个48位的寄存器，其中的32位是保存由它指向的gdt表，后13位保存相应于gdt的下标，最后3位<br>包括了程序是否在内存中以及程序的在cpu中的运行级别,指向的gdt是由以64位为一个单位的表，在这<br>张表中就保存着程序运行的代码段以及数据段的起始地址以及与此相应的段限和页面交换还有程序运<br>行级别还有内存粒度等等的信息。一旦一个程序发生了越界访问，cpu就会产生相应的异常保护，于<br>是segmentation fault就出现了。
<img src ="http://www.cppblog.com/beautykingdom/aggbug/142281.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2011-03-20 16:32 <a href="http://www.cppblog.com/beautykingdom/archive/2011/03/20/142281.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux c 大文件使用</title><link>http://www.cppblog.com/beautykingdom/archive/2010/12/10/136040.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Fri, 10 Dec 2010 03:36:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/12/10/136040.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/136040.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/12/10/136040.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/136040.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/136040.html</trackback:ping><description><![CDATA[<span class="Apple-style-span" style="border-collapse: separate; color: #000000; font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span class="Apple-style-span" style="color: #6a7376; font-family: Tahoma; font-size: 12px; line-height: 24px;">
<p style="line-height: normal;">支持大文件的两种方式：</p>
<p style="line-height: normal;">1、gcc 加 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE</p>
<p style="line-height: normal;"><strong style="line-height: normal;"><font style="line-height: normal;" color="#ff0000">2、注意一定要定义在include之前</font></strong></p>
<p style="line-height: normal;">#define _LARGEFILE_SOURCE<br style="line-height: normal;">#define _LARGEFILE64_SOURCE<br style="line-height: normal;">#define _FILE_OFFSET_BITS 64</p>
<p style="line-height: normal;">建议两种方式都加上。</p>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;"><strong style="line-height: normal;">如何create大文件</strong></div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;">要大就非常大，1T吧。</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;">有两种方法：</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;"><wbr style="line-height: normal;"></div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;"><strong style="line-height: normal;">一.dd</strong><br style="line-height: normal;"><font style="line-height: normal;" color="#ff0000">dd if=/dev/zero of=1T.img bs=1G seek=1024 count=0</font><br style="line-height: normal;">bs=1G表示每一次读写1G数据，count=0表示读写0次，seek=1024表示略过1024个Block不写，前面block size是1G，所以共略过1T！<br style="line-height: normal;">这是创建大型sparse文件最简单的方法。</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;"><wbr style="line-height: normal;"></div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;"><strong style="line-height: normal;">二.ftruncate64/ftruncate</strong><br style="line-height: normal;">如果用系统函数就稍微有些麻烦，因为涉及到宏的问题。我会结合一个实际例子详细说明，其中OPTION标志的就是测试项。<br style="line-height: normal;"><em style="line-height: normal;">文件sparse.c:</em></div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;"><wbr style="line-height: normal;"></div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;"><font style="line-height: normal;" color="#ff0000">//OPTION 1:是否定义与大文件相关的宏</font><br style="line-height: normal;">#define _LARGEFILE_SOURCE<br style="line-height: normal;">#define _LARGEFILE64_SOURCE<br style="line-height: normal;">#define _FILE_OFFSET_BITS 64</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;"><wbr style="line-height: normal;"></div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;">#include &lt;stdio.h&gt;<br style="line-height: normal;">#include &lt;sys/types.h&gt;<br style="line-height: normal;">#include &lt;sys/stat.h&gt;<br style="line-height: normal;">#include &lt;fcntl.h&gt;<br style="line-height: normal;">#include &lt;errno.h&gt;<br style="line-height: normal;">#include &lt;string.h&gt;</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;">#define FILENAME "bigfile"<br style="line-height: normal;">#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)<br style="line-height: normal;">int main(int argc, char **argv)<br style="line-height: normal;">{<br style="line-height: normal;"><wbr style="line-height: normal;">int fd, ret;<br style="line-height: normal;"><wbr style="line-height: normal;">off_t offset;</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;"><wbr style="line-height: normal;">int total = 0;<br style="line-height: normal;"><wbr style="line-height: normal;">if ( argc &gt;= 2 )<br style="line-height: normal;"><wbr style="line-height: normal;">{<br style="line-height: normal;"><wbr style="line-height: normal;"><wbr style="line-height: normal;"><wbr style="line-height: normal;">total = atol(argv[1]);<br style="line-height: normal;"><wbr style="line-height: normal;"><wbr style="line-height: normal;"><wbr style="line-height: normal;">printf("total=%d\n", total);<br style="line-height: normal;"><wbr style="line-height: normal;">}</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;"><wbr style="line-height: normal;"><br style="line-height: normal;"><wbr style="line-height: normal;"><font style="line-height: normal;" color="#ff0000">//OPTION 2:是否有O_LARGEFILE选项</font><br style="line-height: normal;"><wbr style="line-height: normal;">//fd = open(FILENAME, O_RDWR|O_CREAT|O_LARGEFILE, 0644);<br style="line-height: normal;"><wbr style="line-height: normal;">fd = open(FILENAME, O_RDWR|O_CREAT, 0644);<br style="line-height: normal;"><wbr style="line-height: normal;">if (fd &lt; 0) {<br style="line-height: normal;"><wbr style="line-height: normal;"><wbr style="line-height: normal;"><wbr style="line-height: normal;">perror(FILENAME);<br style="line-height: normal;"><wbr style="line-height: normal;"><wbr style="line-height: normal;"><wbr style="line-height: normal;">return -1;<br style="line-height: normal;"><wbr style="line-height: normal;">}<br style="line-height: normal;"><wbr style="line-height: normal;">offset = (off_t)total *1024ll*1024ll*1024ll;<br style="line-height: normal;"><wbr style="line-height: normal;">printf("offset=%ld\n", offset);</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;"><wbr style="line-height: normal;"></div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;"><wbr style="line-height: normal;"><font style="line-height: normal;" color="#ff0000">//OPTION 3：是否调用64位系统函数</font><br style="line-height: normal;"><wbr style="line-height: normal;">//if (ftruncate64(fd, offset) &lt; 0)<br style="line-height: normal;"><wbr style="line-height: normal;">if (ftruncate(fd, offset) &lt; 0)<br style="line-height: normal;"><wbr style="line-height: normal;">{<br style="line-height: normal;"><wbr style="line-height: normal;"><wbr style="line-height: normal;"><wbr style="line-height: normal;">printf("[%d]-ftruncate64 error: %s\n",<span class="Apple-converted-space">&nbsp;</span><wbr style="line-height: normal;">errno, strerror(errno));<br style="line-height: normal;"><wbr style="line-height: normal;"><wbr style="line-height: normal;"><wbr style="line-height: normal;">close(fd);<br style="line-height: normal;"><wbr style="line-height: normal;"><wbr style="line-height: normal;"><wbr style="line-height: normal;">return 0;<br style="line-height: normal;"><wbr style="line-height: normal;">}</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;"><wbr style="line-height: normal;">close(fd);<br style="line-height: normal;"><wbr style="line-height: normal;">printf("OK\n");</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;"><wbr style="line-height: normal;">return 0;<br style="line-height: normal;">}</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;"><wbr style="line-height: normal;"></div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;"><strong style="line-height: normal;">测试环境：</strong><br style="line-height: normal;">linux:/disk/test/big # gcc --version<br style="line-height: normal;">gcc (GCC) 3.3.5 20050117 (prerelease) (SUSE Linux)<br style="line-height: normal;">linux:/disk/test/big # uname -a<br style="line-height: normal;">Linux linux 2.6.11.4-20a-default #1 Wed Mar 23 21:52:37 UTC 2005 i686 i686 i386 GNU/Linux</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;"><wbr style="line-height: normal;"></div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;"><strong style="line-height: normal;">测试结果（伪码表示）：</strong><br style="line-height: normal;"><strong style="line-height: normal;">1.宏定义完全的情况下：</strong><br style="line-height: normal;">IF {O_LARGEFILE=TRUE &amp;&amp; ftruncate64=TRUE}<br style="line-height: normal;"><wbr style="line-height: normal;">OK；<br style="line-height: normal;">ELSEIF {O_LARGEFILE=FALSE &amp;&amp; ftruncate64=TRUE}<br style="line-height: normal;"><wbr style="line-height: normal;">OK；<br style="line-height: normal;">ELSEIF {O_LARGEFILE=FALSE &amp;&amp; ftruncate64=FALSE}<br style="line-height: normal;"><wbr style="line-height: normal;">运行不报错，但是不支持&gt;4G；<br style="line-height: normal;">ELSEIF {O_LARGEFILE=TRUE &amp;&amp; ftruncate64=FALSE}<br style="line-height: normal;"><wbr style="line-height: normal;">运行不报错，但是不支持&gt;4G；<br style="line-height: normal;">【<strong style="line-height: normal;">结论</strong>】：<font style="line-height: normal;" color="#ff0000">在宏定义完全的情况下，是否调用ftruncate64，是决定支持4G以上文件的关键，O_LARGEFILE无作用</font>。</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;"><wbr style="line-height: normal;"></div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;"><strong style="line-height: normal;">2.宏定义不完全：缺少_FILE_OFFSET_BITS</strong><br style="line-height: normal;">首先声明一点，<font style="line-height: normal;" color="#ff0000">O_LARGEFILE需要定义_LARGEFILE64_SOURCE</font>。<br style="line-height: normal;">IF {O_LARGEFILE=TRUE &amp;&amp; ftruncate64=TRUE}<br style="line-height: normal;"><wbr style="line-height: normal;">产生不正常超大文件；<br style="line-height: normal;">ELSEIF {O_LARGEFILE=FALSE &amp;&amp; ftruncate64=TRUE}<br style="line-height: normal;"><wbr style="line-height: normal;">产生不正常超大文件；<br style="line-height: normal;">ELSEIF {O_LARGEFILE=FALSE &amp;&amp; ftruncate64=FALSE}<br style="line-height: normal;"><wbr style="line-height: normal;">运行不报错，但是不支持&gt;2G；<br style="line-height: normal;">ELSEIF {O_LARGEFILE=TRUE &amp;&amp; ftruncate64=FALSE}<br style="line-height: normal;"><wbr style="line-height: normal;">运行不报错，但是不支持&gt;4G；<br style="line-height: normal;">【<strong style="line-height: normal;">结论</strong>】：<font style="line-height: normal;" color="#ff0000">未定义_FILE_OFFSET_BITS的情况下，ftruncate64调用是非法的，会产生无法预料的后果，这里的测试就是产生一个超大文件(&gt;1T)，我也无法解释其原因；O_LARGEFILE的作用就是在32位系统中支持大文件系统,允许打开那些用31位（2G）都不能表示其长度的大文件；此外，off_t为unsigned int类型，也就是说最多只能达到4G，所以ftruncate最大支持4G文件。</font></div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;"><wbr style="line-height: normal;"></div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;"><strong style="line-height: normal;">总结一下</strong>：<font style="line-height: normal;" color="#ff0000">如果要支持超过2G的文件，至少需要定义_LARGEFILE64_SOURCE宏，并且设置O_LARGEFILE选项；如果要支持超过4G，需要定义所有上述的宏，并且调用ftruncate64；其余的搭配都是错误的！</font></div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;"><wbr style="line-height: normal;"></div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;">【<strong style="line-height: normal;">附</strong>】：<br style="line-height: normal;">dd 的主要选项：<br style="line-height: normal;">指定数字的地方若以下列字符结尾乘以相应的数字:<br style="line-height: normal;">b=512, c=1, k=1024, w=2, m=1024k, g=1024m<br style="line-height: normal;">大小写不限。</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;">if=file<br style="line-height: normal;">输入文件名，缺省为标准输入。</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;">of=file<br style="line-height: normal;">输出文件名，缺省为标准输出。</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;">ibs=bytes<br style="line-height: normal;">一次读入 bytes 个字节(即一个块大小为 bytes 个字节)。</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;">obs=bytes<br style="line-height: normal;">一次写 bytes 个字节(即一个块大小为 bytes 个字节)。</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;">bs=bytes<br style="line-height: normal;">同时设置读写块的大小为 bytes ，可代替 ibs 和 obs 。</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;">cbs=bytes<br style="line-height: normal;">一次转换 bytes 个字节，即转换缓冲区大小。</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;">skip=blocks<br style="line-height: normal;">从输入文件开头跳过 blocks 个块后再开始复制。</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;">seek=blocks<br style="line-height: normal;">从输出文件开头跳过 blocks 个块后再开始复制。(通常只有当输出文件是磁盘或磁带时才有效)</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;">count=blocks<br style="line-height: normal;">仅拷贝 blocks 个块，块大小等于 ibs 指定的字节数。</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;">conv=conversion[,conversion...]<br style="line-height: normal;">用指定的参数转换文件。</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;">转换参数:</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;">ascii 转换 EBCDIC 为 ASCII。</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;">ebcdic 转换 ASCII 为 EBCDIC。</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;">ibm 转换 ASCII 为 alternate EBCDIC.</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;">block 把每一行转换为长度为 cbs 的记录，不足部分用空格填充。</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;">unblock<br style="line-height: normal;">使每一行的长度都为 cbs ，不足部分用空格填充。</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;">lcase 把大写字符转换为小写字符。</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;">ucase 把小写字符转换为大写字符。</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;">noerror<br style="line-height: normal;">不显示错误</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;">notrunc<br style="line-height: normal;">不截短输出文件。</div>
<div style="font-family: Arial; word-wrap: break-word; visibility: visible ! important; filter: none; font-size: 12px; line-height: normal;">sync 把每个输入块填充到ibs个字节，不足部分用空(NUL)字符补齐。<br><br><br><br>from:<br><a  href="http://hi.baidu.com/roxws/blog/item/785c4bcb61662ff853664f2d.html/cmtid/f990c324dee21627d50742e9">http://hi.baidu.com/roxws/blog/item/785c4bcb61662ff853664f2d.html/cmtid/f990c324dee21627d50742e9</a><br><br></div>
</span></span><img src ="http://www.cppblog.com/beautykingdom/aggbug/136040.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-12-10 11:36 <a href="http://www.cppblog.com/beautykingdom/archive/2010/12/10/136040.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux 引导过程内幕 从主引导记录到第一个用户空间应用程序的指导</title><link>http://www.cppblog.com/beautykingdom/archive/2010/11/08/133023.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Mon, 08 Nov 2010 11:58:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/11/08/133023.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/133023.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/11/08/133023.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/133023.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/133023.html</trackback:ping><description><![CDATA[

<span style="font-family: arial, nsimsun, sans-serif; font-size: 12px; "><strong style="font-size: 1em; font-weight: bold; ">简介：</strong></span><span style="font-family: arial, nsimsun, sans-serif; font-size: 12px; ">&nbsp;引导 Linux&#174; 系统的过程包括很多阶段。不管您是引导一个标准的 x86 桌面系统，还是引导一台嵌入式的 PowerPC&#174; 机器，很多流程都惊人地相似。本文将探索 Linux 的引导过程，从最初的引导到启动第一个用户空间应用程序。在本文介绍的过程中，您将学习到各种与引导有关的主题，例如引导加载程序、内核解压、初始 RAM 磁盘以及 Linux 引导的其他一些元素。</span>

<div><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; ">早期时，启动一台计算机意味着要给计算机喂一条包含引导程序的纸带，或者手工使用前端面板地址/数据/控制开关来加载引导程序。尽管目前的计算机已经装备了很多工具来简化引导过程，但是这一切并没有对整个过程进行必要的简化。</p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; ">让我们先从高级的视角来查看 Linux 引导过程，这样就可以看到整个过程的全貌了。然后将回顾一下在各个步骤到底发生了什么。在整个过程中，参考一下内核源代码可以帮助我们更好地了解内核源代码树，并在以后对其进行深入分析。</p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; "><a name="N1005E"><span class="atitle" style="font-size: 1.5em; font-weight: bold; ">概述</span></a></p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; ">图 1 是我们在 20,000 英尺的高度看到的视图。</p><br><a name="fig1" style="font-family: Simsun; font-size: medium; "><strong style="font-size: 0.76em; font-weight: bold; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-family: arial, sans-serif; ">图 1. Linux 引导过程在 20,000 英尺处的视图</strong></a><br><span style="border-style: initial; border-color: initial; padding-top: 0.3em; padding-bottom: 0.7em;"><img alt="Linux 引导过程在 20,000 英尺处的视图" height="300" src="http://www.ibm.com/developerworks/cn/linux/l-linuxboot/fig1.gif" width="529" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; "></span>&nbsp;<br><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; ">当系统首次引导时，或系统被重置时，处理器会执行一个位于已知位置处的代码。在个人计算机（PC）中，这个位置在基本输入/输出系统（BIOS）中，它保存在主板上的闪存中。嵌入式系统中的中央处理单元（CPU）会调用这个重置向量来启动一个位于闪存/ROM 中的已知地址处的程序。在这两种情况下，结果都是相同的。因为 PC 提供了很多灵活性，BIOS 必须确定要使用哪个设备来引导系统。稍后我们将详细介绍这个过程。</p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; ">当找到一个引导设备之后，第一阶段的引导加载程序就被装入 RAM 并执行。这个引导加载程序在大小上小于 512 字节（一个扇区），其作用是加载第二阶段的引导加载程序。</p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; ">当第二阶段的引导加载程序被装入 RAM 并执行时，通常会显示一个动画屏幕，并将 Linux 和一个可选的初始 RAM 磁盘（临时根文件系统）加载到内存中。在加载映像时，第二阶段的引导加载程序就会将控制权交给内核映像，然后内核就可以进行解压和初始化了。在这个阶段中，第二阶段的引导加载程序会检测系统硬件、枚举系统链接的硬件设备、挂载根设备，然后加载必要的内核模块。完成这些操作之后启动第一个用户空间程序（<code style="font-family: monospace; font-size: small !important; ">init</code>），并执行高级系统初始化工作。</p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; ">这就是 Linux 引导的整个过程。现在让我们深入挖掘一下这个过程，并深入研究一下 Linux 引导过程的一些详细信息。</p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; "><span style="font-family: Simsun; font-size: medium; "></span></p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; "><a name="N10087"><span class="atitle" style="font-size: 1.5em; font-weight: bold; ">系统启动</span></a></p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; ">系统启动阶段依赖于引导 Linux 系统上的硬件。在嵌入式平台中，当系统加电或重置时，会使用一个启动环境。这方面的例子包括 U-Boot、RedBoot 和 Lucent 的 MicroMonitor。嵌入式平台通常都是与引导监视器搭配销售的。这些程序位于目标硬件上的闪存中的某一段特殊区域，它们提供了将 Linux 内核映像下载到闪存并继续执行的方法。除了可以存储并引导 Linux 映像之外，这些引导监视器还执行一定级别的系统测试和硬件初始化过程。在嵌入式平台中，这些引导监视器通常会涉及第一阶段和第二阶段的引导加载程序。</p><div class="ibm-container ibm-alt-header dw-container-sidebar" style="margin-top: 0px; margin-right: 0px; margin-bottom: 1.2em; margin-left: 10px; width: 320px; float: right; "><h2 style="font-family: arial, nsimsun, sans-serif; background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(247, 248, 252); border-top-color: rgb(204, 204, 204); border-right-color: rgb(204, 204, 204); border-bottom-color: rgb(204, 204, 204); border-left-color: rgb(204, 204, 204); border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 5px; padding-bottom: 3px; padding-left: 5px; height: 15px; font-size: 0.75em; background-position: 0px -545px; background-repeat: repeat no-repeat; ">提取 MBR 的信息</h2><div class="ibm-container-body" style="background-image: url(http://www.ibm.com/i/v16/t/container-gradient.gif); background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(255, 255, 255); border-left-color: rgb(204, 204, 204); font-size: 0.76em; font-family: arial, sans-serif; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; background-position: 0px 100%; background-repeat: repeat no-repeat; "><p style="font-family: arial, nsimsun, sans-serif; font-size: 0.76em; padding-left: 5px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; ">要查看 MBR 的内容，请使用下面的命令：</p><code style="font-family: monospace; font-size: small !important; ">#&nbsp;<strong>dd if=/dev/hda of=mbr.bin bs=512 count=1</strong>&nbsp;#<strong>od -xa mbr.bin</strong></code><p style="font-family: arial, nsimsun, sans-serif; font-size: 0.76em; padding-left: 5px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; ">这个&nbsp;<code style="font-family: monospace; font-size: small !important; ">dd</code>&nbsp;命令需要以 root 用户的身份运行，它从 /dev/hda（第一个 IDE 盘） 上读取前 512 个字节的内容，并将其写入&nbsp;<code style="font-family: monospace; font-size: small !important; ">mbr.bin</code>&nbsp;文件中。<code style="font-family: monospace; font-size: small !important; ">od</code>&nbsp;命令会以十六进制和 ASCII 码格式打印这个二进制文件的内容。</p></div></div><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; ">在 PC 中，引导 Linux 是从 BIOS 中的地址 0xFFFF0 处开始的。BIOS 的第一个步骤是加电自检（POST）。POST 的工作是对硬件进行检测。BIOS 的第二个步骤是进行本地设备的枚举和初始化。</p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; ">给定 BIOS 功能的不同用法之后，BIOS 由两部分组成：POST 代码和运行时服务。当 POST 完成之后，它被从内存中清理了出来，但是 BIOS 运行时服务依然保留在内存中，目标操作系统可以使用这些服务。</p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; ">要引导一个操作系统，BIOS 运行时会按照 CMOS 的设置定义的顺序来搜索处于活动状态并且可以引导的设备。引导设备可以是软盘、CD-ROM、硬盘上的某个分区、网络上的某个设备，甚至是 USB 闪存。</p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; ">通常，Linux 都是从硬盘上引导的，其中主引导记录（MBR）中包含主引导加载程序。MBR 是一个 512 字节大小的扇区，位于磁盘上的第一个扇区中（0 道 0 柱面 1 扇区）。当 MBR 被加载到 RAM 中之后，BIOS 就会将控制权交给 MBR。</p><p>&#160;</p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; "><span style="font-family: Simsun; font-size: medium; "></span></p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; "><a name="N100C2"><span class="atitle" style="font-size: 1.5em; font-weight: bold; ">第一阶段引导加载程序</span></a></p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; ">MBR 中的主引导加载程序是一个 512 字节大小的映像，其中包含程序代码和一个小分区表（参见图 2）。前 446 个字节是主引导加载程序，其中包含可执行代码和错误消息文本。接下来的 64 个字节是分区表，其中包含 4 个分区的记录（每个记录的大小是 16 个字节）。MBR 以两个特殊数字的字节（0xAA55）结束。这个数字会用来进行 MBR 的有效性检查。</p><br><a name="fig2"><strong style="font-size: 0.76em; font-weight: bold; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-family: arial, sans-serif; ">图 2. MBR 剖析</strong></a><br><img alt="MBR 剖析" height="469" src="http://www.ibm.com/developerworks/cn/linux/l-linuxboot/fig2.gif" width="479" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; ">&nbsp;<br><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; ">主引导加载程序的工作是查找并加载次引导加载程序（第二阶段）。它是通过在分区表中查找一个活动分区来实现这种功能的。当找到一个活动分区时，它会扫描分区表中的其他分区，以确保它们都不是活动的。当这个过程验证完成之后，就将活动分区的引导记录从这个设备中读入 RAM 中并执行它。</p><p>&#160;</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; "></p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; "><a name="N100DE"><span class="atitle" style="font-size: 1.5em; font-weight: bold; ">第二阶段引导加载程序</span></a></p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; ">次引导加载程序（第二阶段引导加载程序）可以更形象地称为内核加载程序。这个阶段的任务是加载 Linux 内核和可选的初始 RAM 磁盘。</p><div class="ibm-container ibm-alt-header dw-container-sidebar" style="margin-top: 0px; margin-right: 0px; margin-bottom: 1.2em; margin-left: 10px; width: 320px; float: right; font-family: Simsun; font-size: medium; "><h2 style="font-family: arial, nsimsun, sans-serif; background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(247, 248, 252); border-top-color: rgb(204, 204, 204); border-right-color: rgb(204, 204, 204); border-bottom-color: rgb(204, 204, 204); border-left-color: rgb(204, 204, 204); border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 5px; padding-bottom: 3px; padding-left: 5px; height: 15px; font-size: 0.75em; background-position: 0px -545px; background-repeat: repeat no-repeat; ">GRUB 阶段引导加载程序</h2><div class="ibm-container-body" style="background-image: url(http://www.ibm.com/i/v16/t/container-gradient.gif); background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(255, 255, 255); border-left-color: rgb(204, 204, 204); font-size: 0.76em; font-family: arial, sans-serif; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; background-position: 0px 100%; background-repeat: repeat no-repeat; "><p style="font-family: arial, nsimsun, sans-serif; font-size: 0.76em; padding-left: 5px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; "><code style="font-family: monospace; font-size: small !important; ">/boot/grub</code>&nbsp;目录中包含了&nbsp;<code style="font-family: monospace; font-size: small !important; ">stage1</code>、<code style="font-family: monospace; font-size: small !important; ">stage1.5</code>&nbsp;和&nbsp;<code style="font-family: monospace; font-size: small !important; ">stage2</code>&nbsp;引导加载程序，以及很多其他加载程序（例如，CR-ROM 使用的是&nbsp;<code style="font-family: monospace; font-size: small !important; ">iso9660_stage_1_5</code>）。</p></div></div><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; ">在 x86 PC 环境中，第一阶段和第二阶段的引导加载程序一起称为 Linux Loader（LILO）或 GRand Unified Bootloader（GRUB）。由于 LILO 有一些缺点，而 GRUB 克服了这些缺点，因此下面让我们就来看一下 GRUB。（有关 GRUB、LILO 和相关主题的更多内容，请参阅本文后面的&nbsp;<a href="http://www.ibm.com/developerworks/cn/linux/l-linuxboot/#resources" style="color: rgb(76, 110, 148); ">参考资料</a>&nbsp;部分的内容。）</p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; ">关于 GRUB，很好的一件事情是它包含了有关 Linux 文件系统的知识。GRUB 不像 LILO 一样使用裸扇区，而是可以从 ext2 或 ext3 文件系统中加载 Linux 内核。它是通过将两阶段的引导加载程序转换成三阶段的引导加载程序来实现这项功能的。阶段 1 （MBR）引导了一个阶段 1.5 的引导加载程序，它可以理解包含 Linux 内核映像的特殊文件系统。这方面的例子包括&nbsp;<code style="font-family: monospace; font-size: small !important; ">reiserfs_stage1_5</code>（要从 Reiser 日志文件系统上进行加载）或&nbsp;<code style="font-family: monospace; font-size: small !important; ">e2fs_stage1_5</code>（要从 ext2 或 ext3 文件系统上进行加载）。当阶段 1.5 的引导加载程序被加载并运行时，阶段 2 的引导加载程序就可以进行加载了。</p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; ">当阶段 2 加载之后，GRUB 就可以在请求时显示可用内核列表（在&nbsp;<code style="font-family: monospace; font-size: small !important; ">/etc/grub.conf</code>&nbsp;中进行定义，同时还有几个软符号链接<code style="font-family: monospace; font-size: small !important; ">/etc/grub/menu.lst</code>&nbsp;和&nbsp;<code style="font-family: monospace; font-size: small !important; ">/etc/grub.conf</code>）。我们可以选择内核甚至修改附加内核参数。另外，我们也可以使用一个命令行的 shell 对引导过程进行高级手工控制。</p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; ">将第二阶段的引导加载程序加载到内存中之后，就可以对文件系统进行查询了，并将默认的内核映像和&nbsp;<code style="font-family: monospace; font-size: small !important; ">initrd</code>&nbsp;映像加载到内存中。当这些映像文件准备好之后，阶段 2 的引导加载程序就可以调用内核映像了。</p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; "><span style="font-family: Simsun; font-size: medium; "></span></p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; "><a name="N1012F"><span class="atitle" style="font-size: 1.5em; font-weight: bold; ">内核</span></a></p><div class="ibm-container ibm-alt-header dw-container-sidebar" style="margin-top: 0px; margin-right: 0px; margin-bottom: 1.2em; margin-left: 10px; width: 320px; float: right; "><h2 style="font-family: arial, nsimsun, sans-serif; background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(247, 248, 252); border-top-color: rgb(204, 204, 204); border-right-color: rgb(204, 204, 204); border-bottom-color: rgb(204, 204, 204); border-left-color: rgb(204, 204, 204); border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 5px; padding-bottom: 3px; padding-left: 5px; height: 15px; font-size: 0.75em; background-position: 0px -545px; background-repeat: repeat no-repeat; ">GRUB 中的手工引导</h2><div class="ibm-container-body" style="background-image: url(http://www.ibm.com/i/v16/t/container-gradient.gif); background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(255, 255, 255); border-left-color: rgb(204, 204, 204); font-size: 0.76em; font-family: arial, sans-serif; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; background-position: 0px 100%; background-repeat: repeat no-repeat; "><p style="font-family: arial, nsimsun, sans-serif; font-size: 0.76em; padding-left: 5px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; ">在 GRUB 命令行中，我们可以使用&nbsp;<code style="font-family: monospace; font-size: small !important; ">initrd</code>&nbsp;映像引导一个特定的内核，方法如下：</p><p style="font-family: arial, nsimsun, sans-serif; font-size: 0.76em; padding-left: 5px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; ">grub&gt; kernel /bzImage-2.6.14.2<br>[Linux-bzImage, setup=0x1400, size=0x29672e]<br>grub&gt; initrd /initrd-2.6.14.2.img<br>[Linux-initrd @ 0x5f13000, 0xcc199 bytes]<br>grub&gt; boot<br>Uncompressing Linux... Ok, booting the kernel.</p><p style="font-family: arial, nsimsun, sans-serif; font-size: 0.76em; padding-left: 5px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; ">如果您不知道要引导的内核的名称，只需使用斜线（/）然后按下 Tab 键即可。GRUB 会显示内核和&nbsp;<code style="font-family: monospace; font-size: small !important; ">initrd</code>&nbsp;映像列表。</p></div></div><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; ">当内核映像被加载到内存中，并且阶段 2 的引导加载程序释放控制权之后，内核阶段就开始了。内核映像并不是一个可执行的内核，而是一个压缩过的内核映像。通常它是一个 zImage（压缩映像，小于 512KB）或一个 bzImage（较大的压缩映像，大于 512KB），它是提前使用 zlib 进行压缩过的。在这个内核映像前面是一个例程，它实现少量硬件设置，并对内核映像中包含的内核进行解压，然后将其放入高端内存中，如果有初始 RAM 磁盘映像，就会将它移动到内存中，并标明以后使用。然后该例程会调用内核，并开始启动内核引导的过程。</p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; ">当 bzImage（用于 i386 映像）被调用时，我们从<code style="font-family: monospace; font-size: small !important; ">./arch/i386/boot/head.S</code>&nbsp;的&nbsp;<code style="font-family: monospace; font-size: small !important; ">start</code>&nbsp;汇编例程开始执行（主要流程图请参看图 3）。这个例程会执行一些基本的硬件设置，并调用<code style="font-family: monospace; font-size: small !important; ">./arch/i386/boot/compressed/head.S</code>&nbsp;中的&nbsp;<code style="font-family: monospace; font-size: small !important; ">startup_32</code>&nbsp;例程。此例程会设置一个基本的环境（堆栈等），并清除 Block Started by Symbol（BSS）。然后调用一个叫做&nbsp;<code style="font-family: monospace; font-size: small !important; ">decompress_kernel</code>&nbsp;的 C 函数（在<code style="font-family: monospace; font-size: small !important; ">./arch/i386/boot/compressed/misc.c</code>&nbsp;中）来解压内核。当内核被解压到内存中之后，就可以调用它了。这是另外一个&nbsp;<code style="font-family: monospace; font-size: small !important; ">startup_32</code>&nbsp;函数，但是这个函数在&nbsp;<code style="font-family: monospace; font-size: small !important; ">./arch/i386/kernel/head.S</code>&nbsp;中。</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; "><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; "><font  face="arial, nsimsun, sans-serif"><span  style="font-size: 12px;">&nbsp;vi arch/x86/{boot/{header.S,compressed/{head_{32,64}.S,misc.c},kernel/head.S}} init/main.c</span></font></p></p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; ">在这个新的&nbsp;<code style="font-family: monospace; font-size: small !important; ">startup_32</code>&nbsp;函数（也称为清除程序或进程 0）中，会对页表进行初始化，并启用内存分页功能。然后会为任何可选的浮点单元（FPU）检测 CPU 的类型，并将其存储起来供以后使用。然后调用&nbsp;<code style="font-family: monospace; font-size: small !important; ">start_kernel</code>&nbsp;函数（在&nbsp;<code style="font-family: monospace; font-size: small !important; ">init/main.c</code>&nbsp;中），它会将您带入与体系结构无关的 Linux 内核部分。实际上，这就是 Linux 内核的&nbsp;<code style="font-family: monospace; font-size: small !important; ">main</code>&nbsp;函数。</p><br><a name="fig3"><strong style="font-size: 0.76em; font-weight: bold; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-family: arial, sans-serif; ">图 3. Linux 内核 i386 引导的主要函数流程&nbsp;</strong></a><br><img alt="Linux 内核 i386 引导的主要函数流程 " height="288" src="http://www.ibm.com/developerworks/cn/linux/l-linuxboot/fig3.gif" width="443" style="border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; ">&nbsp;<br><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; ">通过调用&nbsp;<code style="font-family: monospace; font-size: small !important; ">start_kernel</code>，会调用一系列初始化函数来设置中断，执行进一步的内存配置，并加载初始 RAM 磁盘。最后，要调用<code style="font-family: monospace; font-size: small !important; ">kernel_thread</code>（在&nbsp;<code style="font-family: monospace; font-size: small !important; ">arch/i386/kernel/process.c</code>&nbsp;中）来启动&nbsp;<code style="font-family: monospace; font-size: small !important; ">init</code>&nbsp;函数，这是第一个用户空间进程（user-space process）。最后，启动空任务，现在调度器就可以接管控制权了（在调用&nbsp;<code style="font-family: monospace; font-size: small !important; ">cpu_idle</code>&nbsp;之后）。通过启用中断，抢占式的调度器就可以周期性地接管控制权，从而提供多任务处理能力。</p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; ">在内核引导过程中，初始 RAM 磁盘（<code style="font-family: monospace; font-size: small !important; ">initrd</code>）是由阶段 2 引导加载程序加载到内存中的，它会被复制到 RAM 中并挂载到系统上。这个&nbsp;<code style="font-family: monospace; font-size: small !important; ">initrd</code>&nbsp;会作为 RAM 中的临时根文件系统使用，并允许内核在没有挂载任何物理磁盘的情况下完整地实现引导。由于与外围设备进行交互所需要的模块可能是&nbsp;<code style="font-family: monospace; font-size: small !important; ">initrd</code>&nbsp;的一部分，因此内核可以非常小，但是仍然需要支持大量可能的硬件配置。在内核引导之后，就可以正式装备根文件系统了（通过&nbsp;<code style="font-family: monospace; font-size: small !important; ">pivot_root</code>）：此时会将&nbsp;<code style="font-family: monospace; font-size: small !important; ">initrd</code>&nbsp;根文件系统卸载掉，并挂载真正的根文件系统。</p><div class="ibm-container ibm-alt-header dw-container-sidebar" style="margin-top: 0px; margin-right: 0px; margin-bottom: 1.2em; margin-left: 10px; width: 320px; float: right; "><h2 style="font-family: arial, nsimsun, sans-serif; background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(247, 248, 252); border-top-color: rgb(204, 204, 204); border-right-color: rgb(204, 204, 204); border-bottom-color: rgb(204, 204, 204); border-left-color: rgb(204, 204, 204); border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 3px; padding-right: 5px; padding-bottom: 3px; padding-left: 5px; height: 15px; font-size: 0.75em; background-position: 0px -545px; background-repeat: repeat no-repeat; ">decompress_kernel 输出</h2><div class="ibm-container-body" style="background-image: url(http://www.ibm.com/i/v16/t/container-gradient.gif); background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(255, 255, 255); border-left-color: rgb(204, 204, 204); font-size: 0.76em; font-family: arial, sans-serif; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; background-position: 0px 100%; background-repeat: repeat no-repeat; "><p style="font-family: arial, nsimsun, sans-serif; font-size: 0.76em; padding-left: 5px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; ">函数&nbsp;<code style="font-family: monospace; font-size: small !important; ">decompress_kernel</code>&nbsp;就是显示我们通常看到的解压消息的地方：</p><p style="font-family: arial, nsimsun, sans-serif; font-size: 0.76em; padding-left: 5px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; ">Uncompressing Linux... Ok, booting the kernel.</p></div></div><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; "><code style="font-family: monospace; font-size: small !important; ">initrd</code>&nbsp;函数让我们可以创建一个小型的 Linux 内核，其中包括作为可加载模块编译的驱动程序。这些可加载的模块为内核提供了访问磁盘和磁盘上的文件系统的方法，并为其他硬件提供了驱动程序。由于根文件系统是磁盘上的一个<em>文件系统</em>，因此&nbsp;<code style="font-family: monospace; font-size: small !important; ">initrd</code>&nbsp;函数会提供一种启动方法来获得对磁盘的访问，并挂载真正的根文件系统。在一个没有硬盘的嵌入式环境中，<code style="font-family: monospace; font-size: small !important; ">initrd</code>&nbsp;可以是最终的根文件系统，或者也可以通过网络文件系统（NFS）来挂载最终的根文件系统。</p><p>&#160;</p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; "><span style="font-family: Simsun; font-size: medium; "></span></p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; "><a name="N101F4"><span class="atitle" style="font-size: 1.5em; font-weight: bold; ">Init</span></a></p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; ">当内核被引导并进行初始化之后，内核就可以启动自己的第一个用户空间应用程序了。这是第一个调用的使用标准 C 库编译的程序。在此之前，还没有执行任何标准的 C 应用程序。</p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; ">在桌面 Linux 系统上，第一个启动的程序通常是&nbsp;<code style="font-family: monospace; font-size: small !important; ">/sbin/init</code>。但是这不是一定的。很少有嵌入式系统会需要使用&nbsp;<code style="font-family: monospace; font-size: small !important; ">init</code>&nbsp;所提供的丰富初始化功能（这是通过&nbsp;<code style="font-family: monospace; font-size: small !important; ">/etc/inittab</code>&nbsp;进行配置的）。在很多情况下，我们可以调用一个简单的 shell 脚本来启动必需的嵌入式应用程序。</p><p>&#160;</p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; "></p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; "><a name="N1020D"><span class="atitle" style="font-size: 1.5em; font-weight: bold; ">结束语</span></a></p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; ">与 Linux 本身非常类似，Linux 的引导过程也非常灵活，可以支持众多的处理器和硬件平台。最初，加载引导加载程序提供了一种简单的方法，不用任何花架子就可以引导 Linux。LILO 引导加载程序对引导能力进行了扩充，但是它却缺少文件系统的感知能力。最新一代的引导加载程序，例如 GRUB，允许 Linux 从一些文件系统（从 Minix 到 Reise）上进行引导。</p><br><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; "><a name="resources"><span class="atitle" style="font-size: 1.5em; font-weight: bold; ">参考资料</span></a></p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; "><strong style="font-size: 1em; font-weight: bold; ">学习</strong></p><ul style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 5px; padding-bottom: 5px; font-size: 0.76em; font-family: Simsun; "><li style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 5px; padding-bottom: 3px; ">您可以参阅本文在 developerWorks 全球站点上的&nbsp;<a href="http://www.ibm.com/developerworks/linux/library/l-linuxboot/?S_TACT=105AGX52&amp;S_CMP=cn-a-l" target="_blank" style="color: rgb(76, 110, 148); ">英文原文</a>&nbsp;。<br><br></li><li style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 5px; padding-bottom: 3px; "><a href="http://mirror.href.com/thestarman/asm/mbr/MBR_in_detail.htm" style="color: rgb(76, 110, 148); ">Boot Records Revealed</a>&nbsp;是有关 MBR 和各种引导加载程序很好的资源。这个资源不仅仅是有关 MBR 的资料的汇编，还讨论了 GRUB、LILO 和各种 Windows&#174; 引导加载程序的问题。&nbsp;<br><br></li><li style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 5px; padding-bottom: 3px; ">请查看&nbsp;<a href="http://www.rwc.uc.edu/koehler/comath/42.html" style="color: rgb(76, 110, 148); ">Disk Geometry</a>&nbsp;页面来理解磁盘及其结构。您会发现有关磁盘的有用属性。&nbsp;<br><br></li><li style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 5px; padding-bottom: 3px; "><a href="http://en.wikipedia.org/wiki/LiveCD" style="color: rgb(76, 110, 148); ">live CD</a>&nbsp;是一个可以从 CD 或 DVD 上引导的操作系统，它不需要使用硬盘。&nbsp;<br><br></li><li style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 5px; padding-bottom: 3px; ">&#8220;<a href="http://www.ibm.com/developerworks/cn/linux/l-bootload.html" style="color: rgb(76, 110, 148); ">引导加载程序之争：了解 LILO 和 GRUB</a>&#8221;（developerWorks，2005 年 8 月）详细介绍了 LILO 和 GRUB 引导加载程序。&nbsp;<br><br></li><li style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 5px; padding-bottom: 3px; ">在 developerWorks 上的&nbsp;<a href="http://www.ibm.com/developerworks/cn/linux/lpi/101.html" style="color: rgb(76, 110, 148); ">LPI 考试准备</a>&nbsp;系列教程中，我们可以学习有关引导 Linux 系统的详细介绍，以及在准备参加系统管理员认证考试时需要准备的 Linux 基础知识。&nbsp;<br><br></li><li style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 5px; padding-bottom: 3px; "><a href="http://www.freshmeat.net/projects/lilo/" style="color: rgb(76, 110, 148); ">LILO</a>&nbsp;是 GRUB 的先驱，但是我们可能发现它依然可以引导 Linux。&nbsp;<br><br></li><li style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 5px; padding-bottom: 3px; "><a href="http://www.netadmintools.com/html/mkinitrd.man.html" style="color: rgb(76, 110, 148); ">mkintrd</a>&nbsp;命令用来创建初始的 RAM 磁盘映像。这个命令可以用来构建初始的根文件系统，它可以用来引导允许提前加载访问真正根文件系统所需要的块设备的配置。&nbsp;<br><br></li><li style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 5px; padding-bottom: 3px; ">在&nbsp;<a href="http://debianlinux.net/linux.html" style="color: rgb(76, 110, 148); ">Debian Linux Kernel Project</a>&nbsp;中，我们可以找到更多有关 Linux 内核、引导和嵌入式开发的信息。&nbsp;<br><br></li><li style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 5px; padding-bottom: 3px; ">在&nbsp;<a href="http://www.ibm.com/developerworks/cn/linux/" style="color: rgb(76, 110, 148); ">developerWorks Linux 专区</a>&nbsp;中可以找到为 Linux 开发人员准备的更多资源。&nbsp;<br><br></li><li style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 5px; padding-bottom: 3px; ">随时关注&nbsp;<a href="http://www.ibm.com/developerworks/offers/techbriefings/?S_TACT=105AGX52&amp;S_CMP=cn-a-l" style="color: rgb(76, 110, 148); ">developerWorks 技术事件和网络广播</a>。&nbsp;<br><br></li></ul><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; "><strong style="font-size: 1em; font-weight: bold; ">获得产品和技术</strong></p><ul style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 5px; padding-bottom: 5px; font-size: 0.76em; font-family: Simsun; "><li style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 5px; padding-bottom: 3px; "><a href="http://www.linuxdevices.com/articles/AT8516113114.html" style="color: rgb(76, 110, 148); ">MicroMonitor</a>&nbsp;为各种小型的目标设备提供了引导环境。我们可以使用这个监视器在嵌入式环境中引导 Linux。它已经移植到 ARM、 XScale、MIPS、PowerPC、Coldfire 和 Hitachi 的 Super-H 上了。&nbsp;<br><br></li><li style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 5px; padding-bottom: 3px; "><a href="http://www.gnu.org/software/grub/" style="color: rgb(76, 110, 148); ">GNU GRUB</a>&nbsp;是一个具有众多选项和灵活性的引导 shell。&nbsp;<br><br></li><li style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 5px; padding-bottom: 3px; "><a href="http://www.linuxbios.org/index.php/Main_Page" style="color: rgb(76, 110, 148); ">LinuxBIOS</a>&nbsp;是 BIOS 的一个替代品。LinuxBIOS 不但可以引导 Linux，而且它本身就是一个压缩的 Linux 内核。&nbsp;<br><br></li><li style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 5px; padding-bottom: 3px; "><a href="http://www.openbios.org/" style="color: rgb(76, 110, 148); ">OpenBIOS</a>&nbsp;是另一个可移植的 BIOS 项目，可以在很多体系结构上进行操作，例如 x86、Alpha 和 AMD64。&nbsp;<br><br></li><li style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 5px; padding-bottom: 3px; ">在&nbsp;<a href="http://www.kernel.org/" style="color: rgb(76, 110, 148); ">kernel.org</a>&nbsp;上可以找到最新的内核树。&nbsp;<br><br></li><li style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-right: 5px; padding-bottom: 3px; ">使用&nbsp;<a href="http://www.ibm.com/developerworks/downloads/?S_TACT=105AGX52&amp;S_CMP=cn-a-l" style="color: rgb(76, 110, 148); ">IBM 试用版软件</a>&nbsp;改进您的下一个开发项目，从 developerWorks 上可以直接下载这些软件。&nbsp;</li></ul><div><font face="arial, nsimsun, sans-serif"><span style="font-size: 12px;"><br></span></font></div><p>&#160;</p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; "><br></p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; ">from：</p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; "><a href="http://www.ibm.com/developerworks/cn/linux/l-linuxboot/">http://www.ibm.com/developerworks/cn/linux/l-linuxboot/</a></p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; "><br></p><p style="font-family: arial, nsimsun, sans-serif; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0.3em; padding-right: 5px; padding-bottom: 0.7em; padding-left: 5px; font-size: 0.76em; "><br></p><p>&#160;</p></div><img src ="http://www.cppblog.com/beautykingdom/aggbug/133023.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-11-08 19:58 <a href="http://www.cppblog.com/beautykingdom/archive/2010/11/08/133023.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>aix支持大于2G的文件</title><link>http://www.cppblog.com/beautykingdom/archive/2010/11/04/132461.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Thu, 04 Nov 2010 09:42:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/11/04/132461.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/132461.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/11/04/132461.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/132461.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/132461.html</trackback:ping><description><![CDATA[<div>加</div><div>-D_LARGE_FILES 1</div><div>参数就可以了。</div>
<img src ="http://www.cppblog.com/beautykingdom/aggbug/132461.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-11-04 17:42 <a href="http://www.cppblog.com/beautykingdom/archive/2010/11/04/132461.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>gdb带参数调试</title><link>http://www.cppblog.com/beautykingdom/archive/2010/09/29/128087.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Wed, 29 Sep 2010 13:31:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/09/29/128087.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/128087.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/09/29/128087.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/128087.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/128087.html</trackback:ping><description><![CDATA[<span  style="font-family: verdana, sans-serif; font-size: 14px; line-height: 21px; ">gdb --args ./testprg arg1 arg2&nbsp;</span>

<div><span  style="font-family: verdana, sans-serif; font-size: 14px; line-height: 21px; "><br></span></div><div><span  style="font-family: verdana, sans-serif; font-size: 14px; line-height: 21px; ">from：</span></div><div><span  style="font-family: verdana, sans-serif; font-size: 14px; line-height: 21px; "><a href="http://blog.csdn.net/lw1a2/archive/2006/07/30/1001298.aspx">http://blog.csdn.net/lw1a2/archive/2006/07/30/1001298.aspx</a></span></div><img src ="http://www.cppblog.com/beautykingdom/aggbug/128087.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-09-29 21:31 <a href="http://www.cppblog.com/beautykingdom/archive/2010/09/29/128087.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux中ctime、mtime、atime的区别</title><link>http://www.cppblog.com/beautykingdom/archive/2010/09/15/126652.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Wed, 15 Sep 2010 05:14:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/09/15/126652.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/126652.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/09/15/126652.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/126652.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/126652.html</trackback:ping><description><![CDATA[<table border="0" cellspacing="0" cellpadding="0" width="100%" style="border-collapse: collapse; word-wrap: break-word; font-family: song, Verdana; font-size: 12px; -webkit-border-horizontal-spacing: 1px; -webkit-border-vertical-spacing: 1px; "><tbody><tr style="font: normal normal normal 12px/normal song, Verdana; "><td align="middle" style="font: normal normal normal 12px/normal song, Verdana; "><table border="0" cellspacing="0" cellpadding="0" width="100%" style="border-collapse: collapse; word-wrap: break-word; "><tbody><tr style="font: normal normal normal 12px/normal song, Verdana; "><td style="font: normal normal normal 12px/normal song, Verdana; "><div id="art" style="margin-top: 15px; margin-right: 15px; margin-bottom: 15px; margin-left: 15px; "><font size="2" style="font-family: SimSun; ">当你同熟练的UNIX用户进行交谈时，你经常会听到他们傲慢地讲出术语&#8220;改变时间(change time)&#8221;和&#8220;修改时间(modification time)&#8221;。对于许多人(和许多字典而言),改变和修改是相同的。这里会有什么不同那？<br style="font: normal normal normal 12px/normal song, Verdana; "></font><div class="t_msgfont" style="font-family: SimSun; "><font size="2"><br style="font: normal normal normal 12px/normal song, Verdana; ">&nbsp;&nbsp;&nbsp; 改变和修改之间的区别在于是改某个组件的标签还是更改它的内容。如果有人说chmod a-w myfile,那么这是一个改变；如果有人说echo foo &gt;&gt; myfile,那么&nbsp;<br style="font: normal normal normal 12px/normal song, Verdana; ">这是一个修改。改变是文件的索引节点发生了改变；修改是文本本身的内容发生了变化。[文件的修改时间也叫时间标志 (timestamp).]<br style="font: normal normal normal 12px/normal song, Verdana; "><br style="font: normal normal normal 12px/normal song, Verdana; ">&nbsp;&nbsp;&nbsp; 只要讨论改变时间和修改时间，就不可能不提到&#8220;访问时间(access time)&#8221;.访问时间是文件最后一次被读取的时间。因此阅读一个文件会更新它的访问时间，当它的改变时间并没有变化(有关文件的信息没有被改变)，它的修改时间也同样如此(文件本身没有被改变)<br style="font: normal normal normal 12px/normal song, Verdana; "><br style="font: normal normal normal 12px/normal song, Verdana; ">有时，在许多地方改变时间或者&#8220;ctime&#8221;被错误地写成&#8220;创建时间&#8221;，包括某些UNIX参考手册。不要相信他们</font></div><div id="message607093" class="t_msgfont" style="font-family: SimSun; "><font size="2">下面是我man出来的内容，仅供参考！<br style="font: normal normal normal 12px/normal song, Verdana; "><br style="font: normal normal normal 12px/normal song, Verdana; ">&nbsp; &nbsp;&nbsp;&nbsp;st_atime<br style="font: normal normal normal 12px/normal song, Verdana; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;Time when file data was last accessed. Changed by&nbsp;&nbsp;the<br style="font: normal normal normal 12px/normal song, Verdana; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;following&nbsp; &nbsp;functions:&nbsp; &nbsp;creat(),&nbsp; &nbsp;mknod(),&nbsp; &nbsp;pipe(),<br style="font: normal normal normal 12px/normal song, Verdana; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;utime(2), and read(2).<br style="font: normal normal normal 12px/normal song, Verdana; "><br style="font: normal normal normal 12px/normal song, Verdana; ">&nbsp; &nbsp;&nbsp;&nbsp;st_mtime<br style="font: normal normal normal 12px/normal song, Verdana; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;Time when data was last modified. Changed by the&nbsp;&nbsp;fol-<br style="font: normal normal normal 12px/normal song, Verdana; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;lowing&nbsp;&nbsp;functions:&nbsp;&nbsp;creat(), mknod(), pipe(), utime(),<br style="font: normal normal normal 12px/normal song, Verdana; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;and write(2).<br style="font: normal normal normal 12px/normal song, Verdana; "><br style="font: normal normal normal 12px/normal song, Verdana; ">&nbsp; &nbsp;&nbsp;&nbsp;st_ctime<br style="font: normal normal normal 12px/normal song, Verdana; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;Time when file status was last changed. Changed by the<br style="font: normal normal normal 12px/normal song, Verdana; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;following&nbsp; &nbsp;functions:&nbsp; &nbsp;chmod(),&nbsp; &nbsp;chown(),&nbsp;&nbsp;creat(),<br style="font: normal normal normal 12px/normal song, Verdana; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;link(2),&nbsp;&nbsp;mknod(),&nbsp;&nbsp;pipe(),&nbsp;&nbsp;unlink(2),&nbsp;&nbsp;utime(),&nbsp;&nbsp;and<br style="font: normal normal normal 12px/normal song, Verdana; ">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;write().<br style="font: normal normal normal 12px/normal song, Verdana; "><br style="font: normal normal normal 12px/normal song, Verdana; ">ls显示出的time应该是mtime。</font></div><div style="font-family: SimSun; "><font size="2"><br style="font: normal normal normal 12px/normal song, Verdana; ">touch后，文件的三个时间应该都会改变，可以试一试。</font></div><div style="font-family: SimSun; "><font size="2"><br style="font: normal normal normal 12px/normal song, Verdana; ">问题描述<br style="font: normal normal normal 12px/normal song, Verdana; ">文件的 ctime、mtime、atime 之间有什么区别?&nbsp;<br style="font: normal normal normal 12px/normal song, Verdana; ">配置信息<br style="font: normal normal normal 12px/normal song, Verdana; ">解决方法<br style="font: normal normal normal 12px/normal song, Verdana; ">文件的 Access time，atime 是在读取文件或者执行文件时更改的。<br style="font: normal normal normal 12px/normal song, Verdana; ">文件的 Modified time，mtime 是在写入文件时随文件内容的更改而更改的。<br style="font: normal normal normal 12px/normal song, Verdana; ">文件的 Create time，ctime 是在写入文件、更改所有者、权限或链接设置时随 Inode 的内容更改而更改的。&nbsp;<br style="font: normal normal normal 12px/normal song, Verdana; "><br style="font: normal normal normal 12px/normal song, Verdana; ">因此，更改文件的内容即会更改 mtime 和 ctime，但是文件的 ctime 可能会在 mtime 未发生任何变化时更改 - 在权限更改，但是文件内容没有变化的情况下。&nbsp;<br style="font: normal normal normal 12px/normal song, Verdana; ">ls(1) 命令可用来列出文件的 atime、ctime 和 mtime。<br style="font: normal normal normal 12px/normal song, Verdana; ">ls -lc filename&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;列出文件的 ctime<br style="font: normal normal normal 12px/normal song, Verdana; ">ls -lu filename&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;列出文件的 atime<br style="font: normal normal normal 12px/normal song, Verdana; ">ls -l filename&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; 列出文件的 mtime&nbsp;<br style="font: normal normal normal 12px/normal song, Verdana; "><br style="font: normal normal normal 12px/normal song, Verdana; ">&nbsp;&nbsp;&nbsp; atime不一定在访问文件之后被修改，因为：使用ext3文件系统的时候，如果在mount的时候使用了noatime参数那么就不会更新atime的信息。而这是加了 noatime 取消了, 不代表真實情況.反正, 這三個 time stamp 都放在 inode 中.若 mtime, atime 修改, inode 就一定會改, 既然 inode 改了, 那 ctime 也就跟著要改了.之所以在 mount option 中使用 noatime, 就是不想 file system 做太多的修改, 而改善讀取效能.</font></div></div></td></tr></tbody></table><p style="font: normal normal normal 12px/normal song, Verdana; line-height: 18px; margin-top: 5px; margin-right: 5px; margin-bottom: 5px; margin-left: 5px; "></p></td></tr><tr style="font: normal normal normal 12px/normal song, Verdana; "><td height="25" style="font: normal normal normal 12px/normal song, Verdana; ">&nbsp;<font color="#000099"><strong>原文地址</strong></font>&nbsp;<font color="#0000ff"><a href="http://jianjian.blog.51cto.com/35031/103231" target="_blank" style="text-decoration: underline; color: rgb(0, 68, 182); ">http://jianjian.blog.51cto.com/35031/103231</a><br><br>from：<br><a href="http://blog.chinaunix.net/u3/115191/showart_2319400.html">http://blog.chinaunix.net/u3/115191/showart_2319400.html</a></font></td></tr></tbody></table>
<img src ="http://www.cppblog.com/beautykingdom/aggbug/126652.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-09-15 13:14 <a href="http://www.cppblog.com/beautykingdom/archive/2010/09/15/126652.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>从同步互斥机制到智能指针使用成本</title><link>http://www.cppblog.com/beautykingdom/archive/2010/08/30/125263.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Mon, 30 Aug 2010 04:10:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/08/30/125263.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/125263.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/08/30/125263.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/125263.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/125263.html</trackback:ping><description><![CDATA[

<p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; ">一 semaphore机制</p><p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; ">古老的信号量机制，80年代初，从System V体系中产生，称为System v信号量。90年代，Posix标准确立，其中的信号量称为posix信号量。当前linux系统支持这两种信号量（man semget/ man sem_post)。System v信号量为有名信号量，可以用于多进程间的互斥同步。posix信号量分有名和无名两种，当前linux只支持无名信号量，可以用于多线程之间的互斥同步，通过共享内存也可以用于多进程之间。<br>信号量属于内核级别的互斥同步机制，相关调用总是陷入内核态，属于功能强大/重量级的实现。<br><br>&nbsp;&nbsp; 二 spinlock机制<br>多核SMP的cpu流行后，出现的新的互斥同步机制。spinlock实现原理为用户态循环尝试机制，不陷入内核态进行线程切换。spinlock的原子性通过CAS(CompareAndSwap)原语实现。使用spinlock时，应该保证保护区间内代码执行迅速，不应该存在io等耗时操作。<br>多核系统下，针对可快速执行的保护区使用用户态循环尝试机制，可以保证执行线程不需要引起上下文切换即可快速执行通过，这种机制也被形象的称为lock-free机制。我们可以这样理解：lock-free机制即为循环尝试，spinlock是它的具体实现。<br><br>spinlock的实现有多种，常见的有pthread_spin_lock，该spinlock无限制循环尝试，在多核环境下并且保护区代码执行迅速时，执行线程很快可以拿到锁，但当单核环境或者保护区代码执行慢速时，则会耗尽该线程拥有的时间片之后交出cpu，造成cpu的浪费。另一常见的spinlock是boost智能指针中的实现，进行3次无间断的循环CAS原语判断，之后若再次失败，则调用sleep族函数，交出cpu执行权，待再次分配到cpu时间片后继续进行CAS原语判断操作。<br></p><p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; "><br><span style="line-height: 22px; font-size: 14pt; ">&nbsp;&nbsp; <span style="FONT-SIZE: 8pt ">三 mutex机制</span></span><br>mutex属于os之上的再次封装实现。在linux2.6内核上，线程库为nptl，其中的mutex基于futex机制实现，它的实现原理，简单说就是spinlock+semaphore，首先使用spinlock尝试，可以拿到锁则直接向下执行，拿不到锁则执行semaphore机制，陷入内核态，进入线程切换。<br>在多核环境下，当mutex保护的代码段内无io操作，执行很快时，大多数情况下通过spinlock都可拿到锁，不需要陷入内核态。</p><p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; "><br><span style="line-height: 22px; font-size: 14pt; ">&nbsp;&nbsp;<span style="FONT-SIZE: 8pt ">四 为智能指针正名(boost)</span></span><br>智能指针的引用计数仅仅为一个整型变量的增减，属于执行迅速的典型，使用spinlock机制保护，最新boost版本中仅仅是spinlock，而非mutex。从性能角度说，使用智能指针的现象是cpu略微上升（循环尝试导致），而并发量/单个请求的响应时间并无明显影响。proactor机制实现的网络层，智能指针基本无法绕过，刻意避免带来的只能是丑陋的代码和维护量的上升。但线程之间尽量避免传递指针（智能指针），通过传递id等代替。<br>智能指针有它使用的场景，不能滥用，也不能刻意避免。</p><p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; ">from:</p><p style="font-size: 13px; line-height: 19px; margin-top: 10px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; text-indent: 20px; font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; "><a href="http://www.cppblog.com/CppExplore/archive/2010/08/28/125067.html">http://www.cppblog.com/CppExplore/archive/2010/08/28/125067.html</a></p>
<img src ="http://www.cppblog.com/beautykingdom/aggbug/125263.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-08-30 12:10 <a href="http://www.cppblog.com/beautykingdom/archive/2010/08/30/125263.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux僵尸进程产生及如何避免 </title><link>http://www.cppblog.com/beautykingdom/archive/2010/08/26/124849.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Thu, 26 Aug 2010 09:09:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/08/26/124849.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/124849.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/08/26/124849.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/124849.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/124849.html</trackback:ping><description><![CDATA[在fork()/execve()过程中，假设子进程结束时父进程仍存在，而父进程fork()之前既没安装SIGCHLD信号处理函数调用
waitpid()等待子进程结束，又没有显式忽略该信号，则子进程成为僵尸进程，无法正常结束，此时即使是root身份kill-9也不能杀死僵尸进
程。补救办法是杀死僵尸进程的父进程(僵尸进程的父进程必然存在)，僵尸进程成为"孤儿进程"，过继给1号进程init，init始终会负责清理僵尸进
程。
<p>　　僵尸进程是指的父进程已经退出,而该进程dead之后没有进程接受,就成为僵尸进程.(zombie)进程</p>
<p>　　怎样产生僵尸进程的：</p>
<p>　　一个进程在调用exit命令结束自己的生命的时候，其实它并没有真正的被销毁，而是留下一个称为僵尸进程（Zombie）的数据结构（系统调用
exit，它的作用是使进程退出，但也仅仅限于将一个正常的进程变成一个僵尸进程，并不能将其完全销毁）。在Linux进程的状态中，僵尸进程是非常特殊的一种，它已经放弃了几乎所有内存空间，没有任何可执行代码，也不能被调度，仅仅在进程列表中保留一个位置，记载该进程的退出状态等信息供其他进程收集，除此之外，僵尸进程不再占有任何内存空间。它需要它的父进程来为它收尸，如果他的父进程没安装SIGCHLD信号处理函数调用wait或waitpid()等待子进程结束，又没有显式忽略该信号，那么它就一直保持僵尸状态，如果这时父进程结束了，那么init进程自动会接手这个子进程，为它收尸，它还是能被清除的。但是如果如果父进程是一个循环，不会结束，那么子进程就会一直保持僵尸状态，这就是为什么系统中有时会有很多的僵尸进程。</p>
<p>　　Linux系统对运行的进程数量有限制，如果产生过多的僵尸进程占用了可用的进程号，将会导致新的进程无法生成。这就是僵尸进程对系统的最大危害。</p>
<p>　　僵尸进程实例：</p>
<p>　　/*-----zombie1.c-----*/</p>
<p>　　#include "sys/types.h"</p>
<p>　　#include "sys/wait.h"</p>
<p>　　#include "stdio.h"</p>
<p>　　#include "unistd.h"</p>
<p>　　int main(int argc, char* argv[])</p>
<p>　　{</p>
<p>　　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(1)</p>
<p>　　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>　　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  pid_t chi = fork();</p>
<p>　　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(chi == 0)</p>
<p>　　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>　　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; execl("/bin/bash","bash","-c","ls",NULL);</p>
<p>　　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>　　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sleep(2);</p>
<p>　　}</p>
<p>　　会不停地产生僵死进程ls；</p>
<p>　　/*-----zombie2.c-----*/</p>
<p>　　#include &lt;stdio.h&gt;</p>
<p>　　#include&lt;sys/types.h&gt;</p>
<p>　　main()</p>
<p>　　{</p>
<p>　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 　if(!fork())</p>
<p>　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 　{</p>
<p>　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 　printf("child pid=%d\n", getpid());</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 　　exit(0);</p>
<p>　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 　}</p>
<p>　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 　/*wait();*/</p>
<p>　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 　/*waitpid(-1,NULL,0);*/</p>
<p>　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 　sleep(60);</p>
<p>　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 　printf("parent pid=%d \n", getpid());</p>
<p>　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 　exit(0);</p>
<p>　　}</p>
<p>　　60s内会不断产生僵尸进程，直到父进程exit(0);</p>
<p>　　如果在调用wait/waitpid来为子进程收尸，就不会产生僵尸进程了。</p>
<p>　　PS：运行例子，先gcc zombie1.c -o zombie编译，然后运行zombie；</p>
<p>　　然后可以可用ps -ef来查看是否产生了僵尸进程。</p>
<p>　　怎么查看僵尸进程：</p>
<p>　　利用命令ps，可以看到有标记为Z的进程就是僵尸进程。</p>
<p>　　怎样来清除僵尸进程：</p>
<p>　　1.改写父进程，在子进程死后要为它收尸。具体做法是接管SIGCHLD信号。子进程死后，会发送SIGCHLD信号给父进程，父进程收到此信
号后，执行
waitpid()函数为子进程收尸。这是基于这样的原理：就算父进程没有调用wait，内核也会向它发送SIGCHLD消息，尽管对的默认处理是忽略，
如果想响应这个消息，可以设置一个处理函数。</p>
2.把父进程杀掉。父进程死后，僵尸进程成为"孤儿进程"，过继给1号进程init，init始终会负责清理僵尸进程．它产生的所有僵尸进程也跟着消失<br>在Linux中可以用
<p>　　ps auwx</p>
<p>　　发现僵尸进程</p>
<p>　　a all w/ tty, including other users 所有窗口和终端，包括其他用户的进程</p>
<p>　　u user-oriented 面向用户(用户友好)</p>
<p>　　-w,w wide output 宽格式输出</p>
<p>　　x processes w/o controlling ttys</p>
<p>　　在僵尸进程后面 会标注</p>
<p>　　ps axf</p>
<p>　　看进程树，以树形方式现实进程列表</p>
<p>　　ps axm</p>
<p>　　会把线程列出来,在<a href="http://linux.chinaitlab.com/" class="channel_keylink" target="_blank">linux</a>下进程和线程是统一的，是轻量级进程的两种方式。</p>
<p>　　ps axu</p>
<p>　　显示进程的详细状态</p>
<p>　　killall</p>
<p>　　kill -15</p>
<p>　　kill -9</p>
<p>　　一般都不能杀掉 defunct进程</p>
<p>　　用了kill -15,kill -9以后 之后反而会多出更多的僵尸进程</p>
<p>　　kill -kill pid</p>
<p>　　fuser -k pid</p>
<p>　　可以考虑杀死他的parent process，</p>
<p>　　kill -9 他的parent process</p>
<p>　　=========================================== 一个已经终止,但是其父进程尚未对其进行善后处理（获取终止子进程的有关信息、释放它仍占用的资源）的进程被称为僵死进程(Zombie Process)。</p>
<p>　　避免zombie的方法：</p>
<p>　　1)在SVR4中，如果调用signal或sigset将SIGCHLD的配置设置为忽略,则不会产生僵死子进程。另外,使用SVR4版的 sigaction,则可设置SA_NOCLDWAIT标志以避免子进程僵死。</p>
<p>　　Linux中也可使用这个，在一个程序的开始调用这个函数</p>
<p>　　signal(SIGCHLD,SIG_IGN);</p>
<p>　　2)调用fork两次。程序8 - 5 实现了这一点。</p>
<p>　　3)用waitpid等待子进程返回.</p>
<p>　　===========================================</p>
<p>　　zombie进程是僵死进程。防止它的办法，一是用wait,waitpid之类的函数获得进程的终止状态，以释放资源。另一个是fork两次</p>
<p>　　===========================================</p>
<p>　　defunct进程只是在process table里还有一个记录，其他的资源没有占用，除非你的系统的process个数的限制已经快超过了，zombie进程不会有更多的坏处。</p>
<p>　　可能唯一的方法就是reboot系统可以消除zombie进程。</p>
<p>　　===========================================</p>
<p>　　任何程序都有僵尸状态，它占用一点内存资源(也就是进程表里还有一个记录)，仅仅是表象而已不必害怕。如果程序有问题有机会遇见，解决大批量僵尸简单有效的办法是重起。kill是无任何效果的</p>
<p>　　fork与zombie/defunct"</p>
<p>　　在Unix下的一些进程的运作方式。当一个进程死亡时,它并不是完全的消失了。进程终止,它不再运行,但是还有一些残留的小东西等待父进程收
回。这些残留的东西包括子进程的返回值和其他的一些东西。当父进程 fork()一个子进程后,它必须用 wait() 或者 waitpid()
等待子进程退出。正是这个 wait() 动作来让子进程的残留物消失。</p>
<p>　　自然的，在上述规则之外有个例外:父进程可以忽略 SIGCLD 软中断而不必要 wait()。可以这样做到(在支持它的系统上,比如Linux):</p>
<p>　　main()</p>
<p>　　{</p>
<p>　　signal(SIGCLD, SIG_IGN); /* now I don't have to wait()! */</p>
fork();
<p>　　fork();</p>
<p>　　fork(); /* Rabbits, rabbits, rabbits! */</p>
<p>　　｝</p>
<p>　　现在，子进程死亡时父进程没有 wait()，通常用 ps 可以看到它被显示为&#8220;&#8221;。它将永远保持这样 直到 父进程 wait()，或者按以下方法处理。</p>
<p>　　这里是你必须知道的另一个规则:当父进程在它wait()子进程之前死亡了(假定它没有忽略 SIGCLD),子进程将把
init(pid1)进程作为它的父进程。如果子进程工作得很好并能够控制，这并不是问题。但如果子进程已经是defunct，我们就有了一点小麻烦。
看，原先的父进程不可能再 wait()，因为它已经消亡了。这样，init 怎么知道 wait() 这些zombie 进程。</p>
<p>　　答案：不可预料的。在一些系统上，init周期性的破坏掉它所有的defunct进程。在另外一些系统中,它干脆拒绝成为任何defunct进
程的父进程，而是马上毁灭它们。如果你使用上述系统的一种,可以写一个简单的循环，用属于init的defunct进程填满进程表。这大概不会令你的系统
管理员很高兴吧?</p>
<p>　　你的任务：确定你的父进程不要忽略 SIGCLD，也不要 wait() 它 fork() 的所有进程。不过，你也未必
要总是这样做（比如，你要起一个 daemon 或是别的什么东西）,但是你必须小心编程，如果你是一个
fork()的新手。另外，也不要在心理上有任何束缚。</p>
<p>　　总结：</p>
<p>　　子进程成为 defunct 直到父进程 wait()，除非父进程忽略了 SIGCLD 。</p>
<p>　　更进一步，父进程没有 wait() 就消亡（仍假设父进程没有忽略 SIGCLD ）的子进程（活动的或者 defunct）成为 init 的子进程，init 用重手法处理它们。</p>
<p><br></p>
<p>from:</p>
<p>http://linux.chinaitlab.com/administer/818916.html<br></p>
<br>  <img src ="http://www.cppblog.com/beautykingdom/aggbug/124849.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-08-26 17:09 <a href="http://www.cppblog.com/beautykingdom/archive/2010/08/26/124849.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个基于Event Poll(epoll)的TCP Server Framework,浅析epoll</title><link>http://www.cppblog.com/beautykingdom/archive/2010/08/25/124730.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Wed, 25 Aug 2010 12:41:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/08/25/124730.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/124730.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/08/25/124730.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/124730.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/124730.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: epoll,event poll,on linux kernel 2.6.x.pthread,nptl-2.12&nbsp;&nbsp;&nbsp;LT/ET:ET也会多次发送event,当然频率远低于LT,但是epoll one shot才是真正的对"one connection&nbsp;VS one thread in worker thread pool,不依赖于任何connection-...&nbsp;&nbsp;<a href='http://www.cppblog.com/beautykingdom/archive/2010/08/25/124730.html'>阅读全文</a><img src ="http://www.cppblog.com/beautykingdom/aggbug/124730.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-08-25 20:41 <a href="http://www.cppblog.com/beautykingdom/archive/2010/08/25/124730.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> pthread_join函数及linux线程</title><link>http://www.cppblog.com/beautykingdom/archive/2010/08/24/124566.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Tue, 24 Aug 2010 10:01:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/08/24/124566.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/124566.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/08/24/124566.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/124566.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/124566.html</trackback:ping><description><![CDATA[<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><strong><span style="font-size: 15pt;" lang="EN-US"><span style="font-family: Times New Roman;">pthread_join</span></span></strong><strong><span style="font-size: 15pt; font-family: 宋体;">函数及</span></strong><strong><span style="font-size: 15pt;" lang="EN-US"><span style="font-family: Times New Roman;">linux</span></span></strong><strong><span style="font-size: 15pt; font-family: 宋体;">线程</span></strong></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><strong></strong></p>
<span>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">pthread_join</span></span><span style="font-size: 14pt; font-family: 宋体;">使一个线程等待另一个线程结束。</span><span style="font-size: 14pt;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt; font-family: 宋体;">代码中如果没有</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">pthread_join</span></span><span style="font-size: 14pt; font-family: 宋体;">主线程会很快结束从而使整个进程结束，从而使创建的线程没有机会开始执行就结束了。加入</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">pthread_join</span></span><span style="font-size: 14pt; font-family: 宋体;">后，主线程会一直等待直到等待的线程结束自己才结束，使创建的线程有机会执行。</span><span style="font-size: 14pt;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt; font-family: 宋体;">所有线程都有一个线程号，也就是</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">Thread ID</span></span><span style="font-size: 14pt; font-family: 宋体;">。其类型为</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">pthread_t</span></span><span style="font-size: 14pt; font-family: 宋体;">。通过调用</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">pthread_self()</span></span><span style="font-size: 14pt; font-family: 宋体;">函数可以获得自身的线程号。</span><span style="font-size: 14pt;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt; font-family: 宋体;">下面说一下如何创建一个线程。</span><span style="font-size: 14pt;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt; font-family: 宋体;">通过创建线程，线程将会执行一个线程函数，该线程格式必须按照下面来声明：</span><span style="font-size: 14pt;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>void * Thread_Function(void *)</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt; font-family: 宋体;">创建线程的函数如下：</span><span style="font-size: 14pt;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>int pthread_create(pthread_t *restrict thread,</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>const pthread_attr_t *restrict attr,</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>void *(*start_routine)(void*), void *restrict arg);</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt; font-family: 宋体;">下面说明一下各个参数的含义：</span><span style="font-size: 14pt;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">thread</span></span><span style="font-size: 14pt; font-family: 宋体;">：所创建的线程号。</span><span style="font-size: 14pt;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">attr</span></span><span style="font-size: 14pt; font-family: 宋体;">：所创建的线程属性，这个将在后面详细说明。</span><span style="font-size: 14pt;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">start_routine</span></span><span style="font-size: 14pt; font-family: 宋体;">：即将运行的线程函数。</span><span style="font-size: 14pt;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">art</span></span><span style="font-size: 14pt; font-family: 宋体;">：传递给线程函数的参数。</span><span style="font-size: 14pt;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt; font-family: 宋体;">下面是一个简单的创建线程例子：</span><span style="font-size: 14pt;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">#include &lt;pthread.h&gt;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">#include &lt;stdio.h&gt;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">/* Prints x&#8217;s to stderr. The parameter is unused. Does not return. */</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">void* print_xs (void* unused)</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">{</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">while (1)</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">fputc (&#8216;x&#8217;, stderr);</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">return NULL;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">}</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">/* The main program. */</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">int main ()</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">{</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">pthread_t thread_id;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">/* Create a new thread. The new thread will run the print_xs</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">function. */</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">pthread_create (&amp;thread_id, NULL, &amp;print_xs, NULL);</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">/* Print o&#8217;s continuously to stderr. */</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">while (1)</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">fputc (&#8216;o&#8217;, stderr);</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">return 0;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">}</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;"><span>&nbsp;</span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt; font-family: 宋体;">在编译的时候需要注意，由于线程创建函数在</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">libpthread.so</span></span><span style="font-size: 14pt; font-family: 宋体;">库中，所以在编译命令中需要将该库导入。命令如下：</span><span style="font-size: 14pt;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">gcc &#8211;o createthread &#8211;lpthread createthread.c</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt; font-family: 宋体;">如果想传递参数给线程函数，可以通过其参数</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">arg</span></span><span style="font-size: 14pt; font-family: 宋体;">，其类型是</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">void *</span></span><span style="font-size: 14pt; font-family: 宋体;">。如果你需要传递多个参数的话，可以考虑将这些参数组成一个结构体来传递。另外，由于类型是</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">void *</span></span><span style="font-size: 14pt; font-family: 宋体;">，所以你的参数不可以被提前释放掉。</span><span style="font-size: 14pt;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt; font-family: 宋体;">下面一个问题和前面创建进程类似，不过带来的问题回避进程要严重得多。如果你的主线程，也就是</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">main</span></span><span style="font-size: 14pt; font-family: 宋体;">函数执行的那个线程，在你其他县城推出之前就已经退出，那么带来的</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">bug</span></span><span style="font-size: 14pt; font-family: 宋体;">则不可估量。通过</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">pthread_join</span></span><span style="font-size: 14pt; font-family: 宋体;">函数会让主线程阻塞，直到所有线程都已经退出。</span><span style="font-size: 14pt;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">int pthread_join(pthread_t thread, void **value_ptr);</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">thread</span></span><span style="font-size: 14pt; font-family: 宋体;">：等待退出线程的线程号。</span><span style="font-size: 14pt;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">value_ptr</span></span><span style="font-size: 14pt; font-family: 宋体;">：退出线程的返回值。</span><span style="font-size: 14pt;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt; font-family: 宋体;">下面一个例子结合上面的内容：</span><span style="font-size: 14pt;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">int main ()</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">{</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">pthread_t thread1_id;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">pthread_t thread2_id;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">struct char_print_parms thread1_args;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">struct char_print_parms thread2_args;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">/* Create a new thread to print 30,000 x&#8217;s. */</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">thread1_args.character = &#8217;x&#8217;;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">thread1_args.count = 30000;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">pthread_create (&amp;thread1_id, NULL, &amp;char_print, &amp;thread1_args);</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">/* Create a new thread to print 20,000 o&#8217;s. */</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">thread2_args.character = &#8217;o&#8217;;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">thread2_args.count = 20000;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">pthread_create (&amp;thread2_id, NULL, &amp;char_print, &amp;thread2_args);</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">/* Make sure the first thread has finished. */</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">pthread_join (thread1_id, NULL);</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">/* Make sure the second thread has finished. */</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">pthread_join (thread2_id, NULL);</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">/* Now we can safely return. */</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">return 0;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">}</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;"><span>&nbsp;</span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt; font-family: 宋体;">下面说一下前面提到的线程属性。</span><span style="font-size: 14pt;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt; font-family: 宋体;">在我们前面提到，可以通过</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">pthread_join()</span></span><span style="font-size: 14pt; font-family: 宋体;">函数来使主线程阻塞等待其他线程退</span><span style="font-size: 14pt;"><span style="font-family: Times New Roman;"> </span></span><span style="font-size: 14pt; font-family: 宋体;">出，这样主线程可以清理其他线程的环境。但是还有一些线程，更喜欢自己来清理退出的状态，他们也不愿意主线程调用</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">pthread_join</span></span><span style="font-size: 14pt; font-family: 宋体;">来等待他们。我</span><span style="font-size: 14pt;"><span style="font-family: Times New Roman;"> </span></span><span style="font-size: 14pt; font-family: 宋体;">们将这一类线程的属性称为</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">detached</span></span><span style="font-size: 14pt; font-family: 宋体;">。如果我们在调用</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">pthread_create()</span></span><span style="font-size: 14pt; font-family: 宋体;">函数的时候将属性设置为</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">NULL</span></span><span style="font-size: 14pt; font-family: 宋体;">，则表明我们希望所创建的线</span><span style="font-size: 14pt;"><span style="font-family: Times New Roman;"> </span></span><span style="font-size: 14pt; font-family: 宋体;">程采用默认的属性，也就是</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">jionable</span></span><span style="font-size: 14pt; font-family: 宋体;">。如果需要将属性设置为</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">detached</span></span><span style="font-size: 14pt; font-family: 宋体;">，则参考下面的例子：</span><span style="font-size: 14pt;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">#include &lt;stdio.h&gt;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">#include &lt;pthread.h&gt;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">void * start_run(void * arg)</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">{</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>//do some work</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">}</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">int main()</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">{</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pthread_t thread_id;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pthread_attr_t attr;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pthread_attr_init(&amp;attr);</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pthread_attr_setdetachstate(&amp;attr,PTHREAD_CREATE_DETACHED);</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pthread_create(&amp;thread_id,&amp;attr,start_run,NULL);</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>pthread_attr_destroy(&amp;attr);</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>sleep(5);</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>exit(0);</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">}</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;"><span>&nbsp;</span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt; font-family: 宋体;">在线程设置为</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">joinable</span></span><span style="font-size: 14pt; font-family: 宋体;">后，可以调用</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">pthread_detach()</span></span><span style="font-size: 14pt; font-family: 宋体;">使之成为</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">detached</span></span><span style="font-size: 14pt; font-family: 宋体;">。但是相反的操作则不可以。还有，如果线程已经调用</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">pthread_join()</span></span><span style="font-size: 14pt; font-family: 宋体;">后，则再调用</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">pthread_detach()</span></span><span style="font-size: 14pt; font-family: 宋体;">则不会有任何效果。</span><span style="font-size: 14pt;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt; font-family: 宋体;">线程可以通过自身执行结束来结束，也可以通过调用</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">pthread_exit()</span></span><span style="font-size: 14pt; font-family: 宋体;">来结束线程的执行。另外，线程甲可以被线程乙被动结束。这个通过调用</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">pthread_cancel()</span></span><span style="font-size: 14pt; font-family: 宋体;">来达到目的。</span><span style="font-size: 14pt;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">int pthread_cancel(pthread_t thread);</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span><span style="font-family: Times New Roman;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-size: 14pt; font-family: 宋体;">函数调用成功返回</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">0</span></span><span style="font-size: 14pt; font-family: 宋体;">。</span><span style="font-size: 14pt;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt; font-family: 宋体;">当然，线程也不是被动的被别人结束。它可以通过设置自身的属性来决定如何结束。</span><span style="font-size: 14pt;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt; font-family: 宋体;">线程的被动结束分为两种，一种是异步终结，另外一种是同步终结。异步终结就是当其他线程调用</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;"> pthread_cancel</span></span><span style="font-size: 14pt; font-family: 宋体;">的时候，线程就立刻被结束。而同步终结则不会立刻终结，它会继续运行，直到到达下一个结束点（</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">cancellation point</span></span><span style="font-size: 14pt; font-family: 宋体;">）。当一个线程被按照默认的创建方式创建，那么它的属性是同步终结。</span><span style="font-size: 14pt;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt; font-family: 宋体;">通过调用</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">pthread_setcanceltype()</span></span><span style="font-size: 14pt; font-family: 宋体;">来设置终结状态。</span><span style="font-size: 14pt;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">int pthread_setcanceltype(int type, int *oldtype);</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">state</span></span><span style="font-size: 14pt; font-family: 宋体;">：要设置的状态，可以为</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">PTHREAD_CANCEL_DEFERRED</span></span><span style="font-size: 14pt; font-family: 宋体;">或者为</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">PTHREAD_CANCEL_ASYNCHRONOUS</span></span><span style="font-size: 14pt; font-family: 宋体;">。</span><span style="font-size: 14pt;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt; font-family: 宋体;">那么前面提到的结束点又是如何设置了？最常用的创建终结点就是调用</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">pthread_testcancel()</span></span><span style="font-size: 14pt; font-family: 宋体;">的地方。该函数除了检查同步终结时的状态，其他什么也不做。</span><span style="font-size: 14pt;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt; font-family: 宋体;">上面一个函数是用来设置终结状态的。还可以通过下面的函数来设置终结类型，即该线程可不可以被终结：</span><span style="font-size: 14pt;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">int pthread_setcancelstate(int state, int *oldstate);</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>state</span></span><span style="font-size: 14pt; font-family: 宋体;">：终结状态，可以为</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">PTHREAD_CANCEL_DISABLE</span></span><span style="font-size: 14pt; font-family: 宋体;">或者</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">PTHREAD_CANCEL_ENABLE</span></span><span style="font-size: 14pt; font-family: 宋体;">。具体什么含义大家可以通过单词意思即可明白。</span><span style="font-size: 14pt;" lang="EN-US"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">&nbsp;</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt; font-family: 宋体;">最后说一下线程的本质。其实在</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">Linux</span></span><span style="font-size: 14pt; font-family: 宋体;">中，新建的线程并不是在原先的进程中，而是系统通过</span><span style="font-size: 14pt;"><span style="font-family: Times New Roman;"> </span></span><span style="font-size: 14pt; font-family: 宋体;">一个系统调用</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">clone()</span></span><span style="font-size: 14pt; font-family: 宋体;">。该系统</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">copy</span></span><span style="font-size: 14pt; font-family: 宋体;">了一个和原先进程完全一样的进程，并在这个进程中执行线程函数。不过这个</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">copy</span></span><span style="font-size: 14pt; font-family: 宋体;">过程和</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">fork</span></span><span style="font-size: 14pt; font-family: 宋体;">不一样。</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;"> copy</span></span><span style="font-size: 14pt; font-family: 宋体;">后的进程和原先的进程共享了所有的变量，运行环境。这样，原先进程中的变量变动在</span><span style="font-size: 14pt;" lang="EN-US"><span style="font-family: Times New Roman;">copy</span></span><span style="font-size: 14pt; font-family: 宋体;">后的进程中便能体现出来。</span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><br><span style="font-size: 14pt; font-family: 宋体;"></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt; font-family: 宋体;">from:</span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: 14pt; font-family: 宋体;">http://blog.csdn.net/jxxfqyy/archive/2009/04/16/4084193.aspx<br></span></p>
</span><img src ="http://www.cppblog.com/beautykingdom/aggbug/124566.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-08-24 18:01 <a href="http://www.cppblog.com/beautykingdom/archive/2010/08/24/124566.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux下的多线程编程</title><link>http://www.cppblog.com/beautykingdom/archive/2010/08/23/124465.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Mon, 23 Aug 2010 12:35:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/08/23/124465.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/124465.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/08/23/124465.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/124465.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/124465.html</trackback:ping><description><![CDATA[<table border="0" cellspacing="0" cellpadding="0" width="100%" style="border-collapse: collapse; word-wrap: break-word; font-family: song, Verdana; font-size: 12px; "><tbody><tr style="font: normal normal normal 12px/normal song, Verdana; "><td align="center" style="font: normal normal normal 12px/normal song, Verdana; "><table border="0" cellspacing="0" cellpadding="0" width="100%" style="border-collapse: collapse; word-wrap: break-word; "><tbody><tr style="font: normal normal normal 12px/normal song, Verdana; "><td width="100%" style="font: normal normal normal 12px/normal song, Verdana; "><div id="art" width="100%" style="margin-top: 15px; margin-right: 15px; margin-bottom: 15px; margin-left: 15px; "><span  style="font-family: 'Times New Roman'; font-size: 14px; line-height: 18px; "><span class="line"><span class="line"><span class="line"><span class="line"><font color="#5288c7"><strong>1 引言</strong></font><br style="font: normal normal normal 12px/normal song, Verdana; ">　　线程（thread）技术早在60年代就被提出，但真正应用多线程到操作系统中去，是在80年代中期，solaris是这方面的佼佼者。传统的Unix也支持线程的概念，但是在一个进程（process）中只允许有一个线程，这样多线程就意味着多进程。现在，多线程技术已经被许多操作系统所支持，包括Windows/NT，当然，也包括Linux。<br style="font: normal normal normal 12px/normal song, Verdana; ">　　为什么有了进程的概念后，还要再引入线程呢？使用多线程到底有哪些好处？什么的系统应该选用多线程？我们首先必须回答这些问题。<br style="font: normal normal normal 12px/normal song, Verdana; ">　　使用多线程的理由之一是和进程相比，它是一种非常"节俭"的多任务操作方式。我们知道，在Linux系统下，启动一个新的进程必须分配给它独立的地址空间，建立众多的数据表来维护它的代码段、堆栈段和数据段，这是一种"昂贵"的多任务工作方式。而运行于一个进程中的多个线程，它们彼此之间使用相同的地址空间，共享大部分数据，启动一个线程所花费的空间远远小于启动一个进程所花费的空间，而且，线程间彼此切换所需的时间也远远小于进程间切换所需要的时间。据统计，总的说来桓鼋痰目笤际且桓鱿叱炭?0倍左右，当然，在具体的系统上，这个数据可能会有较大的区别。<br style="font: normal normal normal 12px/normal song, Verdana; ">　　使用多线程的理由之二是线程间方便的通信机制。对不同进程来说，它们具有独立的数据空间，要进行数据的传递只能通过通信的方式进行，这种方式不仅费时，而且很不方便。线程则不然，由于同一进程下的线程之间共享数据空间，所以一个线程的数据可以直接为其它线程所用，这不仅快捷，而且方便。当然，数据的共享也带来其他一些问题，有的变量不能同时被两个线程所修改，有的子程序中声明为static的数据更有可能给多线程程序带来灾难性的打击，这些正是编写多线程程序时最需要注意的地方。<br style="font: normal normal normal 12px/normal song, Verdana; ">　　除了以上所说的优点外，不和进程比较，多线程程序作为一种多任务、并发的工作方式，当然有以下的优点：<br style="font: normal normal normal 12px/normal song, Verdana; ">　　1) 提高应用程序响应。这对图形界面的程序尤其有意义，当一个操作耗时很长时，整个系统都会等待这个操作，此时程序不会响应键盘、鼠标、菜单的操作，而使用多线程技术，将耗时长的操作（time consuming）置于一个新的线程，可以避免这种尴尬的情况。<br style="font: normal normal normal 12px/normal song, Verdana; ">　　2) 使多CPU系统更加有效。操作系统会保证当线程数不大于CPU数目时，不同的线程运行于不同的CPU上。<br style="font: normal normal normal 12px/normal song, Verdana; ">　　3) 改善程序结构。一个既长又复杂的进程可以考虑分为多个线程，成为几个独立或半独立的运行部分，这样的程序会利于理解和修改。<br style="font: normal normal normal 12px/normal song, Verdana; ">　　下面我们先来尝试编写一个简单的多线程程序。<br style="font: normal normal normal 12px/normal song, Verdana; "><br style="font: normal normal normal 12px/normal song, Verdana; "><font color="#5288c7"><strong>2 简单的多线程编程</strong></font><br style="font: normal normal normal 12px/normal song, Verdana; ">　　Linux系统下的多线程遵循POSIX线程接口，称为pthread。编写Linux下的多线程程序，需要使用头文件pthread.h，连接时需要使用库libpthread.a。顺便说一下，Linux下pthread的实现是通过系统调用clone（）来实现的。clone（）是Linux所特有的系统调用，它的使用方式类似fork，关于clone（）的详细情况，有兴趣的读者可以去查看有关文档说明。下面我们展示一个最简单的多线程程序example1.c。</span></span></span></span><p style="font: normal normal normal 12px/normal song, Verdana; "></p><p style="font: normal normal normal 12px/normal song, Verdana; "><span class="line"><span class="line"><span class="line"><span class="line">/* example.c*/<br style="font: normal normal normal 12px/normal song, Verdana; ">#include &lt;stdio.h&gt;<br style="font: normal normal normal 12px/normal song, Verdana; ">#include &lt;pthread.h&gt;<br style="font: normal normal normal 12px/normal song, Verdana; ">void thread(void)<br style="font: normal normal normal 12px/normal song, Verdana; ">{<br style="font: normal normal normal 12px/normal song, Verdana; ">int i;<br style="font: normal normal normal 12px/normal song, Verdana; ">for(i=0;i&lt;3;i++)<br style="font: normal normal normal 12px/normal song, Verdana; ">printf("This is a pthread.\n");<br style="font: normal normal normal 12px/normal song, Verdana; ">}</span></span></span></span></p><p style="font: normal normal normal 12px/normal song, Verdana; "><span class="line"><span class="line"><span class="line"><span class="line">int main(void)<br style="font: normal normal normal 12px/normal song, Verdana; ">{<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_t id;<br style="font: normal normal normal 12px/normal song, Verdana; ">int i,ret;<br style="font: normal normal normal 12px/normal song, Verdana; ">ret=pthread_create(&amp;id,NULL,(void *) thread,NULL);<br style="font: normal normal normal 12px/normal song, Verdana; ">if(ret!=0){<br style="font: normal normal normal 12px/normal song, Verdana; ">printf ("Create pthread error!\n");<br style="font: normal normal normal 12px/normal song, Verdana; ">exit (1);<br style="font: normal normal normal 12px/normal song, Verdana; ">}<br style="font: normal normal normal 12px/normal song, Verdana; ">for(i=0;i&lt;3;i++)<br style="font: normal normal normal 12px/normal song, Verdana; ">printf("This is the main process.\n");<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_join(id,NULL);<br style="font: normal normal normal 12px/normal song, Verdana; ">return (0);<br style="font: normal normal normal 12px/normal song, Verdana; ">}</span></span></span></span></p><p style="font: normal normal normal 12px/normal song, Verdana; "><span class="line"><span class="line"><span class="line"><span class="line">我们编译此程序：<br style="font: normal normal normal 12px/normal song, Verdana; ">gcc example1.c -lpthread -o example1<br style="font: normal normal normal 12px/normal song, Verdana; ">运行example1，我们得到如下结果：<br style="font: normal normal normal 12px/normal song, Verdana; ">This is the main process.<br style="font: normal normal normal 12px/normal song, Verdana; ">This is a pthread.<br style="font: normal normal normal 12px/normal song, Verdana; ">This is the main process.<br style="font: normal normal normal 12px/normal song, Verdana; ">This is the main process.<br style="font: normal normal normal 12px/normal song, Verdana; ">This is a pthread.<br style="font: normal normal normal 12px/normal song, Verdana; ">This is a pthread.<br style="font: normal normal normal 12px/normal song, Verdana; ">再次运行，我们可能得到如下结果：<br style="font: normal normal normal 12px/normal song, Verdana; ">This is a pthread.<br style="font: normal normal normal 12px/normal song, Verdana; ">This is the main process.<br style="font: normal normal normal 12px/normal song, Verdana; ">This is a pthread.<br style="font: normal normal normal 12px/normal song, Verdana; ">This is the main process.<br style="font: normal normal normal 12px/normal song, Verdana; ">This is a pthread.<br style="font: normal normal normal 12px/normal song, Verdana; ">This is the main process.<br style="font: normal normal normal 12px/normal song, Verdana; "><br style="font: normal normal normal 12px/normal song, Verdana; ">　　前后两次结果不一样，这是两个线程争夺CPU资源的结果。上面的示例中，我们使用到了两个函数，　　pthread_create和pthread_join，并声明了一个pthread_t型的变量。<br style="font: normal normal normal 12px/normal song, Verdana; ">　　pthread_t在头文件/usr/include/bits/pthreadtypes.h中定义：<br style="font: normal normal normal 12px/normal song, Verdana; ">　　typedef unsigned long int pthread_t;<br style="font: normal normal normal 12px/normal song, Verdana; ">　　它是一个线程的标识符。函数pthread_create用来创建一个线程，它的原型为：<br style="font: normal normal normal 12px/normal song, Verdana; ">　　extern int pthread_create __P ((pthread_t *__thread, __const pthread_attr_t *__attr,<br style="font: normal normal normal 12px/normal song, Verdana; ">　　void *(*__start_routine) (void *), void *__arg));<br style="font: normal normal normal 12px/normal song, Verdana; ">　　第一个参数为指向线程标识符的指针，第二个参数用来设置线程属性，第三个参数是线程运行函数的起始地址，最后一个参数是运行函数的参数。这里，我们的函数thread不需要参数，所以最后一个参数设为空指针。第二个参数我们也设为空指针，这样将生成默认属性的线程。对线程属性的设定和修改我们将在下一节阐述。当创建线程成功时，函数返回0，若不为0则说明创建线程失败，常见的错误返回代码为EAGAIN和EINVAL。前者表示系统限制创建新的线程，例如线程数目过多了；后者表示第二个参数代表的线程属性值非法。创建线程成功后，新创建的线程则运行参数三和参数四确定的函数，原来的线程则继续运行下一行代码。<br style="font: normal normal normal 12px/normal song, Verdana; ">　　函数pthread_join用来等待一个线程的结束。函数原型为：<br style="font: normal normal normal 12px/normal song, Verdana; ">　　extern int pthread_join __P ((pthread_t __th, void **__thread_return));<br style="font: normal normal normal 12px/normal song, Verdana; ">　　第一个参数为被等待的线程标识符，第二个参数为一个用户定义的指针，它可以用来存储被等待线程的返回值。这个函数是一个线程阻塞的函数，调用它的函数将一直等待到被等待的线程结束为止，当函数返回时，被等待线程的资源被收回。一个线程的结束有两种途径，一种是象我们上面的例子一样，函数结束了，调用它的线程也就结束了；另一种方式是通过函数pthread_exit来实现。它的函数原型为：<br style="font: normal normal normal 12px/normal song, Verdana; ">　　extern void pthread_exit __P ((void *__retval)) __attribute__ ((__noreturn__));<br style="font: normal normal normal 12px/normal song, Verdana; ">　　唯一的参数是函数的返回代码，只要pthread_join中的第二个参数thread_return不是NULL，这个值将被传递给thread_return。最后要说明的是，一个线程不能被多个线程等待，否则第一个接收到信号的线程成功返回，其余调用pthread_join的线程则返回错误代码ESRCH。<br style="font: normal normal normal 12px/normal song, Verdana; ">　　在这一节里，我们编写了一个最简单的线程，并掌握了最常用的三个函数pthread_create，pthread_join和pthread_exit。下面，我们来了解线程的一些常用属性以及如何设置这些属性。</span></span></span></span></p><p style="font: normal normal normal 12px/normal song, Verdana; "><span class="line"><span class="line"><span class="line"><span class="line"><font color="#5288c7"><strong>3 修改线程的属性</strong></font><br style="font: normal normal normal 12px/normal song, Verdana; ">　　在上一节的例子里，我们用pthread_create函数创建了一个线程，在这个线程中，我们使用了默认参数，即将该函数的第二个参数设为NULL。的确，对大多数程序来说，使用默认属性就够了，但我们还是有必要来了解一下线程的有关属性。<br style="font: normal normal normal 12px/normal song, Verdana; ">　　属性结构为pthread_attr_t，它同样在头文件/usr/include/pthread.h中定义，喜欢追根问底的人可以自己去查看。属性值不能直接设置，须使用相关函数进行操作，初始化的函数为pthread_attr_init，这个函数必须在pthread_create函数之前调用。属性对象主要包括是否绑定、是否分离、堆栈地址、堆栈大小、优先级。默认的属性为非绑定、非分离、缺省1M的堆栈、与父进程同样级别的优先级。<br style="font: normal normal normal 12px/normal song, Verdana; ">　　关于线程的绑定，牵涉到另外一个概念：轻进程（LWP：Light Weight Process）。轻进程可以理解为内核线程，它位于用户层和系统层之间。系统对线程资源的分配、对线程的控制是通过轻进程来实现的，一个轻进程可以控制一个或多个线程。默认状况下，启动多少轻进程、哪些轻进程来控制哪些线程是由系统来控制的，这种状况即称为非绑定的。绑定状况下，则顾名思义，即某个线程固定的"绑"在一个轻进程之上。被绑定的线程具有较高的响应速度，这是因为CPU时间片的调度是面向轻进程的，绑定的线程可以保证在需要的时候它总有一个轻进程可用。通过设置被绑定的轻进程的优先级和调度级可以使得绑定的线程满足诸如实时反应之类的要求。<br style="font: normal normal normal 12px/normal song, Verdana; ">　　设置线程绑定状态的函数为pthread_attr_setscope，它有两个参数，第一个是指向属性结构的指针，第二个是绑定类型，它有两个取值：PTHREAD_SCOPE_SYSTEM（绑定的）和PTHREAD_SCOPE_PROCESS（非绑定的）。下面的代码即创建了一个绑定的线程。<br style="font: normal normal normal 12px/normal song, Verdana; ">#include &lt;pthread.h&gt;<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_attr_t attr;<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_t tid;</span></span></span></span></p><p style="font: normal normal normal 12px/normal song, Verdana; "><span class="line"><span class="line"><span class="line"><span class="line">/*初始化属性值，均设为默认值*/<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_attr_init(&amp;attr);<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_attr_setscope(&amp;attr, PTHREAD_SCOPE_SYSTEM);</span></span></span></span></p><p style="font: normal normal normal 12px/normal song, Verdana; "><span class="line"><span class="line"><span class="line"><span class="line">pthread_create(&amp;tid, &amp;attr, (void *) my_function, NULL);</span></span></span></span></p><p style="font: normal normal normal 12px/normal song, Verdana; "><span class="line"><span class="line"><span class="line"><span class="line">　　线程的分离状态决定一个线程以什么样的方式来终止自己。在上面的例子中，我们采用了线程的默认属性，即为非分离状态，这种情况下，原有的线程等待创建的线程结束。只有当pthread_join（）函数返回时，创建的线程才算终止，才能释放自己占用的系统资源。而分离线程不是这样子的，它没有被其他的线程所等待，自己运行结束了，线程也就终止了，马上释放系统资源。程序员应该根据自己的需要，选择适当的分离状态。设置线程分离状态的函数为pthread_attr_setdetachstate（pthread_attr_t *attr, int detachstate）。第二个参数可选为PTHREAD_CREATE_DETACHED（分离线程）和 PTHREAD _CREATE_JOINABLE（非分离线程）。这里要注意的一点是，如果设置一个线程为分离线程，而这个线程运行又非常快，它很可能在pthread_create函数返回之前就终止了，它终止以后就可能将线程号和系统资源移交给其他的线程使用，这样调用pthread_create的线程就得到了错误的线程号。要避免这种情况可以采取一定的同步措施，最简单的方法之一是可以在被创建的线程里调用pthread_cond_timewait函数，让这个线程等待一会儿，留出足够的时间让函数pthread_create返回。设置一段等待时间，是在多线程编程里常用的方法。但是注意不要使用诸如wait（）之类的函数，它们是使整个进程睡眠，并不能解决线程同步的问题。<br style="font: normal normal normal 12px/normal song, Verdana; ">　　另外一个可能常用的属性是线程的优先级，它存放在结构sched_param中。用函数pthread_attr_getschedparam和函数pthread_attr_setschedparam进行存放，一般说来，我们总是先取优先级，对取得的值修改后再存放回去。下面即是一段简单的例子。<br style="font: normal normal normal 12px/normal song, Verdana; ">#include &lt;pthread.h&gt;<br style="font: normal normal normal 12px/normal song, Verdana; ">#include &lt;sched.h&gt;<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_attr_t attr;<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_t tid;<br style="font: normal normal normal 12px/normal song, Verdana; ">sched_param param;<br style="font: normal normal normal 12px/normal song, Verdana; ">int newprio=20;</span></span></span></span></p><p style="font: normal normal normal 12px/normal song, Verdana; "><span class="line"><span class="line"><span class="line"><span class="line">pthread_attr_init(&amp;attr);<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_attr_getschedparam(&amp;attr, &amp;param);<br style="font: normal normal normal 12px/normal song, Verdana; ">param.sched_priority=newprio;<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_attr_setschedparam(&amp;attr, &amp;param);<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_create(&amp;tid, &amp;attr, (void *)myfunction, myarg);<br style="font: normal normal normal 12px/normal song, Verdana; ">　　<br style="font: normal normal normal 12px/normal song, Verdana; "><font color="#5288c7"><strong>4 线程的数据处理</strong></font><br style="font: normal normal normal 12px/normal song, Verdana; ">　　和进程相比，线程的最大优点之一是数据的共享性，各个进程共享父进程处沿袭的数据段，可以方便的获得、修改数据。但这也给多线程编程带来了许多问题。我们必须当心有多个不同的进程访问相同的变量。许多函数是不可重入的，即同时不能运行一个函数的多个拷贝（除非使用不同的数据段）。在函数中声明的静态变量常常带来问题，函数的返回值也会有问题。因为如果返回的是函数内部静态声明的空间的地址，则在一个线程调用该函数得到地址后使用该地址指向的数据时，别的线程可能调用此函数并修改了这一段数据。在进程中共享的变量必须用关键字volatile来定义，这是为了防止编译器在优化时（如gcc中使用-OX参数）改变它们的使用方式。为了保护变量，我们必须使用信号量、互斥等方法来保证我们对变量的正确使用。下面，我们就逐步介绍处理线程数据时的有关知识。</span></span></span></span></p><p style="font: normal normal normal 12px/normal song, Verdana; "><span class="line"><span class="line"><span class="line"><span class="line"><strong>4.1 线程数据</strong><br style="font: normal normal normal 12px/normal song, Verdana; ">　　在单线程的程序里，有两种基本的数据：全局变量和局部变量。但在多线程程序里，还有第三种数据类型：线程数据（TSD: Thread-Specific Data）。它和全局变量很象，在线程内部，各个函数可以象使用全局变量一样调用它，但它对线程外部的其它线程是不可见的。这种数据的必要性是显而易见的。例如我们常见的变量errno，它返回标准的出错信息。它显然不能是一个局部变量，几乎每个函数都应该可以调用它；但它又不能是一个全局变量，否则在A线程里输出的很可能是B线程的出错信息。要实现诸如此类的变量，我们就必须使用线程数据。我们为每个线程数据创建一个键，它和这个键相关联，在各个线程里，都使用这个键来指代线程数据，但在不同的线程里，这个键代表的数据是不同的，在同一个线程里，它代表同样的数据内容。<br style="font: normal normal normal 12px/normal song, Verdana; ">　　和线程数据相关的函数主要有4个：创建一个键；为一个键指定线程数据；从一个键读取线程数据；删除键。<br style="font: normal normal normal 12px/normal song, Verdana; ">　　创建键的函数原型为：<br style="font: normal normal normal 12px/normal song, Verdana; ">　　extern int pthread_key_create __P ((pthread_key_t *__key,<br style="font: normal normal normal 12px/normal song, Verdana; ">　　void (*__destr_function) (void *)));<br style="font: normal normal normal 12px/normal song, Verdana; ">　　第一个参数为指向一个键值的指针，第二个参数指明了一个destructor函数，如果这个参数不为空，那么当每个线程结束时，系统将调用这个函数来释放绑定在这个键上的内存块。这个函数常和函数pthread_once ((pthread_once_t*once_control, void (*initroutine) (void)))一起使用，为了让这个键只被创建一次。函数pthread_once声明一个初始化函数，第一次调用pthread_once时它执行这个函数，以后的调用将被它忽略。<br style="font: normal normal normal 12px/normal song, Verdana; "><br style="font: normal normal normal 12px/normal song, Verdana; ">　　在下面的例子中，我们创建一个键，并将它和某个数据相关联。我们要定义一个函数createWindow，这个函数定义一个图形窗口（数据类型为Fl_Window *，这是图形界面开发工具FLTK中的数据类型）。由于各个线程都会调用这个函数，所以我们使用线程数据。<br style="font: normal normal normal 12px/normal song, Verdana; ">/* 声明一个键*/<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_key_t myWinKey;<br style="font: normal normal normal 12px/normal song, Verdana; ">/* 函数 createWindow */<br style="font: normal normal normal 12px/normal song, Verdana; ">void createWindow ( void ) {<br style="font: normal normal normal 12px/normal song, Verdana; ">Fl_Window * win;<br style="font: normal normal normal 12px/normal song, Verdana; ">static pthread_once_t once= PTHREAD_ONCE_INIT;<br style="font: normal normal normal 12px/normal song, Verdana; ">/* 调用函数createMyKey，创建键*/<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_once ( &amp; once, createMyKey) ;<br style="font: normal normal normal 12px/normal song, Verdana; ">/*win指向一个新建立的窗口*/<br style="font: normal normal normal 12px/normal song, Verdana; ">win=new Fl_Window( 0, 0, 100, 100, "MyWindow");<br style="font: normal normal normal 12px/normal song, Verdana; ">/* 对此窗口作一些可能的设置工作，如大小、位置、名称等*/<br style="font: normal normal normal 12px/normal song, Verdana; ">setWindow(win);<br style="font: normal normal normal 12px/normal song, Verdana; ">/* 将窗口指针值绑定在键myWinKey上*/<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_setpecific ( myWinKey, win);<br style="font: normal normal normal 12px/normal song, Verdana; ">}</span></span></span></span></p><p style="font: normal normal normal 12px/normal song, Verdana; "><span class="line"><span class="line"><span class="line"><span class="line">/* 函数 createMyKey，创建一个键，并指定了destructor */<br style="font: normal normal normal 12px/normal song, Verdana; ">void createMyKey ( void ) {<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_keycreate(&amp;myWinKey, freeWinKey);<br style="font: normal normal normal 12px/normal song, Verdana; ">}</span></span></span></span></p><p style="font: normal normal normal 12px/normal song, Verdana; "><span class="line"><span class="line"><span class="line"><span class="line">/* 函数 freeWinKey，释放空间*/<br style="font: normal normal normal 12px/normal song, Verdana; ">void freeWinKey ( Fl_Window * win){<br style="font: normal normal normal 12px/normal song, Verdana; ">delete win;<br style="font: normal normal normal 12px/normal song, Verdana; ">}</span></span></span></span></p><p style="font: normal normal normal 12px/normal song, Verdana; "><span class="line"><span class="line"><span class="line"><span class="line">　　这样，在不同的线程中调用函数createMyWin，都可以得到在线程内部均可见的窗口变量，这个变量通过函数pthread_getspecific得到。在上面的例子中，我们已经使用了函数pthread_setspecific来将线程数据和一个键绑定在一起。这两个函数的原型如下：<br style="font: normal normal normal 12px/normal song, Verdana; ">　　extern int pthread_setspecific __P ((pthread_key_t __key,__const void *__pointer));<br style="font: normal normal normal 12px/normal song, Verdana; ">　　extern void *pthread_getspecific __P ((pthread_key_t __key));<br style="font: normal normal normal 12px/normal song, Verdana; ">　　这两个函数的参数意义和使用方法是显而易见的。要注意的是，用pthread_setspecific为一个键指定新的线程数据时，必须自己释放原有的线程数据以回收空间。这个过程函数pthread_key_delete用来删除一个键，这个键占用的内存将被释放，但同样要注意的是，它只释放键占用的内存，并不释放该键关联的线程数据所占用的内存资源，而且它也不会触发函数pthread_key_create中定义的destructor函数。线程数据的释放必须在释放键之前完成。</span></span></span></span></p><p style="font: normal normal normal 12px/normal song, Verdana; "><span class="line"><span class="line"><span class="line"><span class="line"><strong>4.2 互斥锁</strong><br style="font: normal normal normal 12px/normal song, Verdana; ">　　互斥锁用来保证一段时间内只有一个线程在执行一段代码。必要性显而易见：假设各个线程向同一个文件顺序写入数据，最后得到的结果一定是灾难性的。<br style="font: normal normal normal 12px/normal song, Verdana; ">　　我们先看下面一段代码。这是一个读/写程序，它们公用一个缓冲区，并且我们假定一个缓冲区只能保存一条信息。即缓冲区只有两个状态：有信息或没有信息。</span></span></span></span></p><p style="font: normal normal normal 12px/normal song, Verdana; "><span class="line"><span class="line"><span class="line"><span class="line">void reader_function ( void );<br style="font: normal normal normal 12px/normal song, Verdana; ">void writer_function ( void );</span></span></span></span></p><p style="font: normal normal normal 12px/normal song, Verdana; "><span class="line"><span class="line"><span class="line"><span class="line">char buffer;<br style="font: normal normal normal 12px/normal song, Verdana; ">int buffer_has_item=0;<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_mutex_t mutex;<br style="font: normal normal normal 12px/normal song, Verdana; ">struct timespec delay;<br style="font: normal normal normal 12px/normal song, Verdana; ">void main ( void ){<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_t reader;<br style="font: normal normal normal 12px/normal song, Verdana; ">/* 定义延迟时间*/<br style="font: normal normal normal 12px/normal song, Verdana; ">delay.tv_sec = 2;<br style="font: normal normal normal 12px/normal song, Verdana; ">delay.tv_nec = 0;<br style="font: normal normal normal 12px/normal song, Verdana; ">/* 用默认属性初始化一个互斥锁对象*/<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_mutex_init (&amp;mutex,NULL);<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_create(&amp;reader, pthread_attr_default, (void *)&amp;reader_function), NULL);<br style="font: normal normal normal 12px/normal song, Verdana; ">writer_function( );<br style="font: normal normal normal 12px/normal song, Verdana; ">}</span></span></span></span></p><p style="font: normal normal normal 12px/normal song, Verdana; "><span class="line"><span class="line"><span class="line"><span class="line">void writer_function (void){<br style="font: normal normal normal 12px/normal song, Verdana; ">while(1){<br style="font: normal normal normal 12px/normal song, Verdana; ">/* 锁定互斥锁*/<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_mutex_lock (&amp;mutex);<br style="font: normal normal normal 12px/normal song, Verdana; ">if (buffer_has_item==0){<br style="font: normal normal normal 12px/normal song, Verdana; ">buffer=make_new_item( );<br style="font: normal normal normal 12px/normal song, Verdana; ">buffer_has_item=1;<br style="font: normal normal normal 12px/normal song, Verdana; ">}<br style="font: normal normal normal 12px/normal song, Verdana; ">/* 打开互斥锁*/<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_mutex_unlock(&amp;mutex);<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_delay_np(&amp;delay);<br style="font: normal normal normal 12px/normal song, Verdana; ">}<br style="font: normal normal normal 12px/normal song, Verdana; ">}</span></span></span></span></p><p style="font: normal normal normal 12px/normal song, Verdana; "><span class="line"><span class="line"><span class="line"><span class="line">void reader_function(void){<br style="font: normal normal normal 12px/normal song, Verdana; ">while(1){<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_mutex_lock(&amp;mutex);<br style="font: normal normal normal 12px/normal song, Verdana; ">if(buffer_has_item==1){<br style="font: normal normal normal 12px/normal song, Verdana; ">consume_item(buffer);<br style="font: normal normal normal 12px/normal song, Verdana; ">buffer_has_item=0;<br style="font: normal normal normal 12px/normal song, Verdana; ">}<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_mutex_unlock(&amp;mutex);<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_delay_np(&amp;delay);<br style="font: normal normal normal 12px/normal song, Verdana; ">}<br style="font: normal normal normal 12px/normal song, Verdana; ">}<br style="font: normal normal normal 12px/normal song, Verdana; ">　　这里声明了互斥锁变量mutex，结构pthread_mutex_t为不公开的数据类型，其中包含一个系统分配的属性对象。函数pthread_mutex_init用来生成一个互斥锁。NULL参数表明使用默认属性。如果需要声明特定属性的互斥锁，须调用函数pthread_mutexattr_init。函数pthread_mutexattr_setpshared和函数pthread_mutexattr_settype用来设置互斥锁属性。前一个函数设置属性pshared，它有两个取值，PTHREAD_PROCESS_PRIVATE和PTHREAD_PROCESS_SHARED。前者用来不同进程中的线程同步，后者用于同步本进程的不同线程。在上面的例子中，我们使用的是默认属性PTHREAD_PROCESS_ PRIVATE。后者用来设置互斥锁类型，可选的类型有PTHREAD_MUTEX_NORMAL、PTHREAD_MUTEX_ERRORCHECK、PTHREAD_MUTEX_RECURSIVE和PTHREAD _MUTEX_DEFAULT。它们分别定义了不同的上所、解锁机制，一般情况下，选用最后一个默认属性。<br style="font: normal normal normal 12px/normal song, Verdana; ">　　pthread_mutex_lock声明开始用互斥锁上锁，此后的代码直至调用pthread_mutex_unlock为止，均被上锁，即同一时间只能被一个线程调用执行。当一个线程执行到pthread_mutex_lock处时，如果该锁此时被另一个线程使用，那此线程被阻塞，即程序将等待到另一个线程释放此互斥锁。在上面的例子中，我们使用了pthread_delay_np函数，让线程睡眠一段时间，就是为了防止一个线程始终占据此函数。<br style="font: normal normal normal 12px/normal song, Verdana; ">　　上面的例子非常简单，就不再介绍了，需要提出的是在使用互斥锁的过程中很有可能会出现死锁：两个线程试图同时占用两个资源，并按不同的次序锁定相应的互斥锁，例如两个线程都需要锁定互斥锁1和互斥锁2，a线程先锁定互斥锁1，b线程先锁定互斥锁2，这时就出现了死锁。此时我们可以使用函数pthread_mutex_trylock，它是函数pthread_mutex_lock的非阻塞版本，当它发现死锁不可避免时，它会返回相应的信息，程序员可以针对死锁做出相应的处理。另外不同的互斥锁类型对死锁的处理不一样，但最主要的还是要程序员自己在程序设计注意这一点。</span></span></span></span></p><p style="font: normal normal normal 12px/normal song, Verdana; "><span class="line"><span class="line"><span class="line"><span class="line"><strong>4.3 条件变量<br style="font: normal normal normal 12px/normal song, Verdana; "></strong>　　前一节中我们讲述了如何使用互斥锁来实现线程间数据的共享和通信，互斥锁一个明显的缺点是它只有两种状态：锁定和非锁定。而条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足，它常和互斥锁一起使用。使用时，条件变量被用来阻塞一个线程，当条件不满足时，线程往往解开相应的互斥锁并等待条件发生变化。一旦其它的某个线程改变了条件变量，它将通知相应的条件变量唤醒一个或多个正被此条件变量阻塞的线程。这些线程将重新锁定互斥锁并重新测试条件是否满足。一般说来，条件变量被用来进行线承间的同步。<br style="font: normal normal normal 12px/normal song, Verdana; ">　　条件变量的结构为pthread_cond_t，函数pthread_cond_init（）被用来初始化一个条件变量。它的原型为：<br style="font: normal normal normal 12px/normal song, Verdana; ">　　extern int pthread_cond_init __P ((pthread_cond_t *__cond,__const pthread_condattr_t *__cond_attr));<br style="font: normal normal normal 12px/normal song, Verdana; ">　　其中cond是一个指向结构pthread_cond_t的指针，cond_attr是一个指向结构pthread_condattr_t的指针。结构pthread_condattr_t是条件变量的属性结构，和互斥锁一样我们可以用它来设置条件变量是进程内可用还是进程间可用，默认值是PTHREAD_ PROCESS_PRIVATE，即此条件变量被同一进程内的各个线程使用。注意初始化条件变量只有未被使用时才能重新初始化或被释放。释放一个条件变量的函数为pthread_cond_ destroy（pthread_cond_t cond）。　<br style="font: normal normal normal 12px/normal song, Verdana; ">　　函数pthread_cond_wait（）使线程阻塞在一个条件变量上。它的函数原型为：<br style="font: normal normal normal 12px/normal song, Verdana; ">　　extern int pthread_cond_wait __P ((pthread_cond_t *__cond,<br style="font: normal normal normal 12px/normal song, Verdana; ">　　pthread_mutex_t *__mutex));<br style="font: normal normal normal 12px/normal song, Verdana; ">　　线程解开mutex指向的锁并被条件变量cond阻塞。线程可以被函数pthread_cond_signal和函数pthread_cond_broadcast唤醒，但是要注意的是，条件变量只是起阻塞和唤醒线程的作用，具体的判断条件还需用户给出，例如一个变量是否为0等等，这一点我们从后面的例子中可以看到。线程被唤醒后，它将重新检查判断条件是否满足，如果还不满足，一般说来线程应该仍阻塞在这里，被等待被下一次唤醒。这个过程一般用while语句实现。<br style="font: normal normal normal 12px/normal song, Verdana; ">　　另一个用来阻塞线程的函数是pthread_cond_timedwait（），它的原型为：<br style="font: normal normal normal 12px/normal song, Verdana; ">　　extern int pthread_cond_timedwait __P ((pthread_cond_t *__cond,<br style="font: normal normal normal 12px/normal song, Verdana; ">　　pthread_mutex_t *__mutex, __const struct timespec *__abstime));<br style="font: normal normal normal 12px/normal song, Verdana; ">　　它比函数pthread_cond_wait（）多了一个时间参数，经历abstime段时间后，即使条件变量不满足，阻塞也被解除。<br style="font: normal normal normal 12px/normal song, Verdana; ">　　函数pthread_cond_signal（）的原型为：<br style="font: normal normal normal 12px/normal song, Verdana; ">　　extern int pthread_cond_signal __P ((pthread_cond_t *__cond));<br style="font: normal normal normal 12px/normal song, Verdana; ">　　它用来释放被阻塞在条件变量cond上的一个线程。多个线程阻塞在此条件变量上时，哪一个线程被唤醒是由线程的调度策略所决定的。要注意的是，必须用保护条件变量的互斥锁来保护这个函数，否则条件满足信号又可能在测试条件和调用pthread_cond_wait函数之间被发出，从而造成无限制的等待。下面是使用函数pthread_cond_wait（）和函数pthread_cond_signal（）的一个简单的例子。</span></span></span></span></p><p style="font: normal normal normal 12px/normal song, Verdana; "><span class="line"><span class="line"><span class="line"><span class="line">pthread_mutex_t count_lock;<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_cond_t count_nonzero;<br style="font: normal normal normal 12px/normal song, Verdana; ">unsigned count;<br style="font: normal normal normal 12px/normal song, Verdana; ">decrement_count　() {<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_mutex_lock (&amp;count_lock);<br style="font: normal normal normal 12px/normal song, Verdana; ">while(count==0)&nbsp;<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_cond_wait( &amp;count_nonzero, &amp;count_lock);<br style="font: normal normal normal 12px/normal song, Verdana; ">count=count -1;<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_mutex_unlock (&amp;count_lock);<br style="font: normal normal normal 12px/normal song, Verdana; ">}<br style="font: normal normal normal 12px/normal song, Verdana; "><br style="font: normal normal normal 12px/normal song, Verdana; ">increment_count(){<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_mutex_lock(&amp;count_lock);<br style="font: normal normal normal 12px/normal song, Verdana; ">if(count==0)<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_cond_signal(&amp;count_nonzero);<br style="font: normal normal normal 12px/normal song, Verdana; ">count=count+1;<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_mutex_unlock(&amp;count_lock);<br style="font: normal normal normal 12px/normal song, Verdana; ">}<br style="font: normal normal normal 12px/normal song, Verdana; ">　　count值为0</span></span></span></span><span class="line"><span class="line"><span class="line"><span class="line">时，decrement函数在pthread_cond_wait处被阻塞，并打开互斥锁count_lock。此时，当调用到函数increment_count时，pthread_cond_signal（）函数改变条件变量，告知decrement_count（）停止阻塞。读者可以试着让两个线程分别运行这两个函数，看看会出现什么样的结果。<br style="font: normal normal normal 12px/normal song, Verdana; ">　　函数pthread_cond_broadcast（pthread_cond_t *cond）用来唤醒所有被阻塞在条件变量cond上的线程。这些线程被唤醒后将再次竞争相应的互斥锁，所以必须小心使用这个函数。</span></span></span></span></p><p style="font: normal normal normal 12px/normal song, Verdana; "><span class="line"><span class="line"><span class="line"><span class="line"><strong>4.4 信号量<br style="font: normal normal normal 12px/normal song, Verdana; "></strong>　　信号量本质上是一个非负的整数计数器，它被用来控制对公共资源的访问。当公共资源增加时，调用函数sem_post（）增加信号量。只有当信号量值大于０时，才能使用公共资源，使用后，函数sem_wait（）减少信号量。函数sem_trywait（）和函数pthread_ mutex_trylock（）起同样的作用，它是函数sem_wait（）的非阻塞版本。下面我们逐个介绍和信号量有关的一些函数，它们都在头文件/usr/include/semaphore.h中定义。<br style="font: normal normal normal 12px/normal song, Verdana; ">　　信号量的数据类型为结构sem_t，它本质上是一个长整型的数。函数sem_init（）用来初始化一个信号量。它的原型为：<br style="font: normal normal normal 12px/normal song, Verdana; ">　　extern int sem_init __P ((sem_t *__sem, int __pshared, unsigned int __value));<br style="font: normal normal normal 12px/normal song, Verdana; ">　　sem为指向信号量结构的一个指针；pshared不为０时此信号量在进程间共享，否则只能为当前进程的所有线程共享；value给出了信号量的初始值。<br style="font: normal normal normal 12px/normal song, Verdana; ">　　函数sem_post( sem_t *sem )用来增加信号量的值。当有线程阻塞在这个信号量上时，调用这个函数会使其中的一个线程不在阻塞，选择机制同样是由线程的调度策略决定的。<br style="font: normal normal normal 12px/normal song, Verdana; ">　　函数sem_wait( sem_t *sem )被用来阻塞当前线程直到信号量sem的值大于0，解除阻塞后将sem的值减一，表明公共资源经使用后减少。函数sem_trywait ( sem_t *sem )是函数sem_wait（）的非阻塞版本，它直接将信号量sem的值减一。<br style="font: normal normal normal 12px/normal song, Verdana; ">　　函数sem_destroy(sem_t *sem)用来释放信号量sem。<br style="font: normal normal normal 12px/normal song, Verdana; ">　　下面我们来看一个使用信号量的例子。在这个例子中，一共有4个线程，其中两个线程负责从文件读取数据到公共的缓冲区，另两个线程从缓冲区读取数据作不同的处理（加和乘运算）。<br style="font: normal normal normal 12px/normal song, Verdana; ">/* File sem.c */<br style="font: normal normal normal 12px/normal song, Verdana; ">#include &lt;stdio.h&gt;<br style="font: normal normal normal 12px/normal song, Verdana; ">#include &lt;pthread.h&gt;<br style="font: normal normal normal 12px/normal song, Verdana; ">#include &lt;semaphore.h&gt;<br style="font: normal normal normal 12px/normal song, Verdana; ">#define MAXSTACK 100<br style="font: normal normal normal 12px/normal song, Verdana; ">int stack[MAXSTACK][2];<br style="font: normal normal normal 12px/normal song, Verdana; ">int size=0;<br style="font: normal normal normal 12px/normal song, Verdana; ">sem_t sem;<br style="font: normal normal normal 12px/normal song, Verdana; ">/* 从文件1.dat读取数据，每读一次，信号量加一*/<br style="font: normal normal normal 12px/normal song, Verdana; ">void ReadData1(void){<br style="font: normal normal normal 12px/normal song, Verdana; ">FILE *fp=fopen("1.dat","r");<br style="font: normal normal normal 12px/normal song, Verdana; ">while(!feof(fp)){<br style="font: normal normal normal 12px/normal song, Verdana; ">fscanf(fp,"%d %d",&amp;stack[size][0],&amp;stack[size][1]);<br style="font: normal normal normal 12px/normal song, Verdana; ">sem_post(&amp;sem);<br style="font: normal normal normal 12px/normal song, Verdana; ">++size;<br style="font: normal normal normal 12px/normal song, Verdana; ">}<br style="font: normal normal normal 12px/normal song, Verdana; ">fclose(fp);<br style="font: normal normal normal 12px/normal song, Verdana; ">}<br style="font: normal normal normal 12px/normal song, Verdana; ">/*从文件2.dat读取数据*/<br style="font: normal normal normal 12px/normal song, Verdana; ">void ReadData2(void){<br style="font: normal normal normal 12px/normal song, Verdana; ">FILE *fp=fopen("2.dat","r");<br style="font: normal normal normal 12px/normal song, Verdana; ">while(!feof(fp)){<br style="font: normal normal normal 12px/normal song, Verdana; ">fscanf(fp,"%d %d",&amp;stack[size][0],&amp;stack[size][1]);<br style="font: normal normal normal 12px/normal song, Verdana; ">sem_post(&amp;sem);<br style="font: normal normal normal 12px/normal song, Verdana; ">++size;<br style="font: normal normal normal 12px/normal song, Verdana; ">}<br style="font: normal normal normal 12px/normal song, Verdana; ">fclose(fp);<br style="font: normal normal normal 12px/normal song, Verdana; ">}<br style="font: normal normal normal 12px/normal song, Verdana; ">/*阻塞等待缓冲区有数据，读取数据后，释放空间，继续等待*/<br style="font: normal normal normal 12px/normal song, Verdana; ">void HandleData1(void){<br style="font: normal normal normal 12px/normal song, Verdana; ">while(1){<br style="font: normal normal normal 12px/normal song, Verdana; ">sem_wait(&amp;sem);<br style="font: normal normal normal 12px/normal song, Verdana; ">printf("Plus:%d+%d=%d\n",stack[size][0],stack[size][1],<br style="font: normal normal normal 12px/normal song, Verdana; ">stack[size][0]+stack[size][1]);<br style="font: normal normal normal 12px/normal song, Verdana; ">--size;<br style="font: normal normal normal 12px/normal song, Verdana; ">}<br style="font: normal normal normal 12px/normal song, Verdana; ">}</span></span></span></span></p><p style="font: normal normal normal 12px/normal song, Verdana; "><span class="line"><span class="line"><span class="line"><span class="line">void HandleData2(void){<br style="font: normal normal normal 12px/normal song, Verdana; ">while(1){<br style="font: normal normal normal 12px/normal song, Verdana; ">sem_wait(&amp;sem);<br style="font: normal normal normal 12px/normal song, Verdana; ">printf("Multiply:%d*%d=%d\n",stack[size][0],stack[size][1],<br style="font: normal normal normal 12px/normal song, Verdana; ">stack[size][0]*stack[size][1]);<br style="font: normal normal normal 12px/normal song, Verdana; ">--size;<br style="font: normal normal normal 12px/normal song, Verdana; ">}<br style="font: normal normal normal 12px/normal song, Verdana; ">}<br style="font: normal normal normal 12px/normal song, Verdana; ">int main(void){<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_t t1,t2,t3,t4;<br style="font: normal normal normal 12px/normal song, Verdana; ">sem_init(&amp;sem,0,0);<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_create(&amp;t1,NULL,(void *)HandleData1,NULL);<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_create(&amp;t2,NULL,(void *)HandleData2,NULL);<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_create(&amp;t3,NULL,(void *)ReadData1,NULL);<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_create(&amp;t4,NULL,(void *)ReadData2,NULL);<br style="font: normal normal normal 12px/normal song, Verdana; ">/* 防止程序过早退出，让它在此无限期等待*/<br style="font: normal normal normal 12px/normal song, Verdana; ">pthread_join(t1,NULL);<br style="font: normal normal normal 12px/normal song, Verdana; ">}</span></span></span></span></p><p style="font: normal normal normal 12px/normal song, Verdana; "><span class="line"><span class="line"><span class="line"><span class="line">　　在Linux下，我们用命令gcc -lpthread sem.c -o sem生成可执行文件sem。 我们事先编辑好数据文件1.dat和2.dat，假设它们的内容分别为1 2 3 4 5 6 7 8 9 10和 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 ，我们运行sem，得到如下的结果：<br style="font: normal normal normal 12px/normal song, Verdana; ">Multiply:-1*-2=2<br style="font: normal normal normal 12px/normal song, Verdana; ">Plus:-1+-2=-3<br style="font: normal normal normal 12px/normal song, Verdana; ">Multiply:9*10=90<br style="font: normal normal normal 12px/normal song, Verdana; ">Plus:-9+-10=-19<br style="font: normal normal normal 12px/normal song, Verdana; ">Multiply:-7*-8=56<br style="font: normal normal normal 12px/normal song, Verdana; ">Plus:-5+-6=-11<br style="font: normal normal normal 12px/normal song, Verdana; ">Multiply:-3*-4=12<br style="font: normal normal normal 12px/normal song, Verdana; ">Plus:9+10=19<br style="font: normal normal normal 12px/normal song, Verdana; ">Plus:7+8=15<br style="font: normal normal normal 12px/normal song, Verdana; ">Plus:5+6=11<br style="font: normal normal normal 12px/normal song, Verdana; "><br style="font: normal normal normal 12px/normal song, Verdana; ">　　从中我们可以看出各个线程间的竞争关系。而数值并未按我们原先的顺序显示出来这是由于size这个数值被各个线程任意修改的缘故。这也往往是多线程编程要注意的问题。</span></span></span></span></p><p style="font: normal normal normal 12px/normal song, Verdana; "><span class="line"><span class="line"><span class="line"><span class="line"><strong><font color="#5288c7">5 小结</font></strong><br style="font: normal normal normal 12px/normal song, Verdana; ">　　多线程编程是一个很有意思也很有用的技术，使用多线程技术的网络蚂蚁是目前最常用的下载工具之一，使用多线程技术的grep比单线程的grep要快上几倍，类似的例子还有很多。希望大家能用多线程技术写出高效实用的好程序来。</span></span></span></span></p></span></div></td></tr></tbody></table><p style="font: normal normal normal 12px/normal song, Verdana; line-height: 18px; margin-top: 5px; margin-right: 5px; margin-bottom: 5px; margin-left: 5px; "></p></td></tr><tr style="font: normal normal normal 12px/normal song, Verdana; "><td height="25" style="font: normal normal normal 12px/normal song, Verdana; ">&nbsp;<font color="#000099"><strong>原文地址</strong></font>&nbsp;<a href="http://linux.chinaunix.net/doc/program/2001-08-11/642.shtml" target="_blank" style="text-decoration: underline; color: rgb(0, 68, 182); ">http://linux.chinaunix.net/doc/program/2001-08-11/642.shtml</a><br><br>from:<br><a href="http://blog.chinaunix.net/u3/93660/showart.php?id=2303992">http://blog.chinaunix.net/u3/93660/showart.php?id=2303992</a></td></tr></tbody></table>
<img src ="http://www.cppblog.com/beautykingdom/aggbug/124465.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-08-23 20:35 <a href="http://www.cppblog.com/beautykingdom/archive/2010/08/23/124465.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>段错误bug的调试</title><link>http://www.cppblog.com/beautykingdom/archive/2010/08/21/124207.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Sat, 21 Aug 2010 11:06:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/08/21/124207.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/124207.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/08/21/124207.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/124207.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/124207.html</trackback:ping><description><![CDATA[我们在用C/C++语言写程序的时侯，内存管理的绝大部分工作都是需要我们来做的。实际上，内存管理是一个比较繁琐的工作，无论你多高明，经验多丰富，难
免会在此处犯些小错误，而通常这些错误又是那么的浅显而易于消除。但是手工&#8220;除虫&#8221;（debug），往往是效率低下且让人厌烦的，本文将就"段错误"这个
内存访问越界的错误谈谈如何快速定位这些"段错误"的语句。<br>下面将就以下的一个存在段错误的程序介绍几种调试方法：<br>
<table style="border: 1px solid #999999; width: 80%; font-size: 12px;" align="center">
    <tbody>
        <tr>
            <td>&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp; dummy_function (void)<br>&nbsp;&nbsp;&nbsp;&nbsp; 2&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp; 3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned char *ptr = 0x00;<br>&nbsp;&nbsp;&nbsp;&nbsp; 4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *ptr = 0x00;<br>&nbsp;&nbsp;&nbsp;&nbsp; 5&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp; 6<br>&nbsp;&nbsp;&nbsp;&nbsp; 7&nbsp; int main (void)<br>&nbsp;&nbsp;&nbsp;&nbsp; 8&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp; 9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dummy_function ();<br>&nbsp;&nbsp;&nbsp; 10<br>&nbsp;&nbsp;&nbsp; 11&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>&nbsp;&nbsp;&nbsp; 12&nbsp; }<br></td>
        </tr>
    </tbody>
</table>
作为一个熟练的C/C++程序员，以上代码的bug应该是很清楚的，因为它尝试操作地址为0的内存区域，而这个内存区域通常是不可访问的禁区，当然就会出错了。我们尝试编译运行它:<br>
<table style="border: 1px solid #999999; width: 80%; font-size: 12px;" align="center">
    <tbody>
        <tr>
            <td>xiaosuo@gentux test $ ./a.out<br>段错误<br></td>
        </tr>
    </tbody>
</table>
果然不出所料，它出错并退出了。<br><span style="font-weight: bold;">1.利用gdb逐步查找段错误:</span><br>这种方法也是被大众所熟知并广泛采用的方法，首先我们需要一个带有调试信息的可执行程序，所以我们加上&#8220;-g -rdynamic"的参数进行编译，然后用gdb调试运行这个新编译的程序,具体步骤如下:<br>
<table style="border: 1px solid #999999; width: 80%; font-size: 12px;" align="center">
    <tbody>
        <tr>
            <td>xiaosuo@gentux test $ gcc -g -rdynamic d.c<br>xiaosuo@gentux test $ gdb ./a.out<br>GNU gdb 6.5<br>Copyright (C) 2006 Free Software Foundation, Inc.<br>GDB is free software, covered by the GNU General Public License, and you are<br>welcome to change it and/or distribute copies of it under certain conditions.<br>Type "show copying" to see the conditions.<br>There is absolutely no warranty for GDB.&nbsp; Type "show warranty" for details.<br>This GDB was configured as "i686-pc-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".<br><br>(gdb) r<br>Starting program: /home/xiaosuo/test/a.out<br><br>Program received signal SIGSEGV, Segmentation fault.<br>0x08048524 in dummy_function () at d.c:4<br>4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *ptr = 0x00;<br>(gdb)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br></td>
        </tr>
    </tbody>
</table>
哦？！好像不用一步步调试我们就找到了出错位置d.c文件的第4行，其实就是如此的简单。<br>从这里我们还发现进程是由于收到了SIGSEGV信号而结束的。通过进一步的查阅文档(man 7 signal)，我们知道SIGSEGV默认handler的动作是打印&#8221;段错误"的出错信息，并产生Core文件，由此我们又产生了方法二。<br><span style="font-weight: bold;">2.分析Core文件：</span><br>Core文件是什么呢？<br>
<table style="border: 1px solid #999999; width: 80%; font-size: 12px;" align="center">
    <tbody>
        <tr>
            <td>The&nbsp; default action of certain signals is to cause a process to
            terminate and produce a core dump file, a disk file containing an image
            of the process's memory&nbsp; at the time of termination.&nbsp; A list of the
            signals which cause a process to dump core can be found in signal(7).</td>
        </tr>
    </tbody>
</table>
以
上资料摘自man page(man 5
core)。不过奇怪了，我的系统上并没有找到core文件。后来，忆起为了渐少系统上的拉圾文件的数量（本人有些洁癖，这也是我喜欢Gentoo的原因
之一），禁止了core文件的生成，查看了以下果真如此，将系统的core文件的大小限制在512K大小，再试:<br>
<table style="border: 1px solid #999999; width: 80%; font-size: 12px;" align="center">
    <tbody>
        <tr>
            <td>xiaosuo@gentux test $ ulimit -c<br>0<br>xiaosuo@gentux test $ ulimit -c 1000<br>xiaosuo@gentux test $ ulimit -c<br>1000<br>xiaosuo@gentux test $ ./a.out<br>段错误 (core dumped)<br>xiaosuo@gentux test $ ls<br>a.out&nbsp; core&nbsp; d.c&nbsp; f.c&nbsp; g.c&nbsp; pango.c&nbsp; test_iconv.c&nbsp; test_regex.c<br></td>
        </tr>
    </tbody>
</table>
core文件终于产生了，用gdb调试一下看看吧:<br>
<table style="border: 1px solid #999999; width: 80%; font-size: 12px;" align="center">
    <tbody>
        <tr>
            <td>xiaosuo@gentux test $ gdb ./a.out core<br>GNU gdb 6.5<br>Copyright (C) 2006 Free Software Foundation, Inc.<br>GDB is free software, covered by the GNU General Public License, and you are<br>welcome to change it and/or distribute copies of it under certain conditions.<br>Type "show copying" to see the conditions.<br>There is absolutely no warranty for GDB.&nbsp; Type "show warranty" for details.<br>This GDB was configured as "i686-pc-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".<br><br><br>warning: Can't read pathname for load map: 输入/输出错误.<br>Reading symbols from /lib/libc.so.6...done.<br>Loaded symbols for /lib/libc.so.6<br>Reading symbols from /lib/ld-linux.so.2...done.<br>Loaded symbols for /lib/ld-linux.so.2<br>Core was generated by `./a.out'.<br>Program terminated with signal 11, Segmentation fault.<br>#0&nbsp; 0x08048524 in dummy_function () at d.c:4<br>4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *ptr = 0x00;<br></td>
        </tr>
    </tbody>
</table>
哇，好历害，还是一步就定位到了错误所在地，佩服一下Linux/Unix系统的此类设计。<br>接着考虑下去，以前用windows系统下的ie的时侯，有时打开某些网页，会出现&#8220;运行时错误&#8221;，这个时侯如果恰好你的机器上又装有windows的编译器的话，他会弹出来一个对话框，问你是否进行调试，如果你选择是，编译器将被打开，并进入调试状态，开始调试。<br>Linux下如何做到这些呢？我的大脑飞速地旋转着，有了，让它在SIGSEGV的handler中调用gdb，于是第三个方法又诞生了:<br><span style="font-weight: bold;">3.段错误时启动调试:</span><br>
<table style="border: 1px solid #999999; width: 80%; font-size: 12px;" align="center">
    <tbody>
        <tr>
            <td>#include &lt;stdio.h&gt;<br>#include &lt;stdlib.h&gt;<br>#include &lt;signal.h&gt;<br>#include &lt;string.h&gt;<br><br>void dump(int signo)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char buf[1024];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char cmd[1024];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FILE *fh;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; snprintf(buf, sizeof(buf), "/proc/%d/cmdline", getpid());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(!(fh = fopen(buf, "r")))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit(0);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(!fgets(buf, sizeof(buf), fh))<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit(0);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fclose(fh);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(buf[strlen(buf) - 1] == '\n')<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buf[strlen(buf) - 1] = '\0';<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; snprintf(cmd, sizeof(cmd), "gdb %s %d", buf, getpid());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; system(cmd);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit(0);<br>}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void<br>dummy_function (void)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned char *ptr = 0x00;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *ptr = 0x00;<br>}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int<br>main (void)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; signal(SIGSEGV, &amp;dump);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dummy_function ();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>}<br></td>
        </tr>
    </tbody>
</table>
编译运行效果如下:<br>
<table style="border: 1px solid #999999; width: 80%; font-size: 12px;" align="center">
    <tbody>
        <tr>
            <td>xiaosuo@gentux test $ gcc -g -rdynamic f.c<br>xiaosuo@gentux test $ ./a.out<br>GNU gdb 6.5<br>Copyright (C) 2006 Free Software Foundation, Inc.<br>GDB is free software, covered by the GNU General Public License, and you are<br>welcome to change it and/or distribute copies of it under certain conditions.<br>Type "show copying" to see the conditions.<br>There is absolutely no warranty for GDB.&nbsp; Type "show warranty" for details.<br>This GDB was configured as "i686-pc-linux-gnu"...Using host libthread_db library "/lib/libthread_db.so.1".<br><br>Attaching to program: /home/xiaosuo/test/a.out, process 9563<br>Reading symbols from /lib/libc.so.6...done.<br>Loaded symbols for /lib/libc.so.6<br>Reading symbols from /lib/ld-linux.so.2...done.<br>Loaded symbols for /lib/ld-linux.so.2<br>0xffffe410 in __kernel_vsyscall ()<br>(gdb) bt<br>#0&nbsp; 0xffffe410 in __kernel_vsyscall ()<br>#1&nbsp; 0xb7ee4b53 in waitpid () from /lib/libc.so.6<br>#2&nbsp; 0xb7e925c9 in strtold_l () from /lib/libc.so.6<br>#3&nbsp; 0x08048830 in dump (signo=11) at f.c:22<br>#4&nbsp; &lt;signal handler called&gt;<br>#5&nbsp; 0x0804884c in dummy_function () at f.c:31<br>#6&nbsp; 0x08048886 in main () at f.c:38<br></td>
        </tr>
    </tbody>
</table>
怎么样？是不是依旧很酷？<br>以上方法都是在系统上有gdb的前提下进行的，如果没有呢？其实glibc为我们提供了此类能够dump栈内容的函数簇，详见/usr/include/execinfo.h（这些函数都没有提供man page，难怪我们找不到），另外你也可以通过<a  href="http://www.gnu.org/software/libc/manual/html_node/Backtraces.html" target="_blank">gnu的手册</a>进行学习。<br><span style="font-weight: bold;">4.利用backtrace和objdump进行分析:</span><br>重写的代码如下:<br>
<table style="border: 1px solid #999999; width: 80%; font-size: 12px;" align="center">
    <tbody>
        <tr>
            <td>#include &lt;execinfo.h&gt;<br>#include &lt;stdio.h&gt;<br>#include &lt;stdlib.h&gt;<br>#include &lt;signal.h&gt;<br><br>/* A dummy function to make the backtrace more interesting. */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void<br>dummy_function (void)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned char *ptr = 0x00;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *ptr = 0x00;<br>}<br><br>void dump(int signo)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void *array[10];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size_t size;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char **strings;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size_t i;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size = backtrace (array, 10);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strings = backtrace_symbols (array, size);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf ("Obtained %zd stack frames.\n", size);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (i = 0; i &lt; size; i++)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf ("%s\n", strings[i]);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; free (strings);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit(0);<br>}<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int<br>main (void)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; signal(SIGSEGV, &amp;dump);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dummy_function ();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>}<br></td>
        </tr>
    </tbody>
</table>
编译运行结果如下：<br>
<table style="border: 1px solid #999999; width: 80%; font-size: 12px;" align="center">
    <tbody>
        <tr>
            <td>xiaosuo@gentux test $ gcc -g -rdynamic g.c<br>xiaosuo@gentux test $ ./a.out<br>Obtained 5 stack frames.<br>./a.out(dump+0x19) [0x80486c2]<br>[0xffffe420]<br>./a.out(main+0x35) [0x804876f]<br>/lib/libc.so.6(__libc_start_main+0xe6) [0xb7e02866]<br>./a.out [0x8048601]<br></td>
        </tr>
    </tbody>
</table>
这次你可能有些失望,似乎没能给出足够的信息来标示错误,不急,先看看能分析出来什么吧,用objdump反汇编程序,找到地址0x804876f对应的代码位置:<br>
<table style="border: 1px solid #999999; width: 80%; font-size: 12px;" align="center">
    <tbody>
        <tr>
            <td>xiaosuo@gentux test $ objdump -d a.out<br></td>
        </tr>
    </tbody>
</table>
<br>
<table style="border: 1px solid #999999; width: 80%; font-size: 12px;" align="center">
    <tbody>
        <tr>
            <td>&nbsp;8048765:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e8 02 fe ff ff&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; call&nbsp;&nbsp; 804856c &lt;signal@plt&gt;<br>&nbsp;804876a:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e8 25 ff ff ff&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; call&nbsp;&nbsp; 8048694 &lt;dummy_function&gt;<br>&nbsp;<span style="color: #ff0102;">804876f</span>:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b8 00 00 00 00&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mov&nbsp;&nbsp;&nbsp; $0x0,%eax<br>&nbsp;8048774:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; leave<br></td>
        </tr>
    </tbody>
</table>
我们还是找到了在哪个函数(dummy_function)中出错的,信息已然不是很完整,不过有总比没有好的啊!<br><span style="font-weight: bold;">后记:</span><br>本文给出了分析"段错误"的几种方法,不要认为这是与孔乙己先生的"回"字四种写法一样的哦,因为每种方法都有其自身的适用范围和适用环境,请酌情使用,或遵医嘱。<br>from:<br>http://www.cublog.cn/u/5251/showart.php?id=173718<br><img src ="http://www.cppblog.com/beautykingdom/aggbug/124207.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-08-21 19:06 <a href="http://www.cppblog.com/beautykingdom/archive/2010/08/21/124207.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GDB多线程调试</title><link>http://www.cppblog.com/beautykingdom/archive/2010/08/20/124110.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Fri, 20 Aug 2010 09:16:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/08/20/124110.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/124110.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/08/20/124110.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/124110.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/124110.html</trackback:ping><description><![CDATA[<p>GDB多线程调试的基本命令。 </p>
<p>info threads <br>显示当前可调试的所有线程，每个线程会有一个GDB为其分配的ID，后面操作线程的时候会用到这个ID。 <br>前面有*的是当前调试的线程。 </p>
<p>thread ID <br>切换当前调试的线程为指定ID的线程。 </p>
<p>break thread_test.c:123 thread all<br>在所有线程中相应的行上设置断点</p>
<p>thread apply ID1 ID2 command <br>让一个或者多个线程执行GDB命令command。 </p>
<p>thread apply all command <br>让所有被调试线程执行GDB命令command。 </p>
<p>set scheduler-locking off|on|step <br>估计是实际使用过多线程调试的人都可以发现，在使用step或者continue命令调试当前被调试线程的时候，其他线程也是同时执行的，怎么只让被调试程序执行呢？通过这个命令就可以实现这个需求。<br>off 不锁定任何线程，也就是所有线程都执行，这是默认值。 <br>on 只有当前被调试程序会执行。 <br>step 在单步的时候，除了next过一个函数的情况(熟悉情况的人可能知道，这其实是一个设置断点然后continue的行为)以外，只有当前线程会执行。 </p>
<p>在介绍完基本的多线程调试命令后，大概介绍一下GDB多线程调试的实现思路。 </p>
<p>比较主要的代码是thread.c，前面介绍的几个命令等都是在其中实现。 <br>thread_list这个表存储了当前可调试的所有线程的信息。 <br>函数add_thread_silent或者add_thread(不同版本GDB不同)用来向thread_list列表增加一个线程的信息。 <br>函数delete_thread用来向thread_list列表删除一个线程的信息。 <br>上面提到的这2个函数会被有线程支持的target调用，用来增加和删除线程，不同的OS对线程的实现差异很大，这么实现比较好的保证了GDB多线程调试支持的扩展性。 <br>函数info_threads_command是被命令info threads调用的，就是显示thread_list列表的信息。 <br>函数thread_command是被命令thread调用，切换当前线程最终调用的函数是switch_to_thread，这个函数会先将当前调试线程变量inferior_ptid，然后对寄存器和frame缓冲进行刷新。 <br>函数thread_apply_command被命令thread apply调用，这个函数的实际实现其实很简单，就是先切换当前线为指定线程，然后调用函数execute_command调用指定函数。 </p>
<p>比较特别的是set scheduler-locking没有实现在thread.c中，而是实现在控制被调试程序执行的文件infrun.c中。 <br>对
其的设置会保存到变量scheduler_mode中，而实际使用这个变量的函数只有用来令被调试程序执行的函数resume。在默认情况下，
传递给target_resume的变量是resume_ptid，默认情况下其的值为RESUME_ALL，也就是告诉target程序执行的时候所有
被调试线程都要被执行。而当scheduler_mode设置为只让当前线程执行的时候，resume_ptid将被设置为inferior_ptid，
这就告诉target只有inferior_ptid的线程会被执行。 </p>
<p>最后特别介绍一下Linux下多线程的支持，基本的调试功能在linux-nat.c中，这里有对Linux轻量级别进程本地调试的支持。但是其
在调试多线程程序的时候，还需要对pthread调试的支持，这个功能实现在linux-thread-db.c中。对pthread的调试要通过调用
libthread_db库来支持。 <br>这里有一个单独的target"multi-thread"，这个target有2点很特别: <br>第
一，一般target的装载是在调用相关to_open函数的时候调用push_target进行装载。而这个target则不同，在其初始化
的时候，就注册了函数thread_db_new_objfile到库文件attach事件中。这样当GDB为调试程序的动态加载库时候attach库文
件的时候，就会调用这个函数thread_db_new_objfile。这样当GDB装载libpthread库的时候，最终会装载
target"multi-thread"。 <br>第二，这个target并没有像大部分target那样自己实现了全部调试功能，其配合linux-nat.c的代码的功能，这里有一个target多层结构的设计，要介绍的比较多，就不详细介绍了。 </p>
<p><br>最后介绍一下我最近遇见的一个多线程调试和解决。 </p>
<p>基本问题是在一个Linux环境中，调试多线程程序不正常，info threads看不到多线程的信息。 <br>我先用命令
maintenance print
target-stack看了一下target的装载情况，发现target"multi-thread"没有被装载，用GDB对GDB进行调试，发现在
函数check_for_thread_db在调用libthread_db中的函数td_ta_new的时候，返回了TD_NOLIBTHREAD，所
以没有装载target"multi-thread"。 <br>在时候我就怀疑是不是libpthread有问题，于是检查了一下发现了问题，这个环
境中的libpthread是被strip过的，我想可能
就是以为这个影响了td_ta_new对libpthread符号信息的获取。当我换了一个没有strip过的libpthread的时候，问题果然解决
了。 <br>最终我的解决办法是拷贝了一个.debug版本的libpthread到lib目录中，问题解决了。&nbsp; 多线程如果dump，多为段错误，一般都涉及内存非法读写。可以这样处理，使用下面的命令打开系统开关，让其可以在死掉的时候生成core文件。&nbsp;&nbsp; <br>ulimit -c unlimited<br>这样的话死掉的时候就可以在当前目录看到core.pid(pid为进程号)的文件。接着使用gdb:<br>gdb ./bin ./core.pid <br>进去后，使用bt查看死掉时栈的情况，在使用frame命令。</p>
<p>还有就是里面某个线程停住，也没死，这种情况一般就是死锁或者涉及消息接受的超时问题(听人说的，没有遇到过)。遇到这种情况，可以使用：<br>gcore pid （调试进程的pid号）<br>手动生成core文件，在使用pstack(linux下好像不好使)查看堆栈的情况。如果都看不出来，就仔细查看代码，看看是不是在if，return，break，continue这种语句操作是忘记解锁，还有嵌套锁的问题，都需要分析清楚了。</p>
<p><br></p>
<p>from:</p>
<p>http://blog.chinaunix.net/u3/91335/showart.php?id=2249238<br></p><img src ="http://www.cppblog.com/beautykingdom/aggbug/124110.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-08-20 17:16 <a href="http://www.cppblog.com/beautykingdom/archive/2010/08/20/124110.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux的消息队列与共享内存编程</title><link>http://www.cppblog.com/beautykingdom/archive/2010/07/14/120300.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Wed, 14 Jul 2010 02:43:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/07/14/120300.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/120300.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/07/14/120300.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/120300.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/120300.html</trackback:ping><description><![CDATA[<p class="cc-lisence" style="line-height: 180%;">
<a  href="http://creativecommons.org/licenses/by/3.0/deed.zh" target="_blank">版权声明</a>：转载时请以超链接形式标明文章原始出处和作者信息及<a  href="http://bangzhuzhongxin.blogbus.com/logs/11205960.html" target="_blank">本声明</a><br><a  href="http://xufish.blogbus.com/logs/40537374.html">http://xufish.blogbus.com/logs/40537374.html</a><br><br>
</p>
<p><span style="font-family: Georgia; line-height: normal;">012号与013
号程序，分别是关于消息队列和共享内存的<br style="line-height: normal;"><br style="line-height: normal;">/*********************程序相关信
息*********************<br style="line-height: normal;">程序编号：012<br style="line-height: normal;">程序编写起始日期：2008.11.1<br style="line-height: normal;">程序编写完成日期：2008.11.1<br style="line-height: normal;">程序修改日
期：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 修改备注：<br style="line-height: normal;">程序目的：学习linux消息队列通信<br style="line-height: normal;">所用主要函
数：msgget(),msgsnd(),msgrcv(),msgctl()<br style="line-height: normal;">程序
存疑：<br style="line-height: normal;">程序完成地点： 宿舍内<br style="line-height: normal;">*********************程序相关信息*********************/<br style="line-height: normal;">#include&lt;sys/types.h&gt;<br style="line-height: normal;">#include&lt;sys/ipc.h&gt;<br style="line-height: normal;">#include&lt;sys/msg.h&gt;<br style="line-height: normal;">#include&lt;stdio.h&gt;<br style="line-height: normal;">#include&lt;string.h&gt;<br style="line-height: normal;">#include&lt;stdlib.h&gt;<br style="line-height: normal;">int main()<br style="line-height: normal;">{<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; int pid,msqid;//后者为消息队列识别代号<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; struct msgbuf<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; {<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; long mtype;//消息类型<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; char mtext[20];//消息内容<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; }send_buf,receive_buf;<br style="line-height: normal;">&nbsp;&nbsp;&nbsp;
if((msqid=msgget(IPC_PRIVATE,0700))&lt;0)//建立消息队列<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; {<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
printf("msgget建立消息队列失败。\n");<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
exit(1);<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; }<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; else<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
printf("msgget建立消息队列成功，该消息队列识别代号为%d。\n",msqid);<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; if((pid=fork())&lt;0)<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; {<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf("fork()函数调用失败！\n");<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; exit(2);<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; }<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; else
if(pid&gt;0)//父进程，发送消息到消息队列<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; {<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; send_buf.mtype=1;<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; strcpy(send_buf.mtext,"My test
information");<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
printf("发送到消息队列的信息内容为：%s\n",send_buf.mtext);<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
if(msgsnd(msqid,&amp;send_buf,20,IPC_NOWAIT)&lt;0)//发送send_buf中的信息到msqid
对应的消息队列<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf("msgsnd消息发送失败。\n");<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; exit(3);<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf("msgsnd消息发送成功。\n");<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sleep(2);<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
exit(0);<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; }<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; else//子进程，从消息队列中接收消息]<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; {<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sleep(2);//等待父进程发送消息完成<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int infolen;//读到的信息数据长度<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
if((infolen=msgrcv(msqid,&amp;receive_buf,20,0,IPC_NOWAIT))&lt;0)//自消息队列
接收信息<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf("msgrcv读取信息错误。\n");<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; exit(4);<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf("msgrcv读取信息成功。\n");<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
printf("自消息队列读取到的内容为%s，共读取%d个字节。\n",receive_buf.mtext,infolen);<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
if((msgctl(msqid,IPC_RMID,NULL))&lt;0)//删除msqid对应的消息队列<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br style="line-height: normal;">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf("msgctl函数调用出现错误。\n");<br style="line-height: normal;">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; exit(5);<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
printf("识别代号为%d的消息队列已经被成功删除。\n",msqid);<br style="line-height: normal;">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; exit(0);<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; }<br style="line-height: normal;">}<br style="line-height: normal;">/*********************程序运行结
果*********************<br style="line-height: normal;">[root@localhost
temp]# ./msg<br style="line-height: normal;">msgget建立消息队列成功，该消息队列识别代号为
98304。<br style="line-height: normal;">发送到消息队列的信息内容为：My test information<br style="line-height: normal;">msgsnd消息发送成功。<br style="line-height: normal;">msgrcv读取信息成功。<br style="line-height: normal;">自消息队列读取到的内容为My
test information，共读取20个字节。<br style="line-height: normal;">识别代号为98304的消息
队列已经被成功删除。<br style="line-height: normal;">***********************************************************/<br style="line-height: normal;"><br style="line-height: normal;">/*********************
程序相关信息*********************<br style="line-height: normal;">程序编号：013<br style="line-height: normal;">程序编写起始日期：2008.11.1<br style="line-height: normal;">程序编写完成日期：2008.11.1<br style="line-height: normal;">程序修改日
期：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 修改备注：<br style="line-height: normal;">程序目的：学习linux共享内存<br style="line-height: normal;">所用主要函
数：shmget(),shmat(),shmctl(),shmdt()<br style="line-height: normal;">程序存
疑：<br style="line-height: normal;">程序完成地点： 宿舍内<br style="line-height: normal;">*********************程序相关信息*********************/<br style="line-height: normal;">#include&lt;sys/ipc.h&gt;<br style="line-height: normal;">#include&lt;sys/shm.h&gt;<br style="line-height: normal;">#include&lt;stdlib.h&gt;<br style="line-height: normal;">#include&lt;string.h&gt;<br style="line-height: normal;">#include&lt;stdio.h&gt;<br style="line-height: normal;">int main()<br style="line-height: normal;">{<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; int pid,shmid;//后者为共享内存识别代号<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; char *write_address;<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; char *read_address;<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; struct shmid_ds dsbuf;<br style="line-height: normal;">&nbsp;&nbsp;&nbsp;
if((shmid=shmget(IPC_PRIVATE,32,0))&lt;0)//分配共享内存<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; {<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
printf("shmid共享内存分配出现错误。\n");<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
exit(1);<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; }<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; else<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
printf("shmid共享内存分配成功，共享内存识别代号为：%d。\n",shmid);<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; if((pid=fork())&lt;0)<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; {<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf("fork函数调用出现错误！\n");<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; exit(2);<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; }<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; else
if(pid&gt;0)//父进程，向共享内存中写入数据<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; {<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf("父进程的ID是：%d\n",getpid());<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; write_address=(char
*)shmat(shmid,NULL,0);//连接共享内存<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
if((int)write_address==-1)<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf("shmat连接共享内存错误。\n");<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; exit(3);<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br style="line-height: normal;">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf("shmat连接共享内存成功。\n");<br style="line-height: normal;">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; strcpy(write_address,"我是写入共享内存的测试数据");//将数据写入共享内存<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
printf("写入共享内存的信息为&#8220;%s&#8221;。\n",write_address);<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if((shmdt((void *)write_address))&lt;0)//断开与共享内存的连接<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
printf("shmdt共享内存断开错误。\n");<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
else<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
printf("shmdt共享内存断开成功。\n");<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
sleep(2);<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return;<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br style="line-height: normal;">&nbsp;&nbsp;&nbsp;
}<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; else//子进程，从共享内存中读取数据<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; {<br style="line-height: normal;">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; sleep(2);//等待父进程写入共享内存完毕<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
printf("子进程ID是：%d\n",getpid());<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
if((shmctl(shmid,IPC_STAT,&amp;dsbuf))&lt;0)<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
printf("shmctl获取共享内存数据结构出现错误。\n");<br style="line-height: normal;">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; exit(4);<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
printf("shmctl获取共享内存数据结构成功。\n建立这个共享内存的进程ID是：%d\n",dsbuf.shm_cpid);<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
printf("该共享内存的大小为：%d\n",dsbuf.shm_segsz);<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if((read_address=(char
*)shmat(shmid,0,0))&lt;0)//连接共享内存<br style="line-height: normal;">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
printf("shmat连接共享内存出现错误。\n");<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; exit(5);<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
printf("自共享内存中读取的信息为：&#8220;%s&#8221;。\n",read_address);<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
printf("最后一个操作该共享内存的进程ID是：%d\n",dsbuf.shm_lpid);<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if((shmdt((void
*)read_address))&lt;0)//断开与共享内存的连接<br style="line-height: normal;">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
printf("shmdt共享内存断开错误。\n");<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; exit(6);<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf("shmdt共享内存断开成功。\n");<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
if(shmctl(shmid,IPC_RMID,NULL)&lt;0)//删除共享内存及其数据结构<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf("shmctl删除共享内存及其数据结构出现错误。\n");<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; exit(7);<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf("shmctl删除共享内存及其数据结构成功。\n");<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; exit(0);<br style="line-height: normal;">&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;<br style="line-height: normal;">&nbsp;&nbsp;&nbsp; }<br style="line-height: normal;">}<br style="line-height: normal;">/*********************程序运行结
果*********************<br style="line-height: normal;">[root@localhost
temp]# ./shm<br style="line-height: normal;">shmid共享内存分配成功，共享内存识别代号
为：1703947。<br style="line-height: normal;">父进程的ID是：7647<br style="line-height: normal;">shmat连接共享内存成功。<br style="line-height: normal;">写入共享内存的信息为&#8220;我是写入共享内存的测试数据&#8221;。<br style="line-height: normal;">shmdt
共享内存断开成功。<br style="line-height: normal;">子进程ID是：7648<br style="line-height: normal;">shmctl获取共享内存数据结构成功。<br style="line-height: normal;">建立这个共享内存的进程ID是：7647<br style="line-height: normal;">该共享内存的大小
为：32<br style="line-height: normal;">自共享内存中读取的信息为：&#8220;我是写入共享内存的测试数据&#8221;。<br style="line-height: normal;">最后一个操作该共享内存的进程ID是：7647<br style="line-height: normal;">shmdt共享内存断开成功。<br style="line-height: normal;">shmctl删除共享内存及其数据结构成功。<br style="line-height: normal;">***********************************************************/</span></p><img src ="http://www.cppblog.com/beautykingdom/aggbug/120300.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-07-14 10:43 <a href="http://www.cppblog.com/beautykingdom/archive/2010/07/14/120300.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ar和nm命令的使用</title><link>http://www.cppblog.com/beautykingdom/archive/2010/05/06/114708.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Thu, 06 May 2010 14:32:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/05/06/114708.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/114708.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/05/06/114708.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/114708.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/114708.html</trackback:ping><description><![CDATA[当我们的程序中有经常使用的模块，而且这种模块在其他程序中也会用到，这时按照软件重用的思想，我们应该将它们生成库，使得以后编程可以减少开发代
码量。这里介绍两个命令ar和nm，用来对库操作。
<p><strong> 　　1、ar基本用法<br></strong> 　　ar命令可以用来创建、修改库，也可以从库中提出单个模块。库是一单独的文
件，里面包含了按照特定的结构组织起来的其它的一些文件（称做此库文件的member）。原始文件的内容、模式、时间戳、属主、组等属性都保留在库文件
中。<br>　　下面是ar命令的格式：<br>　　ar [-]{dmpqrtx}[abcfilNoPsSuvV] [membername]
[count] archive files...<br>　　例如我们可以用ar rv libtest.a hello.o
hello1.o来生成一个库，库名字是test，链接时可以用-ltest链接。该库中存放了两个模块hello.o和hello1.o。选项前可以有
&#8216;-&#8217;字符，也可以没有。下面我们来看看命令的操作选项和任选项。现在我们把{dmpqrtx}部分称为操作选项，而[abcfilNoPsSuvV]部
分称为任选项。<br>　　{dmpqrtx}中的操作选项在命令中只能并且必须使用其中一个，它们的含义如下：<br>　　d：从库中删除模块。按模块
原来的文件名指定要删除的模块。如果使用了任选项v则列出被删除的每个模块。<br>　　m：该操作是在一个库中移动成员。当库中如果有若干模块有相同的
符号定义(如函数定义)，则成员的位置顺序很重要。如果没有指定任选项，任何指定的成员将移到库的最后。也可以使用&#8217;a&#8217;，&#8217;b&#8217;，或&#8217;I&#8217;任选项移动到
指定的位置。 <br>　　p：显示库中指定的成员到标准输出。如果指定任选项v，则在输出成员的内容前，将显示成员的名字。如果没有指定成员的名字，所
有库中的文件将显示出来。 <br>　　q：快速追加。增加新模块到库的结尾处。并不检查是否需要替换。&#8217;a&#8217;，&#8217;b&#8217;，或&#8217;I&#8217;任选项对此操作没有影
响，模块总是追加的库的结尾处。如果使用了任选项v则列出每个模块。 这时，库的符号表没有更新，可以用&#8217;ar
s&#8217;或ranlib来更新库的符号表索引。 <br>　　r：在库中插入模块(替换)。当插入的模块名已经在库中存在，则替换同名的模块。如果若干模块中
有一个模块在库中不存在，ar显示一个错误消息，并不替换其他同名模块。默认的情况下，新的成员增加在库的结尾处，可以使用其他任选项来改变增加的位置。
<br>　　t：显示库的模块表清单。一般只显示模块名。 <br>　　x：从库中提取一个成员。如果不指定要提取的模块，则提取库中所有的模块。 <br>
<br>　　下面在看看可与操作选项结合使用的任选项：<br>　　a：在库的一个已经存在的成员后面增加一个新的文件。如果使用任选项a，则应该为命
令行中membername参数指定一个已经存在的成员名。 <br>　　b：在库的一个已经存在的成员前面增加一个新的文件。如果使用任选项b，则应该
为命令行中membername参数指定一个已经存在的成员名。 <br>　　c：创建一个库。不管库是否存在，都将创建。<br>　　f：在库中截短指
定的名字。缺省情况下，文件名的长度是不受限制的，可以使用此参数将文件名截短，以保证与其它系统的兼容。 <br>　　i：在库的一个已经存在的成员前
面增加一个新的文件。如果使用任选项i，则应该为命令行中membername参数指定一个已经存在的成员名(类似任选项b)。 <br>　　l：暂未使
用 <br>　　N：与count参数一起使用，在库中有多个相同的文件名时指定提取或输出的个数。 <br>　　o：当提取成员时，保留成员的原始数
据。如果不指定该任选项，则提取出的模块的时间将标为提取出的时间。 <br>　　P：进行文件名匹配时使用全路径名。ar在创建库时不能使用全路径名
（这样的库文件不符合POSIX标准），但是有些工具可以。 <br>　　s：写入一个目标文件索引到库中，或者更新一个存在的目标文件索引。甚至对于没
有任何变化的库也作该动作。对一个库做ar s等同于对该库做ranlib。 <br>　　S：不创建目标文件索引，这在创建较大的库时能加快时间。 <br>
u：一般说来，命令ar
r&#8230;插入所有列出的文件到库中，如果你只想插入列出文件中那些比库中同名文件新的文件，就可以使用该任选项。该任选项只用于r操作选项。 <br>
v：该选项用来显示执行操作选项的附加信息。 <br>　　V：显示ar的版本。 <br><br><strong> 　　2、nm基本用法命令<br></strong>
nm用来列出目标文件的符号清单。下面是nm命令的格式：<br>　　nm [-a|--debug-syms]
[-g|--extern-only] [-B][-C|--demangle] [-D|--dynamic]
[-s|--print-armap][-o|--print-file-name]
[-n|--numeric-sort][-p|--no-sort] [-r|--reverse-sort]
[--size-sort][-u|--undefined-only] [-l|--line-numbers]
[--help][--version] [-t radix|--radix=radix][-P|--portability] [-f
format|--format=format][--target=bfdname] [objfile...]<br>　　如果没有为nm命令指出目
标文件，则nm假定目标文件是a.out。下面列出该命令的任选项，大部分支持&#8220;-&#8221;开头的短格式和&#8220;—&#8220;开头的长格式。<br>　　-A、-o或
--print-file-name：在找到的各个符号的名字前加上文件名，而不是在此文件的所有符号前只出现文件名一次。 <br>　　例如nm
libtest.a的输出如下：<br>　　CPThread.o:<br>　　00000068 T Main__8CPThreadPv<br>
00000038 T Start__8CPThread<br>　　00000014 T _._8CPThread<br>　　00000000 T
__8CPThread<br>　　00000000 ? __FRAME_BEGIN__<br>　　&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;<br>　　则nm
&#8211;A 的输出如下：<br>　　libtest.a:CPThread.o:00000068 T Main__8CPThreadPv<br>
libtest.a:CPThread.o:00000038 T Start__8CPThread<br>
libtest.a:CPThread.o:00000014 T _._8CPThread<br>
libtest.a:CPThread.o:00000000 T __8CPThread<br>
libtest.a:CPThread.o:00000000 ? __FRAME_BEGIN__<br>
&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;&#8230;<br>　　-a或--debug-syms：显示调试符号。 <br>　　-B：等同于
--format=bsd，用来兼容MIPS的nm。 <br>　　-C或--demangle：将低级符号名解码(demangle)成用户级名字。这
样可以使得C++函数名具有可读性。 <br>　　-D或--dynamic：显示动态符号。该任选项仅对于动态目标(例如特定类型的共享库)有意义。 <br>
-f format：使用format格式输出。format可以选取bsd、sysv或posix，该选项在GNU的nm中有用。默认为bsd。 <br>
-g或--extern-only：仅显示外部符号。 <br>　　-n、-v或--numeric-sort：按符号对应地址的顺序排序，而非按符号
名的字符顺序。 <br>　　-p或--no-sort：按目标文件中遇到的符号顺序显示，不排序。 <br>　　-P或--portability：使
用POSIX.2标准输出格式代替默认的输出格式。等同于使用任选项-f posix。<br>　　-s或--print-armap：当列出库中成员的
符号时，包含索引。索引的内容包含：哪些模块包含哪些名字的映射。<br>　　-r或--reverse-sort：反转排序的顺序(例如，升序变为降
序)。 <br>　　--size-sort：按大小排列符号顺序。该大小是按照一个符号的值与它下一个符号的值进行计算的。 <br>　　-t
radix或--radix=radix：使用radix进制显示符号值。radix只能为&#8220;d&#8221;表示十进制、&#8220;o&#8221;表示八进制或&#8220;x&#8221;表示十六进制。 <br>
--target=bfdname：指定一个目标代码的格式，而非使用系统的默认格式。 <br>　　-u或--undefined-only：仅显示
没有定义的符号(那些外部符号)。 <br>　　-l或--line-numbers：对每个符号，使用调试信息来试图找到文件名和行号。对于已定义的符
号，查找符号地址的行号。对于未定义符号，查找指向符号重定位入口的行号。如果可以找到行号信息，显示在符号信息之后。 <br>　　-V或
--version：显示nm的版本号。 <br>　　--help：显示nm的任选项。 </p>
<p>　　<strong> 3、示例</strong> <br>　　1)、创建静态库：<br>　　gcc -c hello.c -o hello.o<br>
ar rcs libhello.a hello.o<br><br>　　2)、使用静态库：<br>　　gcc -o test test.c
-static -L. -lhello<br><br>　　3)、共享库版本： version.minor.release<br><br>
4)、构建动态共享库：<br>　　gcc/g++下加 -fPIC -shared 参数即可<br>　　其中 -fPIC
作用于编译阶段，告诉编译器产生与位置无关代码(Position-Independent
Code)，则产生的代码中，没有绝对地址，全部使用相对地址，故而代码可以被加载器加载到内存的任意位置，都可以正确的执行。这正是共享库所要求的，共
享库被加载时，在内存的位置不是固定的。<br>　　可以export LD_DEBUG=files，查看每次加载共享库的实际地址。<br>　　其中
-shared 作用于链接阶段，实际传递给链接器ld，让其添加作为共享库所需要的额外描述信息，去除共享库所不需的信息。<br>　　可以分解为如
下步骤：<br>　　I. gcc -c err.c -fPIC -o err.o<br>　　II. gcc -shared -o
liberr.so.0.0 err.o<br>　　II &lt;==&gt; ld -Bshareable -o liberr.so.0.0
err.o<br>　　III. ln -s liberr.so.0.0 liberr.so<br><br>　　5)、动态共享库的使用：<br>
由共享库加载器自动加载<br>　　gcc -o test test.c -lerr -L. -Wl,-rpath=./<br>
-Wl,option<br>　　Pass option as an option to the linker. If option
contains commas,&nbsp;it is split into multiple options at the commas.<br>
-rpath: 指定运行时搜索动态库的路径，可以用环境变量LD_LIBRARY_PATH指定。<br><br>　　程序自己控制加载、符号解析（使
用libc6之dl库）<br>　　gcc cos.c -o cos -ldl<br>　　/* cos.c */<br>&nbsp;&nbsp;&nbsp; #include
&lt;stdio.h&gt;<br>&nbsp;&nbsp;&nbsp; #include &lt;dlfcn.h&gt;<br>　　int main()<br>　　{<br>
void *handle;<br>　　　　double (*cosine)(double);<br>　　　　char *error;<br>
double rev;</p>
<p>　　　　handle = dlopen("libm.so", RTLD_LAZY); // 加载动态库<br>
if(!handle)<br>　　　　{<br>　　　　　　fprintf(stderr, "%s\n", dlerror());<br>
exit(1);<br>　　　　}</p>
<p>　　　　dlerror();</p>
<p>　　　　cosine = dlsym(handle, "cos"); // 解析符号cos<br>　　　　if((error =
dlerror()) != NULL)<br>　　　　{<br>　　　　　　fprintf(stderr, "%s\n", error);<br>
exit(1);<br>　　　　}</p>
<p>　　　　rev = cosine(3.1415926); // 使用cos函数<br>　　　　printf("The cos result
is: %f\n", rev);</p>
<p>　　　　dlclose(handle);</p>
return 0;<br>　　}<br><br>　　6)、GNU/Linux下动态库之加载器为/lib/ld-linux.so,
可执行的。<br>　　/lib/ld-linux.so ./cos &lt;===&gt; ./cos<br><br>　　7)、有用的环境变
量&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>　　LD_LIBRARY_PATH<br>　　指定运行时动态库的搜索路径<br>　　LD_DEBUG<br>　　调试用，其值
可为：<br>　　libs&nbsp;&nbsp;&nbsp;&nbsp; display library search paths<br>　　reloc&nbsp;&nbsp;&nbsp;&nbsp; display
relocation processing<br>　　files&nbsp;&nbsp;&nbsp;&nbsp; display progress for input file<br>
symbols&nbsp;&nbsp; display symbol table processing<br>　　bindings&nbsp;&nbsp; display
information about symbol binding<br>　　versions&nbsp;&nbsp; display version
dependencies<br>　　all&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; all previous options combined<br>
statistics display relocation statistics<br>　　unused&nbsp;&nbsp;&nbsp;&nbsp; determined
unused DSOs<br>　　help&nbsp;&nbsp;&nbsp;&nbsp; display this help message and exit<br><br>
8)、搜索含有cos函数的共享库名&nbsp;<br>　　nm -AD /lib/* /usr/lib/* 2&gt;/dev/null | grep
"cos$"<br>　　nm -- 从对象文件中列出符号。<br><br>　　9)、读取ELF文件格式信息<br>　　readelf -Ds
./libfoo.so #读出共享库的符号
<br><br>from:<br><a  href="http://fnstudio.blog.sohu.com/74541293.html">http://fnstudio.blog.sohu.com/74541293.html
</a><br><br><img src ="http://www.cppblog.com/beautykingdom/aggbug/114708.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-05-06 22:32 <a href="http://www.cppblog.com/beautykingdom/archive/2010/05/06/114708.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>proc文件系统</title><link>http://www.cppblog.com/beautykingdom/archive/2010/05/04/114374.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Tue, 04 May 2010 14:03:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/05/04/114374.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/114374.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/05/04/114374.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/114374.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/114374.html</trackback:ping><description><![CDATA[<pre>proc文件系统是一个伪文件系统，它只存在内存当中，而不占用外存空间。<br>它以文件系统的方式为访问系统内核数据的操作提供接口。用户和应用程<br>序可以通过proc得到系统的信息，并可以改变内核的某些参数。由于系统<br>的信息，如进程，是动态改变的，所以用户或应用程序读取proc文件时，<br>proc文件系统是动态从系统内核读出所需信息并提交的。<br>它的目录结构如下： <br><br>目录名称                       目录内容 <br>apm                               高级电源管理信息 <br>cmdline                          内核命令行 <br>Cpuinfo                          关于Cpu信息 <br>Devices                          可以用到的设备（块设备/字符设备） <br>Dma                               使用的DMA通道 <br>Filesystems                支持的文件系统 <br>Interrupts                  中断的使用 <br>Ioports                          I/O端口的使用 <br>Kcore                              内核核心印象 <br>Kmsg                             内核消息 <br>Ksyms                           内核符号表 <br>Loadavg                          负载均衡 <br>Locks                           内核锁 <br>Meminfo                          内存信息 <br>Misc                             杂项 <br>Modules                          加载模块列表 <br>Mounts                            加载的文件系统 <br>Partitions                  系统识别的分区表 <br>Rtc                               实时时钟 <br>Slabinfo                       Slab池信息 <br>Stat                             全面统计状态表 <br>Swaps                             对换空间的利用情况 <br>Version                          内核版本 <br>Uptime                            系统正常运行时间   <br><br>并不是所有这些目录在你的系统中都有，这取决于你的内核配置和装载的模块。<br>另外，在/proc下还有三个很重要的目录：net，scsi和 sys。Sys目录是可写的，<br>可以通过它来访问或修改内核的参数（见下一部分），而net和scsi则依赖于<br>内核配置。例如，如果系统不支持scsi，则 scsi目录不存在。   <br><br>除了以上介绍的这些，还有的是一些以数字命名的目录，它们是进程目录。<br>系统中当前运行的每一个进程都有对应的一个目录在/proc下，以进程的<br>PID号为目录名，它们是读取进程信息的接口。而self目录则是读取进程<br>本身的信息接口，是一个link。Proc文件系统的名字就是由之而起。<br>进程目录的结构如下：   <br><br>目录名称                   目录内容 <br>Cmdline                   命令行参数 <br>Environ                   环境变量值 <br>Fd                        一个包含所有文件描述符的目录 <br>Mem                       进程的内存被利用情况 <br>Stat                      进程状态 <br>Status                    进程当前状态，以可读的方式显示出来 <br>Cwd                       当前工作目录的链接 <br>Exe                       指向该进程的执行命令文件 <br>Maps                      内存映象 <br>Statm                     进程内存状态信息 <br>Root                      链接此进程的root目录 <br><br>用户如果要查看系统信息，可以用cat命令。例如： <br><br># cat /proc/interrupts <br>CPU0 <br>0: 8728810 XT-PIC timer <br>1: 895 XT-PIC keyboard <br>2: 0 XT-PIC cascade <br>3: 531695 XT-PIC aha152x <br>4: 2014133 XT-PIC serial <br>5: 44401 XT-PIC pcnet_cs <br>8: 2 XT-PIC rtc <br>11: 8 XT-PIC i82365 <br>12: 182918 XT-PIC Mouse <br>13: 1 XT-PIC fpu PS/2 <br>14: 1232265 XT-PIC ide0 <br>15: 7 XT-PIC ide1 <br>NMI: 0   <br><br>用户还可以实现修改内核参数。在/proc文件系统中有一个有趣的<br>目录：/proc/sys。它不仅提供了内核信息，而且可以通过它修改<br>内核参数，来优化你的系统。但是你必须很小心，因为可能会造<br>成系统崩溃。最好是先找一台无关紧要的机子，调试成功后再应<br>用到你的系统上。 <br><br>要改变内核的参数，只要用vi编辑或echo参数重定向到文件中即<br>可。下面有一个例子：   <br><br># cat /proc/sys/fs/file-max <br>4096 <br># echo 8192 &gt; /proc/sys/fs/file-max <br># cat /proc/sys/fs/file-max <br>8192   <br><br>如果你优化了参数，则可以把它们写成添加到文件rc.local中，<br>使它在系统启动时自动完成修改。 <br><br>/proc文件系统中网络参数在/proc/sys/net/ipv4/目录下，<br>包含的是和tcp/ip协议相关的各种参数，下面我们就对这些<br>网络参数加以详细的说明。 <br><br>ip_forward  参数类型：BOOLEAN <br>0 - 关闭(默认值) <br>not 0 - 打开ip转发 <br><br>在网络本地接口之间转发数据报。该参数非常特殊，对该<br>参数的修改将导致其它所有相关配置参数恢复其默认值<br>(对于主机参阅RFC1122，对于路由器参见RFC1812) <br><br>ip_default_ttl 参数类型：INTEGER <br>默认值为 64 。表示IP数据报的Time To Live值。 <br><br>ip_no_pmtu_disc 参数类型：BOOLEAN <br>关闭路径MTU探测，默认值为FALSE <br><br>ipfrag_high_thresh  参数类型：整型 <br>用来组装分段的IP包的最大内存量。当ipfrag_high_thresh<br>数量的内存被分配来用来组装IP包，则IP分片处理器将丢弃<br>数据报直到ipfrag_low_thresh数量的内存被用来组装IP包。 <br><br>ipfrag_low_thresh 参数类型：整型 <br>参见ipfrag_high_thresh。 <br><br>ipfrag_time 参数类型：整型 <br>保存一个IP分片在内存中的时间。 <br><br>inet_peer_threshold  参数类型：整型 <br>INET对端存储器某个合适值，当超过该阀值条目将被丢弃。<br>该阀值同样决定生存时间以及废物收集通过的时间间隔。<br>条目越多，存活期越低，GC 间隔越短 <br><br>inet_peer_minttl  参数类型：整型 <br>条目的最低存活期。在重组端必须要有足够的碎片(fragment)<br>存活期。这个最低存活期必须保证缓冲池容积是否少于 <br>inet_peer_threshold。该值以 jiffies为单位测量。 <br><br>inet_peer_maxttl  参数类型：整型 <br>条目的最大存活期。在此期限到达之后，如果缓冲池没有耗尽<br>压力的话(例如，缓冲池中的条目数目非常少)，不使用的条目<br>将会超时。该值以 jiffies为单位测量。 <br><br>inet_peer_gc_mintime  参数类型：整型 <br>废物收集(GC)通过的最短间隔。这个间隔会影响到缓冲池中<br>内存的高压力。 该值以 jiffies为单位测量。 <br><br>inet_peer_gc_maxtime  参数类型：整型 <br>废物收集(GC)通过的最大间隔，这个间隔会影响到缓冲池中<br>内存的低压力。 该值以 jiffies为单位测量。 <br><br>tcp_syn_retries  参数类型：整型 <br>对于一个新建连接，内核要发送多少个 SYN 连接请求才决<br>定放弃。不应该大于255，默认值是5，对应于180秒左右。 <br><br>tcp_synack_retries  参数类型：整型 <br>对于远端的连接请求SYN，内核会发送SYN ＋ ACK数据报，<br>以确认收到上一个 SYN连接请求包。这是所谓的三次握手<br>( threeway handshake)机制的第二个步骤。这里决定内<br>核在放弃连接之前所送出的 SYN+ACK 数目。 <br><br>tcp_keepalive_time  参数类型：整型 <br>当keepalive打开的情况下，TCP发送keepalive消息的<br>频率，默认值是2个小时。 <br><br>tcp_keepalive_probes 参数类型：整型 <br>TCP发送keepalive探测以确定该连接已经断开的次数，默认值是9。 <br><br>tcp_keepalive_interval  参数类型：整型 <br>探测消息发送的频率，乘以tcp_keepalive_probes就得到对于从<br>开始探测以来没有响应的连接杀除的时间。默认值为75秒，也就<br>是没有活动的连接将在大约11分钟以后将被丢弃。 <br><br>tcp_retries1  参数类型：整型 <br>当出现可疑情况而必须向网络层报告这个可疑状况之前，需要<br>进行多少次重试。最低的 RFC 数值是 3 ，这也是默认值，<br>根据RTO的值大约在3秒 - 8分钟之间。 <br><br>tcp_retries2  参数类型：整型 <br>在丢弃激活的TCP连接之前，需要进行多少次重试。RFC1122规定，<br>该值必须大于100秒。默认值为15，根据RTO的值来决定，<br>相当于13-30分钟， <br><br>tcp_orphan_retries  参数类型：整型 <br>在近端丢弃TCP连接之前，要进行多少次重试。默认值是 7 个，<br>相当于 50秒 - 16分钟，视 RTO 而定。如果您的系统是负载很大<br>的web服务器，那么也许需要降低该值，这类 sockets 可能会耗费<br>大量的资源。另外参的考 tcp_max_orphans 。 <br><br>tcp_fin_timeout  参数类型：整型 <br>对于本端断开的socket连接，TCP保持在FIN-WAIT-2状态的时间。<br>对方可能会断开连接或一直不结束连接或不可预料的进程死亡。<br>默认值为 60 秒。过去在2.2版本的内核中是 180 秒。您可以<br>设置该值，但需要注意，如果您的机器为负载很重的web服务器，<br>您可能要冒内存被大量无效数据报填满的风险，FIN-WAIT-2 <br>sockets 的危险性低于 FIN-WAIT-1 ，因为它们最多只吃 1.5K <br>的内存，但是它们存在时间更长。另外参考 tcp_max_orphans。   <br><br>tcp_max_tw_buckets  参数类型：整型 <br>系统在同时所处理的最大timewait sockets 数目。如果超过<br>此数的话，time-wait socket 会被立即砍除并且显示警告信息。<br>之所以要设定这个限制，纯粹为了抵御那些简单的 DoS 攻击，<br>千万不要人为的降低这个限制，不过，如果网络条件需要比<br>默认值更多，则可以提高它(或许还要增加内存)。   <br><br>tcp_tw_recycle  参数类型：布尔 <br>打开快速 TIME-WAIT sockets 回收。默认值是1。除非得到<br>技术专家的建议或要求，请不要随意修改这个值。 <br><br>tcp_max_orphans  参数类型：整型 <br>系统所能处理不属于任何进程的TCP sockets最大数量。假如<br>超过这个数量，那么不属于任何进程的连接会被立即reset，<br>并同时显示警告信息。之所以要设定这个限制，纯粹为了抵御<br>那些简单的 DoS 攻击，千万不要依赖这个或是人为的降低<br>这个限制 <br><br>tcp_abort_on_overflow  参数类型：布尔 <br>当守护进程太忙而不能接受新的连接，就象对方发送reset<br>消息，默认值是false。这意味着当溢出的原因是因为一个<br>偶然的猝发，那么连接将恢复状态。只有在你确信守护进程<br>真的不能完成连接请求时才打开该选项，该选项会影响客户<br>的使用。 <br><br>tcp_syncookies  参数类型：整型 <br>只有在内核编译时选择了CONFIG_SYNCOOKIES时才会发生作用。<br>当出现syn等候队列出现溢出时象对方发送syncookies。目的<br>是为了防止syn flood攻击。默认值是false。 <br><br>注意：该选项千万不能用于那些没有收到攻击的高负载服务器，<br>如果在日志中出现synflood消息，但是调查发现没有收到<br>synflood攻击，而是合法用户的连接负载过高的原因，<br>你应该调整其它参数来提高服务器性能。<br>参考: tcp_max_syn_backlog, tcp_synack_retries, <br>tcp_abort_on_overflow. <br><br>syncookie严重的违背TCP协议，不允许使用TCP扩展，<br>可能对某些服务导致严重的性能影响(如SMTP转发)。 <br><br>tcp_stdurg  参数类型：整型 <br>使用 TCP urg pointer 字段中的主机请求解释功能。<br>大部份的主机都使用老旧的 BSD解释，因此如果您在<br>&nbsp;Linux 打开它，或会导致不能和它们正确沟通。<br>默认值为为：FALSE <br><br>tcp_max_syn_backlog  参数类型：整型 <br>对于那些依然还未获得客户端确认的连接请求，需要<br>保存在队列中最大数目。对于超过 128Mb 内存的系统，<br>默认值是 1024 ，低于 128Mb 的则为 128。如果服务<br>器经常出现过载，可以尝试增加这个数字。警告！假如<br>您将此值设为大于 1024，最好修改 include/net/tcp.h<br>&nbsp;里面的 TCP_SYNQ_HSIZE ，以保持<br>&nbsp;TCP_SYNQ_HSIZE*16&lt;=tcp_max_syn_backlog ，<br>并且编进核心之内。 <br><br>tcp_window_scaling  参数类型：布尔 <br>正常来说，TCP/IP 可以接受最大到65535字节的 windows。<br>对于宽带网络，该值可能是不够的，通过调整该参数<br>有助于提高宽带服务器性能。 <br><br>tcp_timestamps  参数类型：布尔 <br>Timestamps 用在其它一些东西中，可以防范那些伪造的<br>&nbsp;sequence 号码。一条1G的宽带线路或许会重遇到带 <br>out-of-line数值的旧sequence 号码(假如它是由于上次<br>产生的)。Timestamp 会让它知道这是个 '旧封包'。 <br><br>tcp_sack  参数类型：布尔 <br>使用 Selective ACK，它可以用来查找特定的遗失的<br>数据报--- 因此有助于快速恢复状态。 <br><br>tcp_fack  参数类型：布尔 <br>打开FACK拥塞避免和快速重传功能。 <br><br>tcp_dsack  参数类型：布尔 <br>允许TCP发送"两个完全相同"的SACK。 <br><br>tcp_ecn  参数类型：布尔 <br>打开TCP的直接拥塞通告功能。 <br><br>tcp_reordering  参数类型：整型 <br>TCP流中重排序的数据报最大数量默认值是 3 。 <br><br>tcp_retrans_collapse  参数类型：布尔 <br>对于某些有bug的打印机提供针对其bug的兼容性。 <br><br>tcp_wmem - 三个整数的向量： min, default, max <br>min：为TCP socket预留用于发送缓冲的内存最小值。<br>每个tcp socket都可以在建议以后都可以使用它。<br>默认值为4K。 <br><br>default：为TCP socket预留用于发送缓冲的内存数量，<br>默认情况下该值会影响其它协议使用的net.core.wmem_default<br>&nbsp;值，一般要低于net.core.wmem_default的值。默认值为16K。 <br><br>max: 用于TCP socket发送缓冲的内存最大值。该值不会影响<br>net.core.wmem_max，今天选择参数SO_SNDBUF则不受该值影响。<br>默认值为128K。 <br><br>tcp_rmem - 三个整数的向量： min, default, max <br>min：为TCP socket预留用于接收缓冲的内存数量，即使在内存<br>出现紧张情况下tcp socket都至少会有这么多数量的内存用于<br>接收缓冲，默认值为8K。 <br><br>default：为TCP socket预留用于接收缓冲的内存数量，默认<br>情况下该值影响其它协议使用的 net.core.wmem_default 值。<br>该值决定了在tcp_adv_win_scale、tcp_app_win和tcp_app_win:0<br>是默认值情况下，tcp 窗口大小为65535。 <br><br>max：用于TCP socket接收缓冲的内存最大值。该值不会影响 <br>net.core.wmem_max，今天选择参数 SO_SNDBUF则不受该值影响。<br>默认值为 128K。默认值为87380*2 bytes。 <br><br>tcp_mem - 三个整数的向量： low, pressure, high <br>low：当TCP使用了低于该值的内存页面数时，TCP不会考虑释放内存。 <br><br>pressure：当TCP使用了超过该值的内存页面数量时，TCP试图稳定<br>其内存使用，进入pressure模式，当内存消耗低于low值时则退出<br>pressure状态。 <br><br>high：允许所有tcp sockets用于排队缓冲数据报的页面量。 <br><br>一般情况下这些值是在系统启动时根据系统内存数量计算得到的。 <br><br>tcp_app_win - 整数 <br><br>保留max(window/2^tcp_app_win, mss)数量的窗口由于应用缓冲。<br>当为0时表示不需要缓冲。默认值是31。 <br><br>tcp_adv_win_scale - 整数 <br>计算缓冲开销bytes/2^tcp_adv_win_scale(如果tcp_adv_win_scale &gt; 0)<br>或者bytes-bytes/2^(-tcp_adv_win_scale)<br>(如果tcp_adv_win_scale &lt;= 0)，默认值为2。 <br><br>ip_local_port_range - 两个整数 <br>定于TCP和UDP使用的本地端口范围，第一个数是开始，<br>第二个数是最后端口号，默认值依赖于系统中可用的<br>内存数： <br>&gt; 128Mb 32768-61000 <br>&lt; 128Mb 1024-4999 or even less. <br>该值决定了活动连接的数量，也就是系统可以并发的连接数 <br><br>icmp_echo_ignore_all - 布尔类型 <br>icmp_echo_ignore_broadcasts - 布尔类型 <br>如果任何一个设置为true(&gt;0)则系统将忽略所有发送给自己<br>的ICMP ECHO请求或那些广播地址的请求。 <br><br>icmp_destunreach_rate - 整数 <br>icmp_paramprob_rate - 整数 <br>icmp_timeexceed_rate - 整数 <br>icmp_echoreply_rate - 整数(not enabled per default) <br>限制发向特定目标的ICMP数据报的最大速率。0表示没有<br>任何限制，否则表示jiffies数据单位中允许发送的个数。 <br><br>icmp_ignore_bogus_error_responses - 布尔类型 <br>某些路由器违背RFC1122标准，其对广播帧发送伪造的响应<br>来应答。这种违背行为通常会被以告警的方式记录在系统<br>日志中。如果该选项设置为True，内核不会记录这种警告<br>信息。默认值为False。 <br><br>(1) Jiffie: 内核使用的内部时间单位，在i386系统上<br>大小为1/100s，在Alpha中为1/1024S。<br>在/usr/include/asm/param.h中的HZ定义有特定系统的值。 <br><br>conf/interface/*: <br>conf/all/*是特定的，用来修改所有接口的设置，<br>is special and changes the settings for all interfaces. <br>Change special settings per interface. <br><br>log_martians - 布尔类型 <br>记录带有不允许的地址的数据报到内核日志中。 <br><br>accept_redirects - 布尔类型 <br>收发接收ICMP重定向消息。对于主机来说默认为True，<br>对于用作路由器时默认值为False。 <br><br>forwarding - 布尔类型 <br>在该接口打开转发功能 <br><br>mc_forwarding - 布尔类型 <br>是否进行多播路由。只有内核编译有CONFIG_MROUTE<br>并且有路由服务程序在运行该参数才有效。 <br><br>proxy_arp - 布尔类型 <br>打开proxy arp功能。 <br><br>shared_media - 布尔类型 <br>发送(路由器)或接收(主机) RFC1620 共享媒体重定向。<br>覆盖ip_secure_redirects的值。默认为True。 <br><br>secure_redirects - 布尔类型 <br>仅仅接收发给默认网关列表中网关的ICMP重定向消息，<br>默认值是TRUE。 <br><br>send_redirects - 布尔类型 <br>如果是router，发送重定向消息，默认值是TRUE <br><br>bootp_relay - 布尔类型 <br>接收源地址为0.b.c.d，目的地址不是本机的数据报。<br>用来支持BOOTP转发服务进程，该进程将捕获并转发该包。<br>默认为False，目前还没有实现。 <br><br>accept_source_route - 布尔类型 <br>接收带有SRR选项的数据报。对于主机来说默认为False，<br>对于用作路由器时默认值为True。 <br><br>rp_filter  参数类型 <br>1 - 通过反向路径回溯进行源地址验证(在RFC1812中定义)。<br>对于单穴主机和stub网络路由器推荐使用该选项。 <br>0 - 不通过反向路径回溯进行源地址验证。 <br>默认值为0。某些发布在启动时自动将其打开。</pre>
<br><br>
<pre>理解 Proc 文件系统 <br><br>--------------------------------------------------------------------------------<br> <br>作者：王旭 翻译 2004-10-05 18:25:55 来自：linuxfocus <br> <br><br>目录: <br>/proc --- 一个虚拟文件系统 <br>加载 proc 文件系统 <br>察看 /proc 的文件 <br>得到有用的系统/内核信息 <br>有关运行中的进程的信息 <br>通过 /proc 与内核交互 <br>结论 <br>参考文献<br><br>  摘要: <br><br><br>Linux 内核提供了一种通过 /proc 文件系统，在运行时访问<br>内核内部数据结构、改变内核设置的机制。尽管在各种硬件<br>平台上的 Linux 系统的 /proc 文件系统的基本概念都是<br>相同的，但本文只讨论基于 intel x86 架构的 Linux <br>/proc 文件系统。 <br><br><br><br>_________________ _________________ _________________<br> <br>  <br>/proc --- 一个虚拟文件系统<br>/proc 文件系统是一种内核和内核模块用来向进程 (process) <br>发送信息的机制 (所以叫做 /proc)。这个伪文件系统让你可以<br>和内核内部数据结构进行交互，获取 有关进程的有用信息，<br>在运行中 (on the fly) 改变设置 (通过改变内核参数)。 <br>与其他文件系统不同，/proc 存在于内存之中而不是硬盘上。<br>如果你察看文件 /proc/mounts (和 mount 命令一样列出所有<br>已经加载的文件系统)，你会看到其中 一行是这样的： <br><br><br><br>grep proc /proc/mounts<br>/proc /proc proc rw 0 0<br><br>/proc 由内核控制，没有承载 /proc 的设备。因为 /proc <br>主要存放由内核控制的状态信息，所以大部分这些信息的<br>逻辑位置位于内核控制的内存。对 /proc 进行一次 'ls -l'<br>可以看到大部分文件都是 0 字节大的；不过察看这些文件的<br>时候，确实可以看到一些信息。这怎么可能？这是因为 /proc<br>文件系统和其他常规的文件系统一样把自己注册到虚拟文件<br>系统层 (VFS) 了。然而，直到当 VFS 调用它，请求文件、<br>目录的 i-node 的时候，/proc 文件系统才根据内核中的信息<br>建立相应的文件和目录。 <br><br>  <br>加载 proc 文件系统<br>如果系统中还没有加载 proc 文件系统，可以通过如下命令<br>加载 proc 文件系统： <br><br><br>mount -t proc proc /proc <br><br>上述命令将成功加载你的 proc 文件系统。更多细节请阅读<br>&nbsp;mount 命令的 man page。 <br><br>  <br>察看 /proc 的文件<br>/proc 的文件可以用于访问有关内核的状态、计算机的属性、<br>正在运行的进程的状态等信息。大部分 /proc 中的文件和<br>目录提供系统物理环境最新的信息。尽管 /proc 中的文件<br>是虚拟的，但它们仍可以使用任何文件编辑器或像'more', <br>'less'或 'cat'这样的程序来查看。当编辑程序试图打开<br>一个虚拟文件时，这个文件就通过内核中的信息被凭空地 <br>(on the fly) 创建了。这是一些我从我的系统中得到的<br>一些有趣结果： <br><br>$ ls -l /proc/cpuinfo<br>-r--r--r-- 1 root root 0 Dec 25 11:01 /proc/cpuinfo<br><br>$ file /proc/cpuinfo<br>/proc/cpuinfo: empty<br><br>$ cat /proc/cpuinfo<br><br>processor       : 0<br>vendor_id       : GenuineIntel<br>cpu family      : 6<br>model           : 8<br>model name      : Pentium III (Coppermine)<br>stepping        : 6<br>cpu MHz         : 1000.119<br>cache size      : 256 KB<br>fdiv_bug        : no<br>hlt_bug         : no<br>sep_bug         : no<br>f00f_bug        : no<br>coma_bug        : no<br>fpu             : yes<br>fpu_exception   : yes<br>cpuid level     : 2<br>wp              : yes<br>flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca<br>cmov pat pse36 mmx fxsr xmm<br>bogomips        : 1998.85<br><br>processor       : 3<br>vendor_id       : GenuineIntel<br>cpu family      : 6<br>model           : 8<br>model name      : Pentium III (Coppermine)<br>stepping        : 6<br>cpu MHz         : 1000.119<br>cache size      : 256 KB<br>fdiv_bug        : no<br>hlt_bug         : no<br>sep_bug         : no<br>f00f_bug        : no<br>coma_bug        : no<br>fpu             : yes<br>fpu_exception   : yes<br>cpuid level     : 2<br>wp              : yes<br>flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca<br>cmov pat pse36 mmx fxsr xmm<br>bogomips        : 1992.29<br><br><br>这是一个从双 CPU 的系统中得到的结果，上述大部分的信息<br>十分清楚地给出了这个系统的有用的硬件信息。有些 /proc <br>的文件是经过编码的，不同的工具可以被用来解释这些编码<br>过的信息并输出成可读的形式。这样的工具包括：'top',<br>&nbsp;'ps', 'apm' 等。 <br><br><br>  <br>得到有用的系统/内核信息<br><br>proc 文件系统可以被用于收集有用的关于系统和运行中的内<br>核的信息。下面是一些重要的文件： <br><br>/proc/cpuinfo - CPU 的信息 (型号, 家族, 缓存大小等) <br>/proc/meminfo - 物理内存、交换空间等的信息 <br>/proc/mounts - 已加载的文件系统的列表 <br>/proc/devices - 可用设备的列表 <br>/proc/filesystems - 被支持的文件系统 <br>/proc/modules - 已加载的模块 <br>/proc/version - 内核版本 <br>/proc/cmdline - 系统启动时输入的内核命令行参数 <br>proc 中的文件远不止上面列出的这么多。想要进一步了解<br>的读者可以对 /proc 的每一个文件都'more'一下或读参考<br>文献[1]获取更多的有关 /proc 目录中的文件的信息。我<br>建议使用'more'而不是'cat'，除非你知道这个文件很小，<br>因为有些文件 (比如 kcore) 可能会非常长。 <br><br>  <br>有关运行中的进程的信息<br>/proc 文件系统可以用于获取运行中的进程的信息。在 <br>/proc 中有一些编号的子目录。每个编号的目录对应<br>一个进程 id (PID)。这样，每一个运行中的进程 /proc <br>中都有一个用它的 PID 命名的目录。这些子目录中包含<br>可以提供有关进程的状态和环境的重要细节信息的文件。<br>让我们试着查找一个运行中的进程。 <br><br>$ ps -aef | grep mozilla<br>root 32558 32425 8  22:53 pts/1  00:01:23  /usr/bin/mozilla<br><br>上述命令显示有一个正在运行的 mozilla 进程的 PID <br>是 32558。相对应的，/proc 中应该有一个名叫 32558 的目录<br><br><br>$ ls -l /proc/32558<br>total 0<br>-r--r--r--    1 root  root            0 Dec 25 22:59 cmdline<br>-r--r--r--    1 root  root            0 Dec 25 22:59 cpu<br>lrwxrwxrwx    1 root  root            0 Dec 25 22:59 cwd -&gt; /proc/<br>-r--------    1 root  root            0 Dec 25 22:59 environ<br>lrwxrwxrwx    1 root  root            0 Dec 25 22:59 exe -&gt; /usr/bin/mozilla*<br>dr-x------    2 root  root            0 Dec 25 22:59 fd/<br>-r--r--r--    1 root  root            0 Dec 25 22:59 maps<br>-rw-------    1 root  root            0 Dec 25 22:59 mem<br>-r--r--r--    1 root  root            0 Dec 25 22:59 mounts<br>lrwxrwxrwx    1 root  root            0 Dec 25 22:59 root -&gt; //<br>-r--r--r--    1 root  root            0 Dec 25 22:59 stat<br>-r--r--r--    1 root  root            0 Dec 25 22:59 statm<br>-r--r--r--    1 root  root            0 Dec 25 22:59 status<br><br>文件 "cmdline" 包含启动进程时调用的命令行。"envir" 进程<br>的环境变两。 "status" 是进程的状态信息，包括启动进程的<br>用户的用户ID (UID) 和组ID(GID) ，父进程ID (PPID)，还有<br>进程当前的状态，比如"Sleelping"和"Running"。每个进程的<br>目录都有几个符号链接，"cwd"是指向进程当前工作目录的符号<br>链接，"exe"指向运行的进程的可执行程序，"root"指向被这个<br>进程看作是根目录的目录 (通常是"/")。目录"fd"包含指向进程<br>使用的文件描述符的链接。 "cpu"仅在运行 SMP 内核时出现，<br>里面是按 CPU 划分的进程时间。 <br><br>/proc/self 是一个有趣的子目录，它使得程序可以方便地使用 <br>/proc 查找本进程地信息。/proc/self 是一个链接到 /proc <br>中访问 /proc 的进程所对应的 PID 的目录的符号链接。<br><br><br>  <br>通过 /proc 与内核交互<br><br>上面讨论的大部分 /proc 的文件是只读的。而实际上 /proc <br>文件系统通过 /proc 中可读写的文件提供了对内核的交互机制。<br>写这些文件可以改变内核的状态，因而要慎重改动这些文件。<br>/proc/sys 目录存放所有可读写的文件的目录，可以被用于改变<br>内核行为。<br><br>/proc/sys/kernel - 这个目录包含反通用内核行为的信息。<br>&nbsp;/proc/sys/kernel/{domainname, hostname} 存放着机器/网络<br>的域名和主机名。这些文件可以用于修改这些名字。<br><br><br><br>$ hostname<br>machinename.domainname.com<br><br>$ cat /proc/sys/kernel/domainname<br>domainname.com<br><br>$ cat /proc/sys/kernel/hostname<br>machinename<br><br>$ echo "new-machinename"  &gt; /proc/sys/kernel/hostname<br><br>$ hostname<br>new-machinename.domainname.com<br><br><br><br>这样，通过修改 /proc 文件系统中的文件，我们可以修改<br>主机名。很多其他可配置的文件存在于 /proc/sys/kernel/。<br>这里不可能列出所有这些文件，读者可以自己去这个目录<br>查看以得到更多细节信息。<br>另一个可配置的目录是 /proc/sys/net。这个目录中的文件<br>可以用于修改机器/网络的网络属性。比如，简单修改一个<br>文件，你可以在网络上瘾藏匿的计算机。<br><br><br>$ echo 1 &gt; /proc/sys/net/ipv4/icmp_echo_ignore_all<br><br>这将在网络上瘾藏你的机器，因为它不响应 icmp_echo。<br>主机将不会响应其他主机发出的 ping 查询。<br><br>$ ping machinename.domainname.com<br>no answer from machinename.domainname.com<br><br>要改回缺省设置，只要<br><br>$ echo 0 &gt; /proc/sys/net/ipv4/icmp_echo_ignore_all<br><br>/proc/sys 下还有许多其它可以用于改变内核属性。读者<br>可以通过参考文献 [1], [2] 获取更多信息。 <br><br>  <br>结论<br>/proc 文件系统提供了一个基于文件的 Linux 内部接口。<br>它可以用于确定系统的各种不同设备和进程的状态。对<br>他们进行配置。因而，理解和应用有关这个文件系统的<br>知识是理解你的 Linux 系统的关键。<br><br>参考文献<br>[1] 有关Linux proc 文件系统的文档位于: <br>/usr/src/linux/Documentation/filesystems/proc.txt<br>[2] RedHat Guide: The /proc File System: <br><a href="http://www.redhat.com/docs/manuals/linux/RHL-7.3-Manual/ref-guide/ch-proc.html" target="_blank">http://www.redhat.com/docs/manuals/linux/RHL-7.3-Manual/ref-guide/ch-proc.html</a> </pre>
from:<br><a href="http://www.cnblogs.com/huqingyu/archive/2005/04/03/131107.html">http://www.cnblogs.com/huqingyu/archive/2005/04/03/131107.html</a>
<br><a href="http://zhidao.baidu.com/question/8804458.html">http://zhidao.baidu.com/question/8804458.html
</a><br><br> <img src ="http://www.cppblog.com/beautykingdom/aggbug/114374.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-05-04 22:03 <a href="http://www.cppblog.com/beautykingdom/archive/2010/05/04/114374.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux下静/动态链接库编程实例</title><link>http://www.cppblog.com/beautykingdom/archive/2010/04/25/113497.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Sun, 25 Apr 2010 03:52:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/04/25/113497.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/113497.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/04/25/113497.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/113497.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/113497.html</trackback:ping><description><![CDATA[<span style="WIDOWS: 2; TEXT-TRANSFORM: none; TEXT-INDENT: 0px; BORDER-COLLAPSE: separate; FONT: medium Simsun; WHITE-SPACE: normal; ORPHANS: 2; LETTER-SPACING: normal; COLOR: rgb(0,0,0); WORD-SPACING: 0px; -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" class=Apple-style-span><span style="BORDER-COLLAPSE: collapse; FONT-FAMILY: song, Verdana; FONT-SIZE: 12px" class=Apple-style-span>今天由于要用到静态链接库,所以就学习了一下相关知识,总结如下:<br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana">静态链接库(一般命名为libxxx.a)就是很多.o文件的集合,在你的项目中如果有一个子模快,这个子模块只是给总控模块提供一个函数接口,那么你就可以考虑把这个子模快编译成静态链接库libxxx.a,然后在总控模块中编译的时候,只需-L包含链接库所在的目录,再-lxxx引用链接库就行.<br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana">当然,你也可以用动态链接库,具体的动态链接库创建和引用,做法和静态链接库大同小异,只是动态链接库是在程序执行的时候是动态的添加到内存的,所以可以实现进程之间的资源共享.<br style="FONT: 12px song, Verdana">另外动态链接库可以做到所有的函数本着&#8220;有需求才调入&#8221;的原则，于是大大节省了系统资源:也就是说什么时候或者什么情况下，链接载入哪个动态链接库函数,完全由程序员在程序代码中控制。这样,当你有一个相当大的工程，每次运行的时候，由于不同的操作需求，就只会有一小部分程序被载入内存。<br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana">具体给一个例子,先看一下工程的目录结构:<br style="FONT: 12px song, Verdana">$ ls -RF<br style="FONT: 12px song, Verdana">.:<br style="FONT: 12px song, Verdana">lib/&nbsp; main.c&nbsp; Makefile<br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana">./lib:<br style="FONT: 12px song, Verdana">Makefile.a&nbsp; Makefile.so&nbsp; string.h&nbsp; strlen.c&nbsp; strnlen.c<br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana">在工程主目录下有main.c主控程序,Makefile文件和lib目录<br style="FONT: 12px song, Verdana">lib目录下有string.h头文件,strlen.c和strnlen.c,这三个文件里的函数就是我们想生成的库函数<br style="FONT: 12px song, Verdana">Makefile.a生成静态链接库的makefile文件<br style="FONT: 12px song, Verdana">Makefile.so生成动态链接库的makefile文件<br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana">好,让我们看一看这些文件的具体内容:<br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana">头文件string.h，声明相关函数原形<br style="FONT: 12px song, Verdana">$cat lib/string.h<br style="FONT: 12px song, Verdana">
<table style="BORDER-COLLAPSE: collapse" border=1 cellSpacing=0 borderColor=#999999 cellPadding=0 width="95%" bgColor=#f1f1f1>
    <tbody>
        <tr style="FONT: 12px song, Verdana">
            <td style="FONT: 12px song, Verdana">
            <p style="MARGIN: 5px; FONT: 12px/18px song, Verdana"><code><span style="COLOR: rgb(0,0,0)"><span style="COLOR: rgb(0,0,255)">int</span><span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(255,0,0)">Strlen</span><span style="COLOR: rgb(0,0,204)">(</span><span style="COLOR: rgb(0,0,255)">char</span><span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,204)">*</span>pStr<span style="COLOR: rgb(0,0,204)">)</span><span style="COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana"><span style="COLOR: rgb(0,0,255)">int</span><span class=Apple-converted-space>&nbsp;</span>StrNlen<span style="COLOR: rgb(0,0,204)">(</span><span style="COLOR: rgb(0,0,255)">char</span><span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,204)">*</span>pStr<span style="COLOR: rgb(0,0,204)">,</span><span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,255)">unsigned</span><span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,255)">long</span><span class=Apple-converted-space>&nbsp;</span>ulMaxLen<span style="COLOR: rgb(0,0,204)">)</span><span style="COLOR: rgb(0,0,204)">;</span></span></code></p>
            </td>
        </tr>
    </tbody>
</table>
<br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana">strlen.c：函数Strlen的实现，获取给定字符串的长度<br style="FONT: 12px song, Verdana">$cat lib/strlen.c<br style="FONT: 12px song, Verdana">&nbsp;
<table style="BORDER-COLLAPSE: collapse" border=1 cellSpacing=0 borderColor=#999999 cellPadding=0 width="95%" bgColor=#f1f1f1>
    <tbody>
        <tr style="FONT: 12px song, Verdana">
            <td style="FONT: 12px song, Verdana">
            <p style="MARGIN: 5px; FONT: 12px/18px song, Verdana"><code><span style="COLOR: rgb(0,0,0)"><span style="COLOR: rgb(0,0,204)">#</span><span style="COLOR: rgb(255,0,0)">include</span><span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,204)">&lt;</span>stdio<span style="COLOR: rgb(0,0,204)">.</span>h<span style="COLOR: rgb(0,0,204)">&gt;</span><br style="FONT: 12px song, Verdana"><span style="COLOR: rgb(0,0,204)">#</span><span style="COLOR: rgb(255,0,0)">include</span><span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,204)">&lt;</span><span style="COLOR: rgb(255,0,0)">assert</span><span style="COLOR: rgb(0,0,204)">.</span>h<span style="COLOR: rgb(0,0,204)">&gt;</span><br style="FONT: 12px song, Verdana"><span style="COLOR: rgb(0,0,255)">int</span><span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(255,0,0)">Strlen</span><span style="COLOR: rgb(0,0,204)">(</span><span style="COLOR: rgb(0,0,255)">char</span><span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,204)">*</span>pStr<span style="COLOR: rgb(0,0,204)">)</span><br style="FONT: 12px song, Verdana"><span style="COLOR: rgb(0,0,204)">{</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,0,255)">unsigned</span><span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,255)">long</span><span class=Apple-converted-space>&nbsp;</span>ulLength<span style="COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(255,0,0)">assert</span><span style="COLOR: rgb(0,0,204)">(</span><span style="COLOR: rgb(255,0,0)">NULL</span><span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,204)">!</span><span style="COLOR: rgb(0,0,204)">=</span><span class=Apple-converted-space>&nbsp;</span>pStr<span style="COLOR: rgb(0,0,204)">)</span><span style="COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;ulLength<span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,204)">=</span><span class=Apple-converted-space>&nbsp;</span>0<span style="COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,0,255)">while</span><span style="COLOR: rgb(0,0,204)">(</span><span style="COLOR: rgb(0,0,204)">*</span>pStr<span style="COLOR: rgb(0,0,204)">+</span><span style="COLOR: rgb(0,0,204)">+</span><span style="COLOR: rgb(0,0,204)">)</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,0,204)">{</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ulLength<span style="COLOR: rgb(0,0,204)">+</span><span style="COLOR: rgb(0,0,204)">+</span><span style="COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,0,204)">}</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,0,255)">return</span><span class=Apple-converted-space>&nbsp;</span>ulLength<span style="COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana"><span style="COLOR: rgb(0,0,204)">}</span></span></code></p>
            </td>
        </tr>
    </tbody>
</table>
<br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana">strnlen.c：函数StrNlen的实现，获取给定字符串的长度，如果输入字符串的长度大于指定的最大长度，则返回最大长度，否者返回字符串的实际长度<br style="FONT: 12px song, Verdana">$cat lib/strnlen.c<br style="FONT: 12px song, Verdana">
<table style="BORDER-COLLAPSE: collapse" border=1 cellSpacing=0 borderColor=#999999 cellPadding=0 width="95%" bgColor=#f1f1f1>
    <tbody>
        <tr style="FONT: 12px song, Verdana">
            <td style="FONT: 12px song, Verdana">
            <p style="MARGIN: 5px; FONT: 12px/18px song, Verdana"><code><span style="COLOR: rgb(0,0,0)"><span style="COLOR: rgb(0,0,204)">#</span><span style="COLOR: rgb(255,0,0)">include</span><span style="COLOR: rgb(0,0,204)">&lt;</span>stdio<span style="COLOR: rgb(0,0,204)">.</span>h<span style="COLOR: rgb(0,0,204)">&gt;</span><br style="FONT: 12px song, Verdana"><span style="COLOR: rgb(0,0,204)">#</span><span style="COLOR: rgb(255,0,0)">include</span><span style="COLOR: rgb(0,0,204)">&lt;</span><span style="COLOR: rgb(255,0,0)">assert</span><span style="COLOR: rgb(0,0,204)">.</span>h<span style="COLOR: rgb(0,0,204)">&gt;</span><br style="FONT: 12px song, Verdana"><span style="COLOR: rgb(0,0,255)">int</span><span class=Apple-converted-space>&nbsp;</span>StrNlen<span style="COLOR: rgb(0,0,204)">(</span><span style="COLOR: rgb(0,0,255)">char</span><span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,204)">*</span>pStr<span style="COLOR: rgb(0,0,204)">,</span><span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,255)">unsigned</span><span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,255)">long</span><span class=Apple-converted-space>&nbsp;</span>ulMaxLen<span style="COLOR: rgb(0,0,204)">)</span><br style="FONT: 12px song, Verdana"><span style="COLOR: rgb(0,0,204)">{</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,0,255)">unsigned</span><span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,255)">long</span><span class=Apple-converted-space>&nbsp;</span>ulLength<span style="COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(255,0,0)">assert</span><span style="COLOR: rgb(0,0,204)">(</span><span style="COLOR: rgb(255,0,0)">NULL</span><span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,204)">!</span><span style="COLOR: rgb(0,0,204)">=</span><span class=Apple-converted-space>&nbsp;</span>pStr<span style="COLOR: rgb(0,0,204)">)</span><span style="COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,0,255)">if</span><span style="COLOR: rgb(0,0,204)">(</span>ulMaxLen<span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,204)">&lt;</span><span style="COLOR: rgb(0,0,204)">=</span><span class=Apple-converted-space>&nbsp;</span>0<span style="COLOR: rgb(0,0,204)">)</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,0,204)">{</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(255,0,0)">printf</span><span style="COLOR: rgb(0,0,204)">(</span><span style="COLOR: rgb(255,0,255)">"Wrong Max Length!\n"</span><span style="COLOR: rgb(0,0,204)">)</span><span style="COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,0,255)">return</span><span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,204)">-</span>1<span style="COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,0,204)">}</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;ulLength<span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,204)">=</span><span class=Apple-converted-space>&nbsp;</span>0<span style="COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,0,255)">while</span><span style="COLOR: rgb(0,0,204)">(</span><span style="COLOR: rgb(0,0,204)">*</span>pStr<span style="COLOR: rgb(0,0,204)">+</span><span style="COLOR: rgb(0,0,204)">+</span><span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,204)">&amp;</span><span style="COLOR: rgb(0,0,204)">&amp;</span><span class=Apple-converted-space>&nbsp;</span>ulLength<span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,204)">&lt;</span><span class=Apple-converted-space>&nbsp;</span>ulMaxLen<span style="COLOR: rgb(0,0,204)">)</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,0,204)">{</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ulLength<span style="COLOR: rgb(0,0,204)">+</span><span style="COLOR: rgb(0,0,204)">+</span><span style="COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,0,204)">}</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,0,255)">return</span><span class=Apple-converted-space>&nbsp;</span>ulLength<span style="COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana"><span style="COLOR: rgb(0,0,204)">}</span></span></code></p>
            </td>
        </tr>
    </tbody>
</table>
<br style="FONT: 12px song, Verdana">这三个文件是在lib/目录下.<br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana">Makefile.a:生成静态链接库的makefile文件<br style="FONT: 12px song, Verdana">$ cat lib/Makefile.a<br style="FONT: 12px song, Verdana">
<table style="BORDER-COLLAPSE: collapse" border=1 cellSpacing=0 borderColor=#999999 cellPadding=0 width="95%" bgColor=#f1f1f1>
    <tbody>
        <tr style="FONT: 12px song, Verdana">
            <td style="FONT: 12px song, Verdana">
            <p style="MARGIN: 5px; FONT: 12px/18px song, Verdana"><code><span style="COLOR: rgb(0,0,0)">libstr<span style="COLOR: rgb(0,0,204)">.</span>a<span style="COLOR: rgb(0,0,204)">:</span><span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(255,0,0)">strlen</span><span style="COLOR: rgb(0,0,204)">.</span>o strnlen<span style="COLOR: rgb(0,0,204)">.</span>o<br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;$<span style="COLOR: rgb(0,0,204)">(</span>AR<span style="COLOR: rgb(0,0,204)">)</span><span class=Apple-converted-space>&nbsp;</span>r $@ $^<br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;$<span style="COLOR: rgb(0,0,204)">(</span>RM<span style="COLOR: rgb(0,0,204)">)</span><span class=Apple-converted-space>&nbsp;</span>$^<br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana"><span style="COLOR: rgb(0,0,204)">.</span>PHONY<span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,204)">:</span><span class=Apple-converted-space>&nbsp;</span>clean<br style="FONT: 12px song, Verdana">clean<span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,204)">:</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;rm<span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,204)">-</span>f libstr<span style="COLOR: rgb(0,0,204)">.</span>a</span></code></p>
            </td>
        </tr>
    </tbody>
</table>
<br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana">Makefile.so:生成动态链接库的makefile文件<br style="FONT: 12px song, Verdana">$ cat Makefile.so<span class=Apple-converted-space>&nbsp;</span><br style="FONT: 12px song, Verdana">
<table style="BORDER-COLLAPSE: collapse" border=1 cellSpacing=0 borderColor=#999999 cellPadding=0 width="95%" bgColor=#f1f1f1>
    <tbody>
        <tr style="FONT: 12px song, Verdana">
            <td style="FONT: 12px song, Verdana">
            <p style="MARGIN: 5px; FONT: 12px/18px song, Verdana"><code><span style="COLOR: rgb(0,0,0)">libstr<span style="COLOR: rgb(0,0,204)">.</span>so<span style="COLOR: rgb(0,0,204)">:</span><span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(255,0,0)">strlen</span><span style="COLOR: rgb(0,0,204)">.</span>o strnlen<span style="COLOR: rgb(0,0,204)">.</span>o<br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;gcc<span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,204)">-</span>fpic<span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,204)">-</span>shared<span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,204)">-</span>o $@ $^<br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;$<span style="COLOR: rgb(0,0,204)">(</span>RM<span style="COLOR: rgb(0,0,204)">)</span><span class=Apple-converted-space>&nbsp;</span>$^<br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana"><span style="COLOR: rgb(0,0,204)">.</span>PHONY<span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,204)">:</span><span class=Apple-converted-space>&nbsp;</span>clean<br style="FONT: 12px song, Verdana">clean<span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,204)">:</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;rm<span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,204)">-</span>f libstr<span style="COLOR: rgb(0,0,204)">.</span>so</span></code></p>
            </td>
        </tr>
    </tbody>
</table>
<br style="FONT: 12px song, Verdana">-fpic 使输出的对象模块是按照可重定位地址方式生成的<br style="FONT: 12px song, Verdana">-shared指定把对应的源文件生成对应的动态链接库文件libstr.so文件<br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana">main.c:总控程序<br style="FONT: 12px song, Verdana">
<table style="BORDER-COLLAPSE: collapse" border=1 cellSpacing=0 borderColor=#999999 cellPadding=0 width="95%" bgColor=#f1f1f1>
    <tbody>
        <tr style="FONT: 12px song, Verdana">
            <td style="FONT: 12px song, Verdana">
            <p style="MARGIN: 5px; FONT: 12px/18px song, Verdana"><code><span style="COLOR: rgb(0,0,0)"><span style="COLOR: rgb(0,0,204)">#</span><span style="COLOR: rgb(255,0,0)">include</span><span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,204)">&lt;</span>stdio<span style="COLOR: rgb(0,0,204)">.</span>h<span style="COLOR: rgb(0,0,204)">&gt;</span><br style="FONT: 12px song, Verdana"><span style="COLOR: rgb(0,0,204)">#</span><span style="COLOR: rgb(255,0,0)">include</span><span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(255,0,255)">"./lib/string.h"</span><span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(255,153,0)">//静态库对应函数的头文件<br style="FONT: 12px song, Verdana"></span><br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana"><span style="COLOR: rgb(0,0,255)">int</span><span class=Apple-converted-space>&nbsp;</span>main<span style="COLOR: rgb(0,0,204)">(</span><span style="COLOR: rgb(0,0,255)">int</span><span class=Apple-converted-space>&nbsp;</span>argc<span style="COLOR: rgb(0,0,204)">,</span><span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,255)">char</span><span style="COLOR: rgb(0,0,204)">*</span><span class=Apple-converted-space>&nbsp;</span>argv<span style="COLOR: rgb(0,0,204)">[</span><span style="COLOR: rgb(0,0,204)">]</span><span style="COLOR: rgb(0,0,204)">)</span><br style="FONT: 12px song, Verdana"><span style="COLOR: rgb(0,0,204)">{</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,0,255)">char</span><span class=Apple-converted-space>&nbsp;</span>str<span style="COLOR: rgb(0,0,204)">[</span><span style="COLOR: rgb(0,0,204)">]</span><span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,204)">=</span><span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,204)">{</span><span style="COLOR: rgb(255,0,255)">"hello world"</span><span style="COLOR: rgb(0,0,204)">}</span><span style="COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,0,255)">unsigned</span><span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,255)">long</span><span class=Apple-converted-space>&nbsp;</span>ulLength<span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,204)">=</span><span class=Apple-converted-space>&nbsp;</span>0<span style="COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(255,0,0)">printf</span><span style="COLOR: rgb(0,0,204)">(</span><span style="COLOR: rgb(255,0,255)">"The string is : %s\n"</span><span style="COLOR: rgb(0,0,204)">,</span><span class=Apple-converted-space>&nbsp;</span>str<span style="COLOR: rgb(0,0,204)">)</span><span style="COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;ulLength<span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,204)">=</span><span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(255,0,0)">Strlen</span><span style="COLOR: rgb(0,0,204)">(</span>str<span style="COLOR: rgb(0,0,204)">)</span><span style="COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(255,0,0)">printf</span><span style="COLOR: rgb(0,0,204)">(</span><span style="COLOR: rgb(255,0,255)">"The string length is : %d(use Strlen)\n"</span><span style="COLOR: rgb(0,0,204)">,</span><span class=Apple-converted-space>&nbsp;</span>ulLength<span style="COLOR: rgb(0,0,204)">)</span><span style="COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;ulLength<span class=Apple-converted-space>&nbsp;</span><span style="COLOR: rgb(0,0,204)">=</span><span class=Apple-converted-space>&nbsp;</span>StrNlen<span style="COLOR: rgb(0,0,204)">(</span>str<span style="COLOR: rgb(0,0,204)">,</span><span class=Apple-converted-space>&nbsp;</span>10<span style="COLOR: rgb(0,0,204)">)</span><span style="COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(255,0,0)">printf</span><span style="COLOR: rgb(0,0,204)">(</span><span style="COLOR: rgb(255,0,255)">"The string length is : %d(use StrNlen)\n"</span><span style="COLOR: rgb(0,0,204)">,</span><span class=Apple-converted-space>&nbsp;</span>ulLength<span style="COLOR: rgb(0,0,204)">)</span><span style="COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;<span style="COLOR: rgb(0,0,255)">return</span><span class=Apple-converted-space>&nbsp;</span>0<span style="COLOR: rgb(0,0,204)">;</span><br style="FONT: 12px song, Verdana"><span style="COLOR: rgb(0,0,204)">}</span></span></code></p>
            </td>
        </tr>
    </tbody>
</table>
<br style="FONT: 12px song, Verdana"><br style="FONT: 12px song, Verdana">总控Makefile<br style="FONT: 12px song, Verdana">$ cat Makefile<span class=Apple-converted-space>&nbsp;</span><br style="FONT: 12px song, Verdana">
<table style="BORDER-COLLAPSE: collapse" border=1 cellSpacing=0 borderColor=#999999 cellPadding=0 width="95%" bgColor=#f1f1f1>
    <tbody>
        <tr style="FONT: 12px song, Verdana">
            <td style="FONT: 12px song, Verdana">
            <p style="MARGIN: 5px; FONT: 12px/18px song, Verdana"><code><span style="COLOR: rgb(0,0,0)">&nbsp;CC = gcc<br>&nbsp;CFLAGS = -Wall -g<br>&nbsp;LIBPATH = -L./lib<br>&nbsp;LIB = -lstr<br>&nbsp;main: main.o<br>&nbsp;&nbsp;&nbsp;&nbsp;( cd ./lib&nbsp; &amp;&amp; make -f makefile.a ) || ( exit 1 )<br>&nbsp;&nbsp;&nbsp;#&nbsp;&nbsp; ( cd ./lib&nbsp; &amp;&amp; make -f makefile.a &amp;&amp; make -f makefile.so ) || ( exit 1 )<br>&nbsp;&nbsp;&nbsp;${CC} ${CFLAGS} -o $@ main.o ${LIBPATH} ${LIB}<br>&nbsp;.PHONY:clean<br>&nbsp;clean:<br>&nbsp;&nbsp;&nbsp;&nbsp;-rm -f main *.o<br>&nbsp;&nbsp;&nbsp;&nbsp;( cd ./lib &amp;&amp; make -f makefile.a clean &amp;&amp; make -f makefile.so clean ) || ( exit 1 )<br></span></code></p>
            </td>
        </tr>
    </tbody>
</table>
</span></span><span style="WIDOWS: 2; TEXT-TRANSFORM: none; TEXT-INDENT: 0px; BORDER-COLLAPSE: separate; FONT: medium Simsun; WHITE-SPACE: normal; ORPHANS: 2; LETTER-SPACING: normal; COLOR: rgb(0,0,0); WORD-SPACING: 0px; -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" class=Apple-style-span><span style="BORDER-COLLAPSE: collapse; FONT-FAMILY: song, Verdana; FONT-SIZE: 12px" class=Apple-style-span>
<p style="FONT: 12px song, Verdana"><br>动态链接库和静态链接库使用时唯一的区别是需要加入动态库的路径:<br style="FONT: 12px song, Verdana">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在程序运行期间，也需要告诉系统去哪里找你的动态链接库文件.在UNIX下是通过定义名为LD_LIBRARY_PATH 的环境变量来实现的.<br>只需将动态链接库的目录path赋值给此变量即可。为了让执行程序顺利找到动态库，有三种方法：<br style="FONT: 12px song, Verdana"><strong>1)把库拷贝到/usr/lib和/lib目录下.</strong><br style="FONT: 12px song, Verdana"><strong>2)在LD_LIBRARY_PATH环境变量中加上库所在路径.</strong>例如动态库libstr.so在/home/xulei/test/lib目录下,以bash为例,使用命令:<br style="FONT: 12px song, Verdana">$export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/xulei/test/lib<br style="FONT: 12px song, Verdana">在环境变量LD_LIBRARY_PATH后添加/home/xulei/test/lib<br style="FONT: 12px song, Verdana"><strong>3) 修改/etc/ld.so.conf文件,把库所在的路径加到文件末尾</strong><br style="FONT: 12px song, Verdana"><strong>然后</strong><strong><font color=#ff0000>sudo ldconfig</font></strong><br style="FONT: 12px song, Verdana">这样,加入的目录下的所有库文件都可见.</span></span></p>
<br><span style="WIDOWS: 2; TEXT-TRANSFORM: none; TEXT-INDENT: 0px; BORDER-COLLAPSE: separate; FONT: medium Simsun; WHITE-SPACE: normal; ORPHANS: 2; LETTER-SPACING: normal; COLOR: rgb(0,0,0); WORD-SPACING: 0px; -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" class=Apple-style-span><span style="BORDER-COLLAPSE: collapse; FONT-FAMILY: song, Verdana; FONT-SIZE: 12px" class=Apple-style-span>reference:<br style="FONT: 12px song, Verdana">linux静态链接库与动态链接库<a style="COLOR: rgb(51,0,255); TEXT-DECORATION: underline" href="http://blog.chinaunix.net/u2/76292/showart_1274181.html" target=_blank>http://blog.chinaunix.net/u2/76292/showart_1274181.html</a><br style="FONT: 12px song, Verdana">Linux静态/动态链接库的创建和使用<a style="COLOR: rgb(51,0,255); TEXT-DECORATION: underline" href="http://dev.csdn.net/article/84/84562.shtm" target=_blank>http://dev.csdn.net/article/84/84562.shtm</a><br>from：<br><a href="http://blog.chinaunix.net/u2/86590/showart.php?id=2138220"><u><font color=#810081 size=3 face="Times New Roman">http://blog.chinaunix.net/u2/86590/showart.php?id=2138220</font></u></a></span></span>
<img src ="http://www.cppblog.com/beautykingdom/aggbug/113497.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-04-25 11:52 <a href="http://www.cppblog.com/beautykingdom/archive/2010/04/25/113497.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>  Linux下C语言历遍目录</title><link>http://www.cppblog.com/beautykingdom/archive/2010/04/14/112595.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Wed, 14 Apr 2010 15:23:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/04/14/112595.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/112595.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/04/14/112595.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/112595.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/112595.html</trackback:ping><description><![CDATA[<p>LINUX下用C语言历遍目录 C语言列出目录2007-04-06 21:02功能：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Linux下C语言目录历遍 (读取目录)</p>
<p>作者：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 小徐</p>
<p>QQ:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 339534039</p>
<p>转载请注明出处 </p>
<p>呵呵，LINUX下历遍目录的方法一般是这样的</p>
<p>打开目录-》读取-》关闭目录</p>
<p>相关函数是</p>
<p>opendir -&gt; readdir -&gt; closedir</p>
<p>&nbsp;</p>
<p>#include &lt;dirent.h&gt;</p>
<p>DIR *opendir(const char *dirname);</p>
<p>&nbsp;</p>
<p>#include &lt;dirent.h&gt;</p>
<p>struct dirent *readdir(DIR *dirp);</p>
<p>&nbsp;</p>
<p>#include &lt;dirent.h&gt;</p>
<p>int closedir(DIR *dirp);</p>
<p>&nbsp;</p>
<p>好了，三个函数都出来了呵呵，原型就是上面，给自己解释一下免得以后我自己忘了呵呵！我以经忘过好几回了，所以这次放上博客来</p>
<p>opendir用于打开目录，是类似于流的那种方式，返回一个指向DIR结构体的指针他的参数*dirname是一个字符数组或者字符串常量,</p>
<p>readdir函数用于读取目录，他只有一个参数，这个参数主opendir返回的结构体指针，或者叫句柄更容易理解些吧。这个函数也返回一个结构
体指针 dirent *</p>
<p>dirent的结构如下定义</p>
<p>&nbsp;&nbsp;&nbsp; struct dirent</p>
<p>&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long d_ino;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* inode number */</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; off_t d_off;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* offset to this dirent */</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned short d_reclen;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* length of this d_name */</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char d_name [NAME_MAX+1];&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* file name
(null-terminated) */</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>结构体中d_ino存放的是该文件的结点数目，什么是结点数目呢我也说不清楚了呵呵，查一下其它资料了</p>
<p>d_off 是文件在目录中的编移，具体是什么意思我也不是很明白，我很少用到它，其本上就是用到d_name short
d_reclen是这个文件的长度，需要注意的是这里的长度并不是指文件大小，因为大小和长度是2回事了，你可以用lseek将文件长度移得很长，但大小
其实还是那么大.最后一个元素就是我们要的了，文件名称！</p>
<p>写了一个实例:</p>
<p>&nbsp;</p>
<p>/**</p>
<p>* 功能：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Linux下C语言目录历遍 (读取目录)</p>
<p>* 作者：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 小徐</p>
<p>* 邮箱：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#120;&#106;&#116;&#100;&#121;&#56;&#56;&#56;&#64;&#49;&#54;&#51;&#46;&#99;&#111;&#109;">xjtdy888@163.com</a></p>
<p>* QQ:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 339534039</p>
<p>* 转载请注明出处 </p>
<p>*/</p>
<p>#include &lt;stdio.h&gt;</p>
<p>#include &lt;stdlib.h&gt;</p>
<p>#include &lt;sys/types.h&gt;</p>
<p>#include &lt;unistd.h&gt;</p>
<p>#include &lt;dirent.h&gt;</p>
<p>&nbsp;</p>
<p>void print_usage(void);</p>
<p>&nbsp;</p>
<p>void print_usage(void)</p>
<p>{</p>
<p>printf("Usage: test dirname\n");</p>
<p>}</p>
<p>&nbsp;</p>
<p>int main(int argc,char *argv[])</p>
<p>{</p>
<p>DIR * dp;</p>
<p>struct dirent *filename;</p>
<p>&nbsp;</p>
<p>if (argc &lt; 2)</p>
<p>{</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print_usage();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit(1);</p>
<p>}</p>
<p>&nbsp;</p>
<p>dp = opendir(argv[1]);</p>
<p>if (!dp)</p>
<p>{</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fprintf(stderr,"open directory error\n");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;</p>
<p>}</p>
<p>while (filename=readdir(dp))</p>
<p>{</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("filename:%-10s\td_info:%ld\t d_reclen:%us\n",</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
filename-&gt;d_name,filename-&gt;d_ino,filename-&gt;d_reclen); </p>
<p>}</p>
<p>closedir(dp);</p>
<p>return 0;</p>
<p>}</p>
<p>&nbsp;</p>
<p>将上面代码保存为readdir.c执行下面的命令进行编译测试</p>
<p>[root@phpos ~]# gcc readdir.c </p>
<p>[root@phpos ~]# ./a.out</p>
<p>Usage: test dirname</p>
<p>[root@phpos ~]# ./a.out /etc/samba/</p>
<p>filename:lmhosts&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_info:49296&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_reclen:24s</p>
<p>filename:smb.conf&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_info:49825&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_reclen:24s</p>
<p>filename:smbpasswd&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_info:49402&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_reclen:24s</p>
<p>filename:..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_info:47906&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_reclen:16s</p>
<p>filename:secrets.tdb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_info:49812&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_reclen:24s</p>
<p>filename:.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_info:49295&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_reclen:16s</p>
<p>filename:smbusers&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_info:49377&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_reclen:24s</p>
<p>[root@phpos ~]# ./a.out /var/</p>
<p>filename:preserve&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_info:31971&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_reclen:24s</p>
<p>filename:lock&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_info:31966&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_reclen:16s</p>
<p>filename:yp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_info:31976&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_reclen:16s</p>
<p>filename:empty&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_info:31962&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_reclen:24s</p>
<p>filename:run&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_info:31972&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_reclen:16s</p>
<p>filename:lib&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_info:31939&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_reclen:16s</p>
<p>filename:nis&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_info:31969&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_reclen:16s</p>
<p>filename:local&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_info:31965&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_reclen:24s</p>
<p>filename:spool&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_info:31973&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_reclen:24s</p>
<p>filename:tmp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_info:31941&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_reclen:16s</p>
<p>filename:opt&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_info:31970&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_reclen:16s</p>
<p>filename:log&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_info:31959&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_reclen:16s</p>
<p>filename:crash&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_info:31997&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_reclen:24s</p>
<p>filename:..&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_info:2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_reclen:16s</p>
<p>filename:account&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_info:32037&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_reclen:24s</p>
<p>filename:mail&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_info:31968&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_reclen:16s</p>
<p>filename:cache&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_info:31960&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_reclen:24s</p>
<p>filename:db&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_info:31961&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_reclen:16s</p>
<p>filename:.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_info:31938&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d_reclen:16s</p>
<p>[root@phpos ~]# </p>
<p>&nbsp;</p>
<p>转载地址：<a href="http://hi.baidu.com/phps/blog/item/92120fd1645fc9d2562c840a.html">http://hi.baidu.com/phps/blog/item/92120fd1645fc9d2562c840a.html</a></p>
<br><img src ="http://www.cppblog.com/beautykingdom/aggbug/112595.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-04-14 23:23 <a href="http://www.cppblog.com/beautykingdom/archive/2010/04/14/112595.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>fork时需要注意的问题</title><link>http://www.cppblog.com/beautykingdom/archive/2010/03/30/110971.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Tue, 30 Mar 2010 03:27:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/03/30/110971.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/110971.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/03/30/110971.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/110971.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/110971.html</trackback:ping><description><![CDATA[<p><span id="sample-permalink">转载请注明：http://www.coder4.com/index.php
/archives/151</span></p>
<p>首先特别感谢这篇文章给的启发！<br>
http://hi.baidu.com/%D3%EA%BA%E7%D1%F4/blog/item/6490202aaba49193023bf633.html<br>
对原作者表示敬意和膜拜！</p>
<p>	fork()之后,非阻塞（异步）等待子进程（回收僵尸）。<br>
fork()之后，子进程和父进程分叉执行，僵尸进程的产生是因为父进程没有给子进程&#8220;收尸&#8221;造成的，又可以根据危害程度分为下述两类：<br>
总体来说：当子进程结束之后，但父进程未结束之前，子进程将成为僵尸进程。<br>
（1）当子进程结束之后，但父进程未结束之前，子进程将成为僵尸进程，父进程结束后僵尸被init进程回收。<br>
（2）如果子进程结束了，但是父进程始终没有结束，那么这个僵尸将一直存在，而且随着exec，僵尸越来越多。<br>
如下面的代码，在父进程执行的5s内，子进程将为僵尸：</p>
<div class="syntaxhighlighter  cpp" id="highlighter_564838">
<div class="bar
">
<div class="toolbar"><a  href="http://www.coder4.com/archives/151#viewSource" class="item viewsource" style="width: 16px; height: 16px;" title="查看源代码">查看源代码</a>
<div class="item copyToClipboard"><embed id="highlighter_564838_clipboard" type="application/x-shockwave-flash" title="复制到剪贴板" allowscriptaccess="always" wmode="transparent" flashvars="highlighterId=highlighter_564838" menu="false" src="http://www.coder4.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter/scripts/clipboard.swf" width="16" height="16"></div>
<a  href="http://www.coder4.com/archives/151#printSource" class="item printsource" style="width: 16px; height: 16px;" title="打印">打印</a><a  href="http://www.coder4.com/archives/151#about" class="item about" style="width: 16px; height: 16px;" title="帮助">帮助</a></div>
</div>
<div class="lines">
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>1</code></td>
            <td class="content"><code class="cpp
            comments">/*</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line
alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>2</code></td>
            <td class="content"><code class="spaces">&nbsp;</code><code class="cpp comments">*
            main.cc</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>3</code></td>
            <td class="content"><code class="spaces">&nbsp;</code><code class="cpp comments">*</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>4</code></td>
            <td class="content"><code class="spaces">&nbsp;</code><code class="cpp comments">*&nbsp;
            Created on: 2009-12-3</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>5</code></td>
            <td class="content"><code class="spaces">&nbsp;</code><code class="cpp comments">*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            Author: liheyuan</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line
alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>6</code></td>
            <td class="content"><code class="spaces">&nbsp;</code><code class="cpp comments">*&nbsp;&nbsp;&nbsp;
            Describe:</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>7</code></td>
            <td class="content"><code class="spaces">&nbsp;</code><code class="cpp comments">*</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>8</code></td>
            <td class="content"><code class="spaces">&nbsp;</code><code class="cpp comments">*&nbsp;&nbsp;
            Last Date: 2009-12-3</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>9</code></td>
            <td class="content"><code class="spaces">&nbsp;</code><code class="cpp comments">*&nbsp;&nbsp;
            CopyRight: 2009 @ ICT LiHeyuan</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>10</code></td>
            <td class="content"><code class="spaces">&nbsp;</code><code class="cpp comments">*/</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>11</code></td>
            <td class="content">&nbsp;</td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>12</code></td>
            <td class="content"><code class="cpp
            preprocessor">#include &lt;stdio.h&gt;</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>13</code></td>
            <td class="content"><code class="cpp preprocessor">#include
            &lt;stdlib.h&gt;</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line
alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>14</code></td>
            <td class="content"><code class="cpp preprocessor">#include &lt;signal.h&gt;</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>15</code></td>
            <td class="content"><code class="cpp preprocessor">#include
            &lt;unistd.h&gt;</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line
alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>16</code></td>
            <td class="content">&nbsp;</td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>17</code></td>
            <td class="content"><code class="cpp
            color1 bold">int</code> <code class="cpp plain">main() {</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>18</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            comments">//子进程的pid</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>19</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp color1
            bold">int</code> <code class="cpp plain">c_pid;</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>20</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp color1
            bold">int</code> <code class="cpp plain">pid;</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>21</code></td>
            <td class="content">&nbsp;</td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>22</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp keyword bold">if</code> <code class="cpp plain">((pid = fork())) {</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>23</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            comments">//父进程</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line
alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>24</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            plain">c_pid = pid;</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>25</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            functions bold">printf</code><code class="cpp plain">(</code><code class="cpp string">"The child process is %d\n"</code><code class="cpp
            plain">, c_pid);</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line
alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>26</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            plain">sleep(5);</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line
alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>27</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            functions bold">exit</code><code class="cpp plain">(0);</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>28</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">}
            </code><code class="cpp keyword bold">else</code> <code class="cpp
            plain">{</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>29</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp comments">//子进程</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>30</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            functions bold">printf</code><code class="cpp plain">(</code><code class="cpp string">"I 'm a child.\n"</code><code class="cpp plain">);</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>31</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            functions bold">exit</code><code class="cpp plain">(0);</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>32</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">}</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>33</code></td>
            <td class="content"><code class="cpp plain">}</code></td>
        </tr>
    </tbody>
</table>
</div>
</div>
</div>
<p>如上面的代码，在父进程的5s内，子进程一直是僵尸！<br>
因此，需要对僵尸进程进行回收，传统的回收方法是，使用wait()函数，等待子进程，wait()是阻塞模式的，当子进程没有结束之前，wait一直等
待，不往下面的语句执行。</p>
<div class="syntaxhighlighter  cpp" id="highlighter_412447">
<div class="bar
">
<div class="toolbar"><a  href="http://www.coder4.com/archives/151#viewSource" class="item viewsource" style="width: 16px; height: 16px;" title="查看源代码">查看源代码</a>
<div class="item copyToClipboard"><embed id="highlighter_412447_clipboard" type="application/x-shockwave-flash" title="复制到剪贴板" allowscriptaccess="always" wmode="transparent" flashvars="highlighterId=highlighter_412447" menu="false" src="http://www.coder4.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter/scripts/clipboard.swf" width="16" height="16"></div>
<a  href="http://www.coder4.com/archives/151#printSource" class="item printsource" style="width: 16px; height: 16px;" title="打印">打印</a><a  href="http://www.coder4.com/archives/151#about" class="item about" style="width: 16px; height: 16px;" title="帮助">帮助</a></div>
</div>
<div class="lines">
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>1</code></td>
            <td class="content"><code class="cpp
            comments">/*</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line
alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>2</code></td>
            <td class="content"><code class="spaces">&nbsp;</code><code class="cpp comments">*
            main.cc</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>3</code></td>
            <td class="content"><code class="spaces">&nbsp;</code><code class="cpp comments">*</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>4</code></td>
            <td class="content"><code class="spaces">&nbsp;</code><code class="cpp comments">*&nbsp;
            Created on: 2009-12-3</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>5</code></td>
            <td class="content"><code class="spaces">&nbsp;</code><code class="cpp comments">*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            Author: liheyuan</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line
alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>6</code></td>
            <td class="content"><code class="spaces">&nbsp;</code><code class="cpp comments">*&nbsp;&nbsp;&nbsp;
            Describe:</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>7</code></td>
            <td class="content"><code class="spaces">&nbsp;</code><code class="cpp comments">*</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>8</code></td>
            <td class="content"><code class="spaces">&nbsp;</code><code class="cpp comments">*&nbsp;&nbsp;
            Last Date: 2009-12-3</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>9</code></td>
            <td class="content"><code class="spaces">&nbsp;</code><code class="cpp comments">*&nbsp;&nbsp;
            CopyRight: 2009 @ ICT LiHeyuan</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>10</code></td>
            <td class="content"><code class="spaces">&nbsp;</code><code class="cpp comments">*/</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>11</code></td>
            <td class="content">&nbsp;</td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>12</code></td>
            <td class="content"><code class="cpp
            preprocessor">#include &lt;stdio.h&gt;</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>13</code></td>
            <td class="content"><code class="cpp preprocessor">#include
            &lt;stdlib.h&gt;</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line
alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>14</code></td>
            <td class="content"><code class="cpp preprocessor">#include &lt;signal.h&gt;</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>15</code></td>
            <td class="content"><code class="cpp preprocessor">#include
            &lt;unistd.h&gt;</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line
alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>16</code></td>
            <td class="content"><code class="cpp preprocessor">#include
            &lt;sys/wait.h&gt;</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>17</code></td>
            <td class="content">&nbsp;</td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>18</code></td>
            <td class="content"><code class="cpp
            color1 bold">int</code> <code class="cpp plain">main() {</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>19</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            comments">//子进程的pid</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>20</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp color1
            bold">int</code> <code class="cpp plain">c_pid;</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>21</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp color1
            bold">int</code> <code class="cpp plain">pid;</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>22</code></td>
            <td class="content">&nbsp;</td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>23</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp keyword bold">if</code> <code class="cpp plain">((pid = fork())) {</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>24</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            comments">//父进程</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line
alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>25</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            plain">c_pid = pid;</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>26</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            functions bold">printf</code><code class="cpp plain">(</code><code class="cpp string">"The child process is %d\n"</code><code class="cpp
            plain">, c_pid);</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line
alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>27</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            comments">//阻塞等待子进程</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>28</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            color1 bold">int</code> <code class="cpp plain">status;</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>29</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            keyword bold">if</code> <code class="cpp plain">((pid =
            wait(&amp;status)) != -1 &amp;&amp; pid == c_pid) {</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>30</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp comments">//成功回收子进程</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>31</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp functions bold">printf</code><code class="cpp plain">(</code><code class="cpp string">"The child exit with %d\n"</code><code class="cpp
            plain">, WEXITSTATUS(status));</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>32</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp functions bold">fflush</code><code class="cpp plain">(stdin);</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>33</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            plain">} </code><code class="cpp keyword bold">else</code> <code class="cpp plain">{</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>34</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp functions bold">printf</code><code class="cpp plain">(</code><code class="cpp string">"wait() fail.\n"</code><code class="cpp plain">);</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>35</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            plain">}</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>36</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp functions bold">printf</code><code class="cpp plain">(</code><code class="cpp string">"Now , The child has
            been exit , and I will sleep.\n"</code><code class="cpp plain">);</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>37</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            plain">sleep(20);</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line
alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>38</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            functions bold">exit</code><code class="cpp plain">(0);</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>39</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">}
            </code><code class="cpp keyword bold">else</code> <code class="cpp
            plain">{</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>40</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp comments">//子进程</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>41</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            functions bold">printf</code><code class="cpp plain">(</code><code class="cpp string">"I 'm a child.\n"</code><code class="cpp plain">);</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>42</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            plain">sleep(5);</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line
alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>43</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            functions bold">exit</code><code class="cpp plain">(0);</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>44</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">}</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>45</code></td>
            <td class="content"><code class="cpp plain">}</code></td>
        </tr>
    </tbody>
</table>
</div>
</div>
</div>
<p><a  href="http://www.coder4.com/index.php/archives/151" style="color: white;">转载自：4号程序员</a></p>
<p>如上面的代码，在子进程执行5秒后，即被回收，在夫进程的20秒内，子进程已经被结束，不再是僵尸。<br>
但是这种利用wait()阻塞等待的方法也有一定的缺陷，那就是父进程必须等待子进程，无法做其他事情，如何非阻塞的等待子进程呢？<br>
man wait,查看NOTES章节，可以找到：<br>
子进程退出的时候，会发送SIGCHLD信号，默认的POSIX不响应，所以，我们只需要把处理SIGCHLD的函数自己实现就OK了，怎么作呢？<br>
signal用于设置处理信号量的规则（或跳转到的函数）</p>
<div class="syntaxhighlighter  cpp" id="highlighter_877614">
<div class="bar                ">
<div class="toolbar"><a  href="http://www.coder4.com/archives/151#viewSource" class="item
viewSource" style="width: 16px; height: 16px;" title="查看源代码">查看源代码</a>
<div class="item copyToClipboard"><embed id="highlighter_877614_clipboard" type="application/x-shockwave-flash" title="复制到剪贴板" allowscriptaccess="always" wmode="transparent" flashvars="highlighterId=highlighter_877614" menu="false" src="http://www.coder4.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter/scripts/clipboard.swf" width="16" height="16"></div>
<a  href="http://www.coder4.com/archives/151#printSource" class="item printsource" style="width: 16px; height: 16px;" title="打印">打印</a><a  href="http://www.coder4.com/archives/151#about" class="item about" style="width: 16px; height: 16px;" title="帮助">帮助</a></div>
</div>
<div class="lines">
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>1</code></td>
            <td class="content"><code class="cpp
            functions bold">signal</code><code class="cpp plain">(SIGCHLD,handler);</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>2</code></td>
            <td class="content"><code class="cpp keyword bold">void</code> <code class="cpp plain">handler(</code><code class="cpp color1 bold">int</code>
            <code class="cpp plain">num)</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>3</code></td>
            <td class="content"><code class="cpp plain">{</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>4</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            comments">//我接受到了SIGCHLD的信号啦</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>5</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp color1
            bold">int</code> <code class="cpp plain">status;</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>6</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp color1
            bold">int</code> <code class="cpp plain">pid =
            waitpid(-1,&amp;status,WNOHANG);</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>7</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            keyword bold">if</code><code class="cpp plain">(WIFEXITED(status))</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>8</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">{</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>9</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            functions bold">printf</code><code class="cpp plain">(</code><code class="cpp string">"The child exit with code %d"</code><code class="cpp
            plain">,WEXITSTATUS(status));</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>10</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">}</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>11</code></td>
            <td class="content"><code class="cpp plain">}</code></td>
        </tr>
    </tbody>
</table>
</div>
</div>
</div>
<p>&nbsp;</p>
<p>OK，全部代码如下，注意父进程不要再用wait阻塞啦！</p>
<div class="bar
">
<div class="toolbar"><a  href="http://www.coder4.com/archives/151#viewSource" class="item viewsource" style="width: 16px; height: 16px;" title="查看源代码">查看源代码</a>
<div class="item copyToClipboard"><embed id="highlighter_394419_clipboard" type="application/x-shockwave-flash" title="复制到剪贴板" allowscriptaccess="always" wmode="transparent" flashvars="highlighterId=highlighter_394419" menu="false" src="http://www.coder4.com/wp-content/plugins/syntaxhighlighter/syntaxhighlighter/scripts/clipboard.swf" width="16" height="16"></div>
<a  href="http://www.coder4.com/archives/151#printSource" class="item printsource" style="width: 16px; height: 16px;" title="打印">打印</a><a  href="http://www.coder4.com/archives/151#about" class="item about" style="width: 16px; height: 16px;" title="帮助">帮助</a></div>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>1</code></td>
            <td class="content"><code class="cpp
            comments">/*</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line
alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>2</code></td>
            <td class="content"><code class="spaces">&nbsp;</code><code class="cpp comments">*
            main.cc</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>3</code></td>
            <td class="content"><code class="spaces">&nbsp;</code><code class="cpp comments">*</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>4</code></td>
            <td class="content"><code class="spaces">&nbsp;</code><code class="cpp comments">*&nbsp;
            Created on: 2009-12-3</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>5</code></td>
            <td class="content"><code class="spaces">&nbsp;</code><code class="cpp comments">*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            Author: liheyuan</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line
alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>6</code></td>
            <td class="content"><code class="spaces">&nbsp;</code><code class="cpp comments">*&nbsp;&nbsp;&nbsp;
            Describe:</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>7</code></td>
            <td class="content"><code class="spaces">&nbsp;</code><code class="cpp comments">*</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>8</code></td>
            <td class="content"><code class="spaces">&nbsp;</code><code class="cpp comments">*&nbsp;&nbsp;
            Last Date: 2009-12-3</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>9</code></td>
            <td class="content"><code class="spaces">&nbsp;</code><code class="cpp comments">*&nbsp;&nbsp;
            CopyRight: 2009 @ ICT LiHeyuan</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>10</code></td>
            <td class="content"><code class="spaces">&nbsp;</code><code class="cpp comments">*/</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>11</code></td>
            <td class="content">&nbsp;</td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>12</code></td>
            <td class="content"><code class="cpp
            preprocessor">#include &lt;stdio.h&gt;</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>13</code></td>
            <td class="content"><code class="cpp preprocessor">#include
            &lt;stdlib.h&gt;</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line
alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>14</code></td>
            <td class="content"><code class="cpp preprocessor">#include &lt;signal.h&gt;</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>15</code></td>
            <td class="content"><code class="cpp preprocessor">#include
            &lt;unistd.h&gt;</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line
alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>16</code></td>
            <td class="content"><code class="cpp preprocessor">#include
            &lt;sys/wait.h&gt;</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>17</code></td>
            <td class="content">&nbsp;</td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>18</code></td>
            <td class="content"><code class="cpp
            keyword bold">void</code> <code class="cpp plain">handler(</code><code class="cpp color1 bold">int</code> <code class="cpp plain">num) {</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>19</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            comments">//我接受到了SIGCHLD的信号啦</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>20</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp color1
            bold">int</code> <code class="cpp plain">status;</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>21</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp color1
            bold">int</code> <code class="cpp plain">pid = waitpid(-1, &amp;status,
            WNOHANG);</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>22</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp keyword bold">if</code> <code class="cpp plain">(WIFEXITED(status)) {</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>23</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            functions bold">printf</code><code class="cpp plain">(</code><code class="cpp string">"The child %d exit with code %d\n"</code><code class="cpp plain">, pid, WEXITSTATUS(status));</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>24</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">}</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>25</code></td>
            <td class="content"><code class="cpp plain">}</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>26</code></td>
            <td class="content">&nbsp;</td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>27</code></td>
            <td class="content"><code class="cpp
            color1 bold">int</code> <code class="cpp plain">main() {</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>28</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            comments">//子进程的pid</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>29</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp color1
            bold">int</code> <code class="cpp plain">c_pid;</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>30</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp color1
            bold">int</code> <code class="cpp plain">pid;</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>31</code></td>
            <td class="content">&nbsp;</td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>32</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp functions bold">signal</code><code class="cpp plain">(SIGCHLD, handler);</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>33</code></td>
            <td class="content">&nbsp;</td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>34</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp keyword bold">if</code> <code class="cpp plain">((pid = fork())) {</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>35</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            comments">//父进程</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line
alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>36</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            plain">c_pid = pid;</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>37</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            functions bold">printf</code><code class="cpp plain">(</code><code class="cpp string">"The child process is %d\n"</code><code class="cpp
            plain">, c_pid);</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line
alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>38</code></td>
            <td class="content">&nbsp;</td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>39</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp comments">//父进程不用等待，做自己的事
            情吧～</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>40</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp keyword bold">for</code> <code class="cpp plain">(</code><code class="cpp color1 bold">int</code> <code class="cpp plain">i = 0; i &lt; 10; i++) {</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>41</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp functions bold">printf</code><code class="cpp plain">(</code><code class="cpp string">"Do parent things.\n"</code><code class="cpp plain">);</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>42</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">sleep(1);</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>43</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            plain">}</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>44</code></td>
            <td class="content">&nbsp;</td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>45</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            functions bold">exit</code><code class="cpp plain">(0);</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>46</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">}
            </code><code class="cpp keyword bold">else</code> <code class="cpp
            plain">{</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>47</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp comments">//子进程</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>48</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            functions bold">printf</code><code class="cpp plain">(</code><code class="cpp string">"I 'm a child.\n"</code><code class="cpp plain">);</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>49</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            plain">sleep(2);</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line
alt2">
<table>
    <tbody>
        <tr>
            <td class="number"><code>50</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp
            functions bold">exit</code><code class="cpp plain">(0);</code></td>
        </tr>
    </tbody>
</table>
</div>
<div class="line alt1">
<table>
    <tbody>
        <tr>
            <td class="number"><code>51</code></td>
            <td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="cpp plain">}</code></td>
        </tr>
    </tbody>
</table>
</div>
<table>
    <tbody>
        <tr>
            <td class="number"><code>52</code></td>
            <td class="content"><code class="cpp plain">}</code></td>
        </tr>
    </tbody>
</table>
<br><br><img src ="http://www.cppblog.com/beautykingdom/aggbug/110971.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-03-30 11:27 <a href="http://www.cppblog.com/beautykingdom/archive/2010/03/30/110971.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>process and thread属性读取</title><link>http://www.cppblog.com/beautykingdom/archive/2010/03/14/109680.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Sun, 14 Mar 2010 07:09:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/03/14/109680.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/109680.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/03/14/109680.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/109680.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/109680.html</trackback:ping><description><![CDATA[<code><span style="color: #000000;">process进程 <span style="color: #0000ff;">and</span> thread<br>
获取当前进程getpid<span style="color: #0000cc;">(</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">,</span>父进程getppid<span style="color: #0000cc;">(</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">,</span>当前用户ID，getuid<span style="color: #0000cc;">(</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">,</span> geteuid<span style="color: #0000cc;">(</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">,</span>组ID，getgid<span style="color: #0000cc;">(</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">,</span>getegid<span style="color: #0000cc;">(</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">,</span> all need head file <span style="color: #0000cc;">&lt;</span>unistd<span style="color: #0000cc;">.</span>h<span style="color: #0000cc;">&gt;</span><br>
getlogin<span style="color: #0000cc;">(</span><span style="color: #0000cc;">)</span>返回登录用户名<br>
example<span style="color: #0000cc;">:</span><br>
#<span style="color: #ff0000;">include</span> <span style="color: #0000cc;">&lt;</span>iostream<span style="color: #0000cc;">.</span>h<span style="color: #0000cc;">&gt;</span><br>
#<span style="color: #ff0000;">include</span> <span style="color: #0000cc;">&lt;</span>unistd<span style="color: #0000cc;">.</span>h<span style="color: #0000cc;">&gt;</span>  //getpid<span style="color: #0000cc;">(</span><span style="color: #0000cc;">)</span>
getppid<span style="color: #0000cc;">(</span><span style="color: #0000cc;">)</span><br>
<span style="color: #0000ff;">int</span> main<span style="color: #0000cc;">(</span><span style="color: #0000cc;">)</span><br>
{<br>
cout<span style="color: #0000cc;">&lt;</span><span style="color: #0000cc;">&lt;</span>getpid<span style="color: #0000cc;">(</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">&lt;</span><span style="color: #0000cc;">&lt;</span>endl<span style="color: #0000cc;">;</span> //current process ID<br>
cout<span style="color: #0000cc;">&lt;</span><span style="color: #0000cc;">&lt;</span>getppid<span style="color: #0000cc;">(</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">&lt;</span><span style="color: #0000cc;">&lt;</span>endl<span style="color: #0000cc;">;</span>  //parent process ID<br>
cout<span style="color: #0000cc;">&lt;</span><span style="color: #0000cc;">&lt;</span>getgid<span style="color: #0000cc;">(</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">&lt;</span><span style="color: #0000cc;">&lt;</span>endl<span style="color: #0000cc;">;</span>  //group process ID<br>
cout<span style="color: #0000cc;">&lt;</span><span style="color: #0000cc;">&lt;</span>getegid<span style="color: #0000cc;">(</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">&lt;</span><span style="color: #0000cc;">&lt;</span>endl<span style="color: #0000cc;">;</span>  //effective group process ID<br>
cout<span style="color: #0000cc;">&lt;</span><span style="color: #0000cc;">&lt;</span>getuid<span style="color: #0000cc;">(</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">&lt;</span><span style="color: #0000cc;">&lt;</span>endl<span style="color: #0000cc;">;</span>  //user process ID<br>
cout<span style="color: #0000cc;">&lt;</span><span style="color: #0000cc;">&lt;</span>geteuid<span style="color: #0000cc;">(</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">&lt;</span><span style="color: #0000cc;">&lt;</span>endl<span style="color: #0000cc;">;</span> //effective user process ID<br>
cout<span style="color: #0000cc;">&lt;</span><span style="color: #0000cc;">&lt;</span>getlogin<span style="color: #0000cc;">(</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">&lt;</span><span style="color: #0000cc;">&lt;</span>endl<span style="color: #0000cc;">;</span>  //getlogin<span style="color: #0000cc;">(</span><span style="color: #0000cc;">)</span>
return the login user <span style="color: #ff0000;">name</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
return 0<span style="color: #0000cc;">;</span><br>
}<br>
<br>
获取登录用户的个人信息，如用户名，当前目录，用户ID，组ID等<span style="color: #0000cc;">,</span>need
function <span style="color: #0000ff;">struct</span> passwd <span style="color: #0000cc;">*</span> getpwnam<span style="color: #0000cc;">(</span>const char <span style="color: #0000cc;">*</span><span style="color: #ff0000;">name</span><span style="color: #0000cc;">)</span><br>
如下面的例子<span style="color: #0000cc;">:</span><br>
/<span style="color: #0000cc;">*</span><br>
&nbsp;<span style="color: #0000cc;">*</span> getname<span style="color: #0000cc;">.</span>c <span style="color: #0000cc;">-</span> Get login names<br>
&nbsp;<span style="color: #0000cc;">*</span><span style="color: #0000cc;">/</span><br>
#<span style="color: #ff0000;">include</span> <span style="color: #0000cc;">&lt;</span>stdio<span style="color: #0000cc;">.</span>h<span style="color: #0000cc;">&gt;</span><br>
#<span style="color: #ff0000;">include</span> <span style="color: #0000cc;">&lt;</span>stdlib<span style="color: #0000cc;">.</span>h<span style="color: #0000cc;">&gt;</span><span style="color: #0000cc;">/</span><span style="color: #0000cc;">/</span>exit<span style="color: #0000cc;">(</span><span style="color: #0000cc;">)</span><br>
#<span style="color: #ff0000;">include</span> <span style="color: #0000cc;">&lt;</span>unistd<span style="color: #0000cc;">.</span>h<span style="color: #0000cc;">&gt;</span><span style="color: #0000cc;">/</span><span style="color: #0000cc;">/</span>getlogin<span style="color: #0000cc;">(</span><span style="color: #0000cc;">)</span><br>
#<span style="color: #ff0000;">include</span> <span style="color: #0000cc;">&lt;</span>pwd<span style="color: #0000cc;">.</span>h<span style="color: #0000cc;">&gt;</span>   //getpwnam<span style="color: #0000cc;">(</span><span style="color: #0000cc;">)</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
<span style="color: #0000ff;">int</span> main<span style="color: #0000cc;">(</span>void<span style="color: #0000cc;">)</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char <span style="color: #0000cc;">*</span>login<span style="color: #0000cc;">;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">struct</span> passwd <span style="color: #0000cc;">*</span>pentry<span style="color: #0000cc;">;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/<span style="color: #0000cc;">*</span> Get the login <span style="color: #ff0000;">name</span> <span style="color: #0000cc;">*</span><span style="color: #0000cc;">/</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">if</span><span style="color: #0000cc;">(</span><span style="color: #0000cc;">(</span>login <span style="color: #0000cc;">=</span>
getlogin<span style="color: #0000cc;">(</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">)</span> <span style="color: #0000cc;">=</span><span style="color: #0000cc;">=</span> NULL<span style="color: #0000cc;">)</span> { /<span style="color: #0000cc;">*</span> oops <span style="color: #0000cc;">*</span><span style="color: #0000cc;">/</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror<span style="color: #0000cc;">(</span><span style="color: #ff00ff;">"getlogin"</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit<span style="color: #0000cc;">(</span>EXIT_FAILURE<span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/<span style="color: #0000cc;">*</span> Get the password
entry <span style="color: #0000ff;">for</span> login <span style="color: #0000cc;">*</span><span style="color: #0000cc;">/</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">if</span><span style="color: #0000cc;">(</span><span style="color: #0000cc;">(</span>pentry <span style="color: #0000cc;">=</span>
getpwnam<span style="color: #0000cc;">(</span>login<span style="color: #0000cc;">)</span><span style="color: #0000cc;">)</span> <span style="color: #0000cc;">=</span><span style="color: #0000cc;">=</span> NULL<span style="color: #0000cc;">)</span> {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror<span style="color: #0000cc;">(</span><span style="color: #ff00ff;">"getpwnam"</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit<span style="color: #0000cc;">(</span>EXIT_FAILURE<span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/<span style="color: #0000cc;">*</span> Display the
password entry <span style="color: #0000cc;">*</span><span style="color: #0000cc;">/</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf<span style="color: #0000cc;">(</span><span style="color: #ff00ff;">"user name: %s\n"</span><span style="color: #0000cc;">,</span> pentry<span style="color: #0000cc;">-</span><span style="color: #0000cc;">&gt;</span>pw_name<span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf<span style="color: #0000cc;">(</span><span style="color: #ff00ff;">"UID          : %d\n"</span><span style="color: #0000cc;">,</span> pentry<span style="color: #0000cc;">-</span><span style="color: #0000cc;">&gt;</span>pw_uid<span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf<span style="color: #0000cc;">(</span><span style="color: #ff00ff;">"GID          : %d\n"</span><span style="color: #0000cc;">,</span> pentry<span style="color: #0000cc;">-</span><span style="color: #0000cc;">&gt;</span>pw_gid<span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf<span style="color: #0000cc;">(</span><span style="color: #ff00ff;">"gecos    : %s\n"</span><span style="color: #0000cc;">,</span> pentry<span style="color: #0000cc;">-</span><span style="color: #0000cc;">&gt;</span>pw_gecos<span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf<span style="color: #0000cc;">(</span><span style="color: #ff00ff;">"home dir : %s\n"</span><span style="color: #0000cc;">,</span> pentry<span style="color: #0000cc;">-</span><span style="color: #0000cc;">&gt;</span>pw_dir<span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf<span style="color: #0000cc;">(</span><span style="color: #ff00ff;">"shell    : %s\n"</span><span style="color: #0000cc;">,</span> pentry<span style="color: #0000cc;">-</span><span style="color: #0000cc;">&gt;</span>pw_shell<span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit<span style="color: #0000cc;">(</span>EXIT_SUCCESS<span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>
}<br>
<br>
system<span style="color: #0000cc;">(</span><span style="color: #0000cc;">)</span><br>
如果没有找到/bin/sh则返回127，成功返回0，出错返回<span style="color: #0000cc;">-</span>1<br>
example<span style="color: #0000cc;">:</span><br>
/<span style="color: #0000cc;">*</span><br>
&nbsp;<span style="color: #0000cc;">*</span> system<span style="color: #0000cc;">.</span>c <span style="color: #0000cc;">-</span>
Demonstrate the system<span style="color: #0000cc;">(</span><span style="color: #0000cc;">)</span> <span style="color: #0000ff;">call</span><br>
&nbsp;<span style="color: #0000cc;">*</span><span style="color: #0000cc;">/</span><br>
#<span style="color: #ff0000;">include</span> <span style="color: #0000cc;">&lt;</span>stdio<span style="color: #0000cc;">.</span>h<span style="color: #0000cc;">&gt;</span><br>
#<span style="color: #ff0000;">include</span> <span style="color: #0000cc;">&lt;</span>stdlib<span style="color: #0000cc;">.</span>h<span style="color: #0000cc;">&gt;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
<span style="color: #0000ff;">int</span> main<span style="color: #0000cc;">(</span>void<span style="color: #0000cc;">)</span><br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">int</span> retval<span style="color: #0000cc;">;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;retval <span style="color: #0000cc;">=</span> system<span style="color: #0000cc;">(</span><span style="color: #ff00ff;">"ls -l"</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff;">if</span><span style="color: #0000cc;">(</span>retval <span style="color: #0000cc;">=</span><span style="color: #0000cc;">=</span> 127<span style="color: #0000cc;">)</span> {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf<span style="color: #0000cc;">(</span>stderr<span style="color: #0000cc;">,</span> <span style="color: #ff00ff;">"/bin/sh not available\n"</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit<span style="color: #0000cc;">(</span>127<span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span><span style="color: #0000cc;">(</span>retval <span style="color: #0000cc;">=</span><span style="color: #0000cc;">=</span> <span style="color: #0000cc;">-</span>1<span style="color: #0000cc;">)</span> {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror<span style="color: #0000cc;">(</span><span style="color: #ff00ff;">"system"</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit<span style="color: #0000cc;">(</span>EXIT_FAILURE<span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span><span style="color: #0000cc;">(</span>retval <span style="color: #0000cc;">!</span><span style="color: #0000cc;">=</span> 0<span style="color: #0000cc;">)</span> {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fprintf<span style="color: #0000cc;">(</span>stderr<span style="color: #0000cc;">,</span> <span style="color: #ff00ff;">"command returned %d\n"</span><span style="color: #0000cc;">,</span> retval<span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror<span style="color: #0000cc;">(</span><span style="color: #ff00ff;">"ls"</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <span style="color: #0000ff;">else</span> {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts<span style="color: #0000cc;">(</span><span style="color: #ff00ff;">"command successfully executed"</span><span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>
}<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit<span style="color: #0000cc;">(</span>EXIT_SUCCESS<span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>
}<br>
<br>
fork调用创建一个新进程<br>
#<span style="color: #ff0000;">include</span> <span style="color: #0000cc;">&lt;</span>unistd<span style="color: #0000cc;">.</span>h<span style="color: #0000cc;">&gt;</span><br>
<br>
pid_t fork<span style="color: #0000cc;">(</span>void<span style="color: #0000cc;">)</span><span style="color: #0000cc;">;</span><br>
<br>
Description<br>
fork<span style="color: #0000cc;">(</span><span style="color: #0000cc;">)</span> creates a child process that differs from the
parent process only <span style="color: #0000ff;">in</span> its
PID <span style="color: #0000ff;">and</span> PPID<span style="color: #0000cc;">,</span> <br>
return value<span style="color: #0000cc;">:</span><br>
On success<span style="color: #0000cc;">,</span> the PID <span style="color: #ff0000;">of</span> the child process is returned <span style="color: #0000ff;">in</span> the parent<span style="color: #ff00ff;">'s thread of execution, and a 0 is returned in the
child'</span>s thread <span style="color: #ff0000;">of</span>
execution<span style="color: #0000cc;">.</span> On failure<span style="color: #0000cc;">,</span> a <span style="color: #0000cc;">-</span>1 will be returned <span style="color: #0000ff;">in</span>
the parent<span style="color: #ff00ff;">'s context, no child
process will be created, and errno will be set
appropriately.执行成功，就向父进程返回子进程的PID，并向子进程返回0,只调用一次fork,它会返回两次<br>
<br>
example:<br>
#include &lt;unistd.h&gt;<br>
#include &lt;stdio.h&gt;<br>
#include &lt;stdlib.h&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
int main(void)<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;pid_t child;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;if((child = fork()) == -1) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror("fork");<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(EXIT_FAILURE);<br>
&nbsp;&nbsp;&nbsp;&nbsp;} else if(child == 0) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts("in child");<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("\tchild pid = %d\n", getpid());<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("\tchild ppid = %d\n", getppid());<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(EXIT_SUCCESS);<br>
&nbsp;&nbsp;&nbsp;&nbsp;} else {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts("in parent");<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("\tparent pid = %d\n", getpid());<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("\tparent ppid = %d\n", getppid());<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;exit(EXIT_SUCCESS);<br>
}<br>
<br>
exec()函数族<br>
exec用被执行的程序完全替换了调用进程的映像。exec启动一个新程序，替换原有的进程<br>
execl, execlp, execle, execv, execvp - execute a file<br>
Synopsis<br>
#include &lt;unistd.h&gt;<br>
<br>
extern char **environ;<br>
<br>
int execl(const char *path, const char *arg, ...);<br>
int execlp(const char *file, const char *arg, ...);<br>
int execle(const char *path, const char *arg,<br>
..., char * const envp[]);<br>
int execve&nbsp;&nbsp;&nbsp;&nbsp;(const char *path, char *const argv[]);<br>
int execvp(const char *file, char *const argv[]);<br>
以上的函数都必须以NULL结束<br>
<br>
example:<br>
/*<br>
&nbsp;* execve.c - Illustrate execve<br>
&nbsp;*/<br>
#include &lt;unistd.h&gt;<br>
#include &lt;stdlib.h&gt;<br>
#include &lt;stdio.h&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
int main(void)<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;char *argv[] = {"/bin/ls", NULL};<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;if(execve("/bin/ls", argv, NULL) == -1) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror("execve");<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(EXIT_FAILURE);<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;puts("shouldn'</span>t get here<span style="color: #ff00ff;">");<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;exit(EXIT_SUCCESS);<br>
}<br>
使用wait and waitpid调用可以收集子进程的退出状态<br>
Name<br>
wait, waitpid - wait for process to change state<br>
Synopsis<br>
#include &lt;sys/types.h&gt;<br>
#include &lt;sys/wait.h&gt;<br>
<br>
pid_t wait(int *status);<br>
pid_t waitpid(pid_t pid, int *status, int options);<br>
int waitid(idtype_t idtype, id_t id "</span><span style="color: #0000cc;">,</span> siginfo_t <span style="color: #0000cc;">*</span><span style="color: #ff00ff;">" infop "</span><span style="color: #0000cc;">,</span> <span style="color: #0000ff;">int</span>
<span style="color: #ff00ff;">" options );<br>
Description<br>
All of these system calls are used to wait for state changes in a child
of the calling process, and obtain information about the child whose
state has changed. A state change is considered to be: the child
terminated; the child was stopped by a signal; or the child was resumed
by a signal. In the case of a terminated child, performing a wait allows
the system to release the resources associated with the child; if a
wait is not performed, then terminated the child remains in a "</span>zombie<span style="color: #ff00ff;">" state (see NOTES below).<br>
<br>
If a child has already changed state, then these calls return
immediately. Otherwise they block until either a child changes state or a
signal handler interrupts the call (assuming that system calls are not
automatically restarted using the SA_RESTART flag of sigaction(2)). In
the remainder of this page, a child whose state has changed and which
has not yet been waited upon by one of these system calls is termed
waitable.<br>
wait() and waitpid()<br>
The wait() system call suspends execution of the current process until
one of its children terminates. The call wait(&amp;status) is equivalent
to:<br>
<br>
waitpid(-1, &amp;status, 0);<br>
<br>
The waitpid() system call suspends execution of the current process
until a child specified by pid argument has changed state. By default,
waitpid() waits only for terminated children, but this behaviour is
modifiable via the options argument, as described below.<br>
<br>
The value of pid can be:<br>
<br>
&lt; -1<br>
&nbsp;&nbsp;&nbsp;&nbsp;meaning wait for any child process whose process group ID is equal
to the absolute value of pid. <br>
-1<br>
&nbsp;&nbsp;&nbsp;&nbsp;meaning wait for any child process. <br>
0<br>
&nbsp;&nbsp;&nbsp;&nbsp;meaning wait for any child process whose process group ID is equal
to that of the calling process. <br>
&gt; 0<br>
&nbsp;&nbsp;&nbsp;&nbsp;meaning wait for the child whose process ID is equal to the value of
pid.<br>
<br>
The value of options is an OR of zero or more of the following
constants:<br>
<br>
WNOHANG<br>
&nbsp;&nbsp;&nbsp;&nbsp;return immediately if no child has exited. <br>
WUNTRACED<br>
&nbsp;&nbsp;&nbsp;&nbsp;also return if a child has stopped (but not traced via ptrace(2)).
Status for traced children which have stopped is provided even if this
option is not specified. <br>
WCONTINUED<br>
&nbsp;&nbsp;&nbsp;&nbsp;(Since Linux 2.6.10) also return if a stopped child has been resumed
by delivery of SIGCONT.<br>
if you want to more information aboat it, you can reference
http://linux.die.net.<br>
<br>
example:<br>
/*<br>
&nbsp;* waiter.c - Simple wait usage<br>
&nbsp;*/<br>
#include &lt;unistd.h&gt;<br>
//#include &lt;sys/types.h&gt;<br>
#include &lt;sys/wait.h&gt;<br>
#include &lt;stdio.h&gt;<br>
#include &lt;stdlib.h&gt;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
int main(void)<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;pid_t child;<br>
&nbsp;&nbsp;&nbsp;&nbsp;int status;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;if((child = fork()) == -1) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror("</span>fork<span style="color: #ff00ff;">");<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(EXIT_FAILURE);<br>
&nbsp;&nbsp;&nbsp;&nbsp;} else if(child == 0) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts("</span><span style="color: #0000ff;">in</span>
child<span style="color: #ff00ff;">");<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("</span><span style="color: #ff00ff;">\</span>tchild
pid <span style="color: #0000cc;">=</span> %d\n<span style="color: #ff00ff;">", getpid());<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("</span><span style="color: #ff00ff;">\</span>tchild
ppid <span style="color: #0000cc;">=</span> %d\n<span style="color: #ff00ff;">", getppid());<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(EXIT_SUCCESS);<br>
&nbsp;&nbsp;&nbsp;&nbsp;} else {<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Wait for the child to exit */<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;waitpid(child, &amp;status, 0);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("</span><span style="color: #0000ff;">in</span>
parent\n<span style="color: #ff00ff;">");<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("</span><span style="color: #ff00ff;">\</span>tparent
pid <span style="color: #0000cc;">=</span> %d\n<span style="color: #ff00ff;">", getpid());<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("</span><span style="color: #ff00ff;">\</span>tparent
ppid <span style="color: #0000cc;">=</span> %d\n<span style="color: #ff00ff;">", getppid());<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("</span><span style="color: #ff00ff;">\</span>tchild
exited with %d\n<span style="color: #ff00ff;">", status);<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;exit(EXIT_SUCCESS);<br>
}<br>
<br>
abort()<br>
#include &lt;stdlib.h&gt;<br>
void abort(void)<br>
<br>
kill()<br>
#include &lt;signal.h&gt;<br>
#include &lt;sys/types.h&gt;<br>
int kill(pid_t pid, int sig)<br>
<br>
example:<br>
~/*<br>
&nbsp;* killer.c - Killing other processes<br>
&nbsp;*/<br>
#include &lt;sys/types.h&gt;<br>
#include &lt;sys/wait.h&gt;//waitpid()<br>
#include &lt;unistd.h&gt;<br>
#include &lt;stdlib.h&gt;<br>
#include &lt;stdio.h&gt;<br>
#include &lt;signal.h&gt;//signal<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
int main(void)<br>
{<br>
&nbsp;&nbsp;&nbsp;&nbsp;pid_t child;<br>
&nbsp;&nbsp;&nbsp;&nbsp;int status, retval;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;if((child = fork()) &lt; 0) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror("</span>fork<span style="color: #ff00ff;">");<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(EXIT_FAILURE);<br>
&nbsp;&nbsp;&nbsp;&nbsp;}<br>
&nbsp;&nbsp;&nbsp;&nbsp;if(child == 0) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Sleep long enough to be killed */<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sleep(1000);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit(EXIT_SUCCESS);<br>
&nbsp;&nbsp;&nbsp;&nbsp;} else {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Use WNOHANG so wait will return */<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if((waitpid(child, &amp;status, WNOHANG)) == 0) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;retval = kill(child, SIGKILL);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(retval) {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Kill failed, so wait on child to exit */<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;puts("</span>kill failed<span style="color: #ff00ff;">");<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;perror("</span>kill<span style="color: #ff00ff;">");<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;waitpid(child, &amp;status, 0);<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} else<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("</span><span style="color: #ff00ff;">%</span>d
killed\n", child);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; exit(EXIT_SUCCESS);<br>}<br>~<br>信
号：<br>alarm(), pause(),kill(), sigfillset()，sigaction(),sigpending()，all
the functions can find from the site http://linux.die.net<br><br>线程<br>_clone(),
pthread_creat(),
pthread_exit()，pthread_join(),pthread_atfork(),pthread_cancel(), pthread
cleanup宏,pthread_equal()<br>线程互斥，pthread_mutex_init, pthread_mutex_lock<br>pthead
中的p display posix<br><br>from：<br>http://blog.chinaunix.net/u1/45689/showart_689217.html<br></span></code><img src ="http://www.cppblog.com/beautykingdom/aggbug/109680.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-03-14 15:09 <a href="http://www.cppblog.com/beautykingdom/archive/2010/03/14/109680.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux下的文件操作：系统调用还是库函数调用？</title><link>http://www.cppblog.com/beautykingdom/archive/2010/03/01/108697.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Mon, 01 Mar 2010 14:03:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/03/01/108697.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/108697.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/03/01/108697.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/108697.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/108697.html</trackback:ping><description><![CDATA[Linux下对文件操作有两种方式：系统调用（system call）和库函数调用（Library
functions）。可以参考《Linux程序设计》（英文原版为《Beginning Linux Programming》，作者是Neil
Matthew和Richard Stones）第三章: Working with files。<br>
<br>
1。系统调用<br>
系统调用提供的函数如open, close, read, write,
ioctl等，需包含头文件unistd.h。以write为例：其函数原型为 size_t write(int fd, const void
*buf, size_t nbytes)，其操作对象为文件描述符或文件句柄fd(file
descriptor)，要想写一个文件，必须先以可写权限用open系统调用打开一个文件，获得所打开文件的fd，例如
fd=open(\"/dev/video\",
O_RDWR)。fd是一个整型值，每新打开一个文件，所获得的fd为当前最大fd加1。Linux系统默认分配了3个文件描述符
值：0－standard input，1－standard output，2－standard error。<br>
系统调用通常用于底层文件访问（low-level file access），例如在驱动程序中对设备文件的直接访问。<br>
系统调用是操作系统相关的，因此一般没有跨操作系统的可移植性。<br>
系统调用发生在内核空间，因此如果在用户空间的一般应用程序中使用系统调用来进行文件操作，会有用户空间到内核空间切换的开销。事实上，即使在用户空间使
用库函数来对文件进行操作，因为文件总是存在于存储介质上，因此不管是读写操作，都是对硬件（存储器）的操作，都必然会引起系统调用。也就是说，库函数对
文件的操作实际上是通过系统调用来实现的。例如C库函数fwrite()就是通过write()系统调用来实现的。<br>
这样的话，使用库函数也有系统调用的开销，为什么不直接使用系统调用呢？这是因为，读写文件通常是大量的数据（这种大量是相对于底层驱动的系统调用所实现
的数据操作单位而言），这时，使用库函数就可以大大减少系统调用的次数。这一结果又缘于缓冲区技术。在用户空间和内核空间，对文件操作都使用了缓冲区，例
如用fwrite写文件，都是先将内容写到用户空间缓冲区，当用户空间缓冲区满或者写操作结束时，才将用户缓冲区的内容写到内核缓冲区，同样的道理，当内
核缓冲区满或写结束时才将内核缓冲区内容写到文件对应的硬件媒介。<br>
<br>
2。库函数调用<br> 标准C库函数提供的文件操作函数如fopen, fread, fwrite, fclose,
fflush, fseek等，需包含头文件stdio.h。以fwrite为例，其函数原型为size_t fwrite(const void
*buffer, size_t size, size_t item_num, FILE *pf)，其操作对象为文件指针FILE
*pf，要想写一个文件，必须先以可写权限用fopen函数打开一个文件，获得所打开文件的FILE结构指针pf，例如
pf=fopen(\"~/proj/filename\",
\"w\")。实际上，由于库函数对文件的操作最终是通过系统调用实现的，因此，每打开一个文件所获得的FILE结构指针都有一个内核空间的文件描述符
fd与之对应。同样有相应的预定义的FILE指针：stdin－standard input，stdout－standard
output，stderr－standard error。<br>
库函数调用通常用于应用程序中对一般文件的访问。<br>
库函数调用是系统无关的，因此可移植性好。<br>
由于库函数调用是基于C库的，因此也就不可能用于内核空间的驱动程序中对设备的操作.<br><br>from:<br>http://blog.c114.net/html/07/206807-17143.html
<br>http://blog.chinaunix.net/u3/94284/showart_1898811.html
<br><br><img src ="http://www.cppblog.com/beautykingdom/aggbug/108697.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-03-01 22:03 <a href="http://www.cppblog.com/beautykingdom/archive/2010/03/01/108697.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux常用C函数</title><link>http://www.cppblog.com/beautykingdom/archive/2010/03/01/108692.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Mon, 01 Mar 2010 13:28:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/03/01/108692.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/108692.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/03/01/108692.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/108692.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/108692.html</trackback:ping><description><![CDATA[<div id="art" style="margin: 15px;">
<div>
<p><font size="3">文件<font face="Times New Roman">IO</font>编程</font></p>
<p><font size="3">一、系统调用及<font face="Times New Roman">API</font></font></p>
<p><font size="3"><font color="#ff0000"><font face="Times New Roman">1、&nbsp; </font>系统调用</font></font></p>
<p><font size="3">所谓系统调用就是指操作系统提供给用户程序调用的一组&#8220;特殊&#8221;接口，用户程序可以通过这组&#8220;特殊&#8221;接口来获得操作系统内核提供的服务，例如，用户可以通过进程控制相关的系统调用来创建进程、实现进程调度、进程管理等</font></p>
<p><font size="3">为了更好地保护内核空间（就是为什么用户程序不能直接访问系统内核提供的服务），将程序的运行分为内核空间和用户空间，它们运行在不同的级别上，在逻辑上是相互隔离的。</font></p>
<p><font size="3"><font color="#ff0000"><font face="Times New Roman">2、&nbsp; </font>用户编程接口（<font face="Times New Roman">API</font>）</font></font></p>
<p><font size="3">系统调用不是直接与程序员进行交互的，它仅仅是一个通过软中断机制向内核提交请求，以获取内核服务的接口，实际使用中，程序员调用的通常是<font face="Times New Roman">API</font>函数，<font face="Times New Roman">API</font>遵循了在<font face="Times New Roman">UNIX</font>中最流行的应用编程界面标准——<font face="Times New Roman">POSIX</font>标准。该标准描述了操作系统的系统调用编程接口（实际上就是<font face="Times New Roman">API</font>），用于保证应用程序可以在源代码一级上在多种操作系统上移植运行，这些系统调用接口主要是通过<font face="Times New Roman">C</font>库来实现的。</font></p>
<p><font size="3"><font color="#ff0000"><font face="Times New Roman">3、&nbsp; </font>系统命令</font></font></p>
<p><font size="3">系统命令相对<font face="Times New Roman">API</font>更高了一层，实际上是一个可执行程序（如<font face="Times New Roman">shell</font>系统命令），它的内部引用了用户编程接口（<font face="Times New Roman">API</font>）来实现相应的功能。</font></p>
<p>&nbsp;</p>
<p><font size="3">二、文件及文件描述符</font></p>
<p><font size="3">在<font face="Times New Roman">linux</font>中对目录和设备的操作都等同于文件的操作，<font face="Times New Roman">linux</font>中文件分为<font color="#ff0000">普通文件、目录文件、链接文件、设备文件四种</font>。</font></p>
<p><font size="3">内
核通过文件描述符区分和引用特定的文件，所有设备和文件的操作都使用文件描述符来进行的，它是一个非负的整数，是一个索引值，并指向内核中每个进程打开文
件的记录表，当打开一个现存文件或创建一个新文件时，内核就向进程返回一个文件描述符，当需要读文件时，也需要把文件描述符作为参数传递给相应的函数。</font></p>
<p><font size="3"><font color="#ff0000">通常，一个进程打开时，都会打开<font face="Times New Roman">3</font>个文件：标准输入、标准输出、和标准出错处理，这<font face="Times New Roman">3</font>个文件分别对应文件描述符为<font face="Times New Roman">0</font>，<font face="Times New Roman">1</font>，<font face="Times New Roman">2</font></font></font></p>
<p><font size="3">三、不带缓存的文件<font face="Times New Roman">IO</font>操作</font></p>
<p><font size="3">不带缓存是指每一个函数都只是调用系统中的一个函数，这些函数虽然不是<font face="Times New Roman">ANSI C</font>的组成部分，但都是<font face="Times New Roman">POSIX</font>的组成部分。</font></p>
<p><font size="3">主要用到<font face="Times New Roman">5</font>个函数：<font face="Times New Roman">open</font>，<font face="Times New Roman">read</font>，<font face="Times New Roman">write</font>，<font face="Times New Roman">close</font>，<font face="Times New Roman">lseek</font>。</font></p>
<p><font size="3"><font color="#ff0000"><font face="Times New Roman">Open</font>函数定义：</font><font face="Times New Roman"> </font></font></p>
<p><font size="3">定义函数</font><font size="3" face="Times New Roman"> int open( const char * pathname, int flags);<br>int open( const char * pathname,int flags, int mode);</font></p>
<p><font size="3">参数<font face="Times New Roman">pathname </font>被打开的文件名（可包含路径名）。</font></p>
<p><font size="3">参数<font face="Times New Roman">flags </font>所能使用的旗标</font><font size="3"><font face="Times New Roman">:<br>O_RDONLY </font>以只读方式打开文件</font><br><font size="3" face="Times New Roman">O_WRONLY </font><font size="3">以只写方式打开文件</font><br><font size="3" face="Times New Roman">O_RDWR </font><font size="3">以可读写方式打开文件。上述三种旗标是互斥的，也就是不可同时使用，但可与下列的旗标利用<font face="Times New Roman">OR(|)</font>运算符组合。</font><br><font size="3" face="Times New Roman">O_CREAT </font><font size="3">若欲打开的文件不存在则自动建立该文件。</font><br><font size="3" face="Times New Roman">O_EXCL </font><font size="3">如果<font face="Times New Roman">O_CREAT </font>也被设置，此指令会去检查文件是否存在。文件若不存在则建立该文件，否则将导致打开文件错误。此外，若<font face="Times New Roman">O_CREAT</font>与<font face="Times New Roman">O_EXCL</font>同时设置，并且欲打开的文件为符号连接，则会打开文件失败。</font><br><font size="3" face="Times New Roman">O_NOCTTY </font><font size="3">如果欲打开的文件为终端机设备时，则不会将该终端机当成进程控制终端机。</font><br><font size="3" face="Times New Roman">O_TRUNC </font><font size="3">若文件存在并且以可写的方式打开时，此旗标会令文件长度清为<font face="Times New Roman">0</font>，而原来存于该文件的资料也会消失。</font><br><font size="3" face="Times New Roman">O_APPEND </font><font size="3">当读写文件时会从文件尾开始移动，也就是所写入的数据会以附加的方式加入到文件后面。</font><br><font size="3" face="Times New Roman">O_NONBLOCK </font><font size="3">以不可阻断的方式打开文件，也就是无论有无数据读取或等待，都会立即返回进程之中。</font><br><font size="3" face="Times New Roman">O_NDELAY </font><font size="3">同<font face="Times New Roman">O_NONBLOCK</font>。</font><br><font size="3" face="Times New Roman">O_SYNC </font><font size="3">以同步的方式打开文件。</font><br><font size="3" face="Times New Roman">O_NOFOLLOW </font><font size="3">如果参数<font face="Times New Roman">pathname </font>所指的文件为一符号连接，则会令打开文件失败。</font><br><font size="3" face="Times New Roman">O_DIRECTORY </font><font size="3">如果参数<font face="Times New Roman">pathname </font>所指的文件并非为一目录，则会令打开文件失败。</font></p>
<p><font size="3">此为<font face="Times New Roman">Linux2.2</font>以后特有的旗标，以避免一些系统安全问题。参数<font face="Times New Roman">mode </font>则有下列数种组合，只有在建立新文件时才会生效，此外真正建文件时的权限会受到<font face="Times New Roman">umask</font>值所影响，因此该文件权限应该为（<font face="Times New Roman">mode-umaks</font>）。</font><br><font size="3" face="Times New Roman">S_IRWXU00700 </font><font size="3">权限，代表该文件所有者具有可读、可写及可执行的权限。</font><br><font size="3" face="Times New Roman">S_IRUSR </font><font size="3">或<font face="Times New Roman">S_IREAD</font>，<font face="Times New Roman">00400</font>权限，代表该文件所有者具有可读取的权限。</font><br><font size="3" face="Times New Roman">S_IWUSR </font><font size="3">或<font face="Times New Roman">S_IWRITE</font>，<font face="Times New Roman">00200 </font>权限，代表该文件所有者具有可写入的权限。</font><br><font size="3" face="Times New Roman">S_IXUSR </font><font size="3">或<font face="Times New Roman">S_IEXEC</font>，<font face="Times New Roman">00100 </font>权限，代表该文件所有者具有可执行的权限。</font><br><font size="3" face="Times New Roman">S_IRWXG 00070</font><font size="3">权限，代表该文件用户组具有可读、可写及可执行的权限。</font><br><font size="3" face="Times New Roman">S_IRGRP 00040 </font><font size="3">权限，代表该文件用户组具有可读的权限。</font><br><font size="3" face="Times New Roman">S_IWGRP 00020</font><font size="3">权限，代表该文件用户组具有可写入的权限。</font><br><font size="3" face="Times New Roman">S_IXGRP 00010 </font><font size="3">权限，代表该文件用户组具有可执行的权限。</font><br><font size="3" face="Times New Roman">S_IRWXO 00007</font><font size="3">权限，代表其他用户具有可读、可写及可执行的权限。</font><br><font size="3" face="Times New Roman">S_IROTH 00004 </font><font size="3">权限，代表其他用户具有可读的权限</font><br><font size="3" face="Times New Roman">S_IWOTH 00002</font><font size="3">权限，代表其他用户具有可写入的权限。</font><br><font size="3" face="Times New Roman">S_IXOTH 00001 </font><font size="3">权限，代表其他用户具有可执行的权限。</font><br><br><font size="3">返回值<font face="Times New Roman"> </font>若所有欲核查的权限都通过了检查则返回<font face="Times New Roman">0 </font>值，表示成功，只要有一个权限被禁止则返回<font face="Times New Roman">-1</font>。</font><br><br><font size="3">错误代码<font face="Times New Roman"> EEXIST </font>参数<font face="Times New Roman">pathname </font>所指的文件已存在，却使用了<font face="Times New Roman">O_CREAT</font>和<font face="Times New Roman">O_EXCL</font>旗标。</font><br><font size="3" face="Times New Roman">EACCESS </font><font size="3">参数<font face="Times New Roman">pathname</font>所指的文件不符合所要求测试的权限。</font><br><font size="3" face="Times New Roman">EROFS </font><font size="3">欲测试写入权限的文件存在于只读文件系统内。</font><br><font size="3" face="Times New Roman">EFAULT </font><font size="3">参数<font face="Times New Roman">pathname</font>指针超出可存取内存空间。</font><br><font size="3" face="Times New Roman">EINVAL </font><font size="3">参数<font face="Times New Roman">mode </font>不正确。</font><br><font size="3" face="Times New Roman">ENAMETOOLONG </font><font size="3">参数<font face="Times New Roman">pathname</font>太长。</font><br><font size="3" face="Times New Roman">ENOTDIR </font><font size="3">参数<font face="Times New Roman">pathname</font>不是目录。</font><br><font size="3" face="Times New Roman">ENOMEM </font><font size="3">核心内存不足。</font><br><font size="3" face="Times New Roman">ELOOP </font><font size="3">参数<font face="Times New Roman">pathname</font>有过多符号连接问题。</font><br><font size="3" face="Times New Roman">EIO I/O </font><font size="3">存取错误</font></p>
<p><font size="3">如：</font></p>
<p><font size="3"><font face="Times New Roman">int dev_fd;//</font>文件描述符，失败返回为<font face="Times New Roman">-1</font>。</font></p>
<p><font size="3" face="Times New Roman">dev_fd = open("/dev/simple",O_RDWR | O_NONBLOCK,0600);</font></p>
<p><font size="3"><font face="Times New Roman">//</font>权限值可以不要</font></p>
<font size="3">
<p><font size="3"><font color="#0000ff">如果使用了<font face="Times New Roman">O_CREATE</font>标志，则使用的函数为<font face="Times New Roman">int open( const char * pathname,int flags, int mode);</font>此时就要指定<font face="Times New Roman">mode</font>，用来表示文件的访问的权限，<font face="Times New Roman">mode</font>的组合表示如上所述。</font></font></p>
<p><font size="3"><font color="#0000ff">除了可以用以上宏来进行&#8220;或&#8221;逻辑产生标志以外，我们还可以使用自己的数字来表示，<font face="Times New Roman">linux</font>总共用<font face="Times New Roman">5</font>个数字来表示文件的各种权限，第一位表示设置用户的<font face="Times New Roman">ID</font>，第二位表示设置组<font face="Times New Roman">ID</font>，第三位表示用户自己的权限位，第四位表示组的权限，第五位表示其他人的权限，每个数字可以取<font face="Times New Roman">1</font>（执行权限），<font face="Times New Roman">2</font>（写权限），<font face="Times New Roman">4</font>（读权限），<font face="Times New Roman">0</font>（无），或者这些值的组合。</font></font></p>
<p><font size="3"><font color="#0000ff"><font face="Times New Roman">&nbsp;&nbsp;&nbsp;&nbsp; </font>例如，如果要创建一个用户可读，可写，可执行，但是组没有权限，其他人可以读，可以执行的文件，并设置用户<font face="Times New Roman">ID</font>，那么使用的模式是<font face="Times New Roman">1</font>（设置用户<font face="Times New Roman">ID</font>）、<font face="Times New Roman">0</font>（不设置用户<font face="Times New Roman">ID</font>）、<font face="Times New Roman">7</font>（<font face="Times New Roman">1+2+4</font>，读，写，执行）、<font face="Times New Roman">0</font>（没有权限）、<font face="Times New Roman">5</font>（<font face="Times New Roman">1+4</font>，读，执行），即<font face="Times New Roman">10705</font>，如：</font></font></p>
<p><font size="3"><font color="#0000ff"><font face="Times New Roman">Open</font>（&#8220;<font face="Times New Roman">test</font>&#8221;，<font face="Times New Roman"> O_CREATE</font>，<font face="Times New Roman">10705</font>）</font></font></p>
<p><font size="3"><font color="#0000ff">以<font face="Times New Roman">O_CREATE</font>为标志的<font face="Times New Roman">open</font>函数实际上实现了文件创建的功能，因此下面的函数等同<font face="Times New Roman">create</font>（）函数。</font></font></p>
<p><font size="3" color="#0000ff" face="Times New Roman">Int open(pathname, O_CREATE |O_WRONLY,mode);</font></p>
</font>&nbsp;
<p><font size="3"><font color="#ff0000">注：<font face="Times New Roman">open</font>函数返回的文件描述符一定是最小的未用文件描述符。</font></font></p>
<p><font size="3" face="Times New Roman">&nbsp;</font></p>
<p><font size="3"><font color="#ff0000"><font face="Times New Roman">Close</font>函数定义：</font></font></p>
<p><font size="3"><font face="Times New Roman">Int close</font>（<font face="Times New Roman">int fd</font>）</font></p>
<p><font size="3"><font face="Times New Roman">fd</font>：文件描述符，<font face="Times New Roman">0</font>为成功，<font face="Times New Roman">-1</font>为出错</font></p>
<p><font size="3" face="Times New Roman">&nbsp;</font></p>
<p><font size="3"><font color="#ff0000"><font face="Times New Roman">read</font>函数定义：</font></font></p>
<p><font size="3"><font face="Times New Roman">read</font>函数是用于将指定的文件描述符中读出数据，当从终端设备中读出数据时，通常一次最多读一行。</font></p>
<p><font size="3">函数原型：<font face="Times New Roman">ssize_t read(int fd,void *buf,size_t count)</font></font></p>
<p><font size="3"><font face="Times New Roman">Buf:</font>指定存储器读出数据的缓冲区</font></p>
<p><font size="3"><font face="Times New Roman">Count</font>：指定读出的字节数</font></p>
<p><font size="3">函数返回值：</font></p>
<p><font size="3">成功：读到的字节数</font></p>
<p><font size="3"><font face="Times New Roman">0</font>：已达到文件尾</font></p>
<p><font size="3"><font face="Times New Roman">-1</font>：出错</font></p>
<p><font size="3">在读普通文件时，若读到要求的字节数之前已到达文件的结尾，则返回的字节数会小于希望读出的字节数。</font></p>
<p><font size="3" face="Times New Roman">&nbsp;</font></p>
<p><font size="3"><font color="#ff0000"><font face="Times New Roman">write</font>函数定义：</font></font></p>
<p><font size="3">函数是用于向打开的文件写数据，写操作从文件的当前位移量处开始，若磁盘已满或超出该文件的长度，则<font face="Times New Roman">write</font>函数返回失败。</font></p>
<p><font size="3">函数原型：<font face="Times New Roman">ssize_t write(int fd,void *buf,size_t count)</font></font></p>
<p><font size="3"><font face="Times New Roman">Buf:</font>指定存储器写入数据的缓冲区</font></p>
<p><font size="3"><font face="Times New Roman">Count</font>：指定读出的字节数</font></p>
<p><font size="3">函数返回值：</font></p>
<p><font size="3">成功：已写的字节数</font></p>
<p><font size="3"><font face="Times New Roman">-1</font>：出错</font></p>
<p><font size="3">在写普通文件时，写操作从文件的当前位移处开始。</font></p>
<p><font size="3" face="Times New Roman">&nbsp;</font></p>
<p><font size="3"><font color="#ff0000"><font face="Times New Roman">lseek</font>函数定义：</font></font></p>
<p><font size="3">函数是用于在指定的文件描述符中将文件指针定位到相应的位置。</font></p>
<p><font size="3">函数原型：<font face="Times New Roman">ssize_t lseek(int fd,off_t offset,int whence)</font></font></p>
<p><font size="3"><font face="Times New Roman">offset:</font>偏移量，每一次读写操作所需要移动的距离，单位是字节的数量，可正可负（向前移，向后移）。<font face="Times New Roman"> </font></font></p>
<p><font size="3"><font face="Times New Roman">whence</font>：<font face="Times New Roman">SEEK_SET:</font>当前位置为文件指针的位置，新位置为当前位置加上偏移量</font></p>
<p><font size="3" face="Times New Roman">SEEK_CUR:</font></p>
<p><font size="3"><font face="Times New Roman">SEEK_END: </font>当前位置为文件的结尾，新位置为偏移量的大小加上偏移量的大小</font></p>
<p><font size="3">函数返回值：</font></p>
<p><font size="3">成功：文件的当前位移</font></p>
<p><font size="3"><font face="Times New Roman">-1</font>：出错</font></p>
<p><font size="3"><font color="#0000ff"><font face="Times New Roman">Offset</font>可取负值，即可将文件指针相对当前位置向前移动<font face="Times New Roman">5</font>个字节，<font face="Times New Roman">lseek</font>函数的返回值为文件指针相对于文件头的位置。</font></font></p>
</div>
</div>
from:<br>http://blog.chinaunix.net/u3/94284/showart_1892712.html
<br><img src ="http://www.cppblog.com/beautykingdom/aggbug/108692.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-03-01 21:28 <a href="http://www.cppblog.com/beautykingdom/archive/2010/03/01/108692.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>open和fopen的区别</title><link>http://www.cppblog.com/beautykingdom/archive/2010/02/20/108108.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Sat, 20 Feb 2010 13:30:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/02/20/108108.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/108108.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/02/20/108108.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/108108.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/108108.html</trackback:ping><description><![CDATA[<div id="art" style="margin: 15px;">
<div>
<div><font size="2">（一）</font></div>
<div><font size="2">1.缓冲文件系统</font></div>
<div><font size="2">缓冲文件系统的特点是：在内存开辟一个&#8220;缓冲区&#8221;，为程序中的每一个文件使用，当执行读文件的操作时，从磁盘文
件将数据先读入内存&#8220;缓冲区&#8221;，装满后再从内存&#8220;缓冲区&#8221;依此读入接收的变量。执行写文件的操作时，先将数据写入内存&#8220;缓冲区&#8221;，待内存&#8220;缓冲区&#8221;装满后
再写入文件。由此可以看出，内存&#8220;缓冲区&#8221;的大小，影响着实际操作外存的次数，内存&#8220;缓冲区&#8221;越大，则操作外存的次数就少，执行速度就快、效率高。一般来
说，文件&#8220;缓冲区&#8221;的大小随机器而定。</font></div>
<div><font size="2"><strong style="color: black; background-color: #ffff66;">fopen</strong>, fclose, fread, fwrite, fgetc, fgets, fputc, fputs, freopen, fseek, ftell, rewind等</font></div>
<div><font size="2">2.非缓冲文件系统</font></div>
<div><font size="2">缓冲文件系统是借助文件结构体指针来对文件进行管理，通过文件指针来对文件进行访问，既可以读写字符、字符串、
格式化数据，也可以读写二进制数据。非缓冲文件系统依赖于操作系统，通过操作系统的功能对文件进行读写，是系统级的输入输出，它不设文件结构体指针，只能
读写二进制文件，但效率高、速度快，由于ANSI标准不再包括非缓冲文件系统，因此建议大家最好不要选择它。本书只作简单介绍。</font></div>
<div><font size="2"><strong style="color: black; background-color: #a0ffff;">open</strong>, close, read, write, getc, getchar, putc,&nbsp;putchar 等</font></div>
<div><font size="2">（二）</font></div>
<div><font size="2"><strong style="color: black; background-color: #a0ffff;">open</strong>和<strong style="color: black; background-color: #ffff66;">fopen</strong>的<strong style="color: black; background-color: #99ff99;">区别</strong>：<br>前者属于低级IO，后者是高级IO。<br>前者返回一个文件描述符(用户程序区的)，后者返回一个文件指针。<br>前者无缓冲，后者有缓冲。<br>前者与 read, write 等配合使用， 后者与 fread, fwrite等配合使用。<br>后者是在前者的基础上扩充而来的，在大多数情况下，用后者。</font></div>
<div><font size="2"><strong style="color: black; background-color: #a0ffff;">open</strong> 是系统调用 <strong style="color: black; background-color: #ffff66;">fopen</strong>是C的库函数。</font></div>
</div>
</div>
from：<br>http://blog.chinaunix.net/u3/94284/showart_2126418.html
<br><br><img src ="http://www.cppblog.com/beautykingdom/aggbug/108108.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-02-20 21:30 <a href="http://www.cppblog.com/beautykingdom/archive/2010/02/20/108108.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>brk__sbrk</title><link>http://www.cppblog.com/beautykingdom/archive/2010/02/18/108032.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Thu, 18 Feb 2010 11:23:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/02/18/108032.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/108032.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/02/18/108032.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/108032.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/108032.html</trackback:ping><description><![CDATA[<p>NAME<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; brk, sbrk - change data segment size</p>
<p>SYNOPSIS<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #include &lt;unistd.h&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int brk(void *end_data_segment);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void *sbrk(intptr_t increment);</p>
<p>DESCRIPTION<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; brk()&nbsp; sets the end of the data segment to the value specified by end_data_segment,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; when that value is reasonable, the system does have enough memory and&nbsp; the&nbsp; process<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; does not exceed its max data size (see setrlimit(2)).</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sbrk() increments the program's data space by increment bytes.&nbsp; sbrk() isn't a sys-<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tem call, it is just a C library wrapper.&nbsp; Calling sbrk() with an&nbsp; increment&nbsp; of&nbsp; 0<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; can be used to find the current location of the program break.</p>
<p>RETURN VALUE<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; On&nbsp; success,&nbsp; brk()&nbsp; returns zero, and sbrk() returns a pointer to the start of the<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new area.&nbsp; On error, -1 is returned, and errno is set to ENOMEM.</p>
<p>CONFORMING TO<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4.3BSD</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; brk() and sbrk() are not defined in the C Standard and&nbsp; are&nbsp; deliberately&nbsp; excluded<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; from the POSIX.1 standard (see paragraphs B.1.1.1.3 and B.8.3.3).</p>
<p>NOTES<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Various&nbsp; systems&nbsp; use&nbsp; various&nbsp; types for the parameter of sbrk().&nbsp; Common are int,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ssize_t, ptrdiff_t, intptr_t.&nbsp; XPGv6 obsoletes this function.</p>
<p>SEE ALSO<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; execve(2), getrlimit(2), malloc(3)<br><br>&nbsp;&nbsp;&nbsp; The brk() and sbrk() functions are used to change the amount of memory <br>&nbsp;&nbsp;&nbsp; allocated in a process's data segment. They do this by moving the loca- <br>&nbsp;&nbsp;&nbsp; tion of the ``break''. The break is the first address after the end of&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; the process's uninitialized data segment (also known as the ``BSS''). <br><br><br>brk and sbrk设置的是BSS里的边界，具体什么是BSS呢<br>bss = "Block Started by Symbol" (由符号启始的区块） <br><br>Dennis Ritchie 曾说过： <br>这个缩写也许有其它说法，但事实上我们采用这个缩写的本意是 <br>"Block Started by Symbol"。它是 FAP 上的伪指令，FAP <br>(Fortran Assembly [-er?] Program) 是指 IBM 704-709-7090-7094 <br>这种机型的组译器。这个指令可定义自己的标号，并且预留一定数目 <br>的字组空间。还有另一个伪指令 BES，是 "Block Ended by <br>Symbol"，跟 BSS 指令几乎一样，不同点在于标号是定义在预留字组 <br>空间尾端的地址 + 1 的地方。在这些机器上，Fortran 的数组是以反 <br>方向储存，而且数组的索引是从 1 算起。 <br><br>这种用法是合理的，因为这跟 UNIX 上标准的程序加载器一样，程序 <br>码当中并非真的放入这一整块预留空间，而是先用一个数目表示，在 <br>加载时才真的把所需的预留空间定出来。 <br>from：<br>Linux man page and <br><a href="http://www.linuxforum.net/forum/gshowflat.php?Cat=&amp;Board=linuxK&amp;Number=300677&amp;page=16&amp;view=collapsed&amp;sb=5&amp;o=all&amp;fpart">http://www.linuxforum.net/forum/gshowflat.php?Cat=&amp;Board=linuxK&amp;Number=300677&amp;page=16&amp;view=collapsed&amp;sb=5&amp;o=all&amp;fpart</a>=</p>
<img src ="http://www.cppblog.com/beautykingdom/aggbug/108032.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-02-18 19:23 <a href="http://www.cppblog.com/beautykingdom/archive/2010/02/18/108032.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>查看系统调用和信号的命令--strace</title><link>http://www.cppblog.com/beautykingdom/archive/2010/02/18/107991.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Wed, 17 Feb 2010 16:05:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/02/18/107991.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/107991.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/02/18/107991.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/107991.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/107991.html</trackback:ping><description><![CDATA[strace命令用法<br><br>调用: <br>strace [ -dffhiqrtttTvxx ] [ -acolumn ] [ -eexpr ] ... <br>[ -ofile ] [ -ppid ] ... [ -sstrsize ] [ -uusername ] [ command [ arg ... ] ] <br><br>strace -c [ -eexpr ] ... [ -Ooverhead ] [ -Ssortby ] [ command [ arg ... ] ] <br>功能: <br>跟踪程式执行时的系统调用和所接收的信号.通常的用法是strace执行一直到commande结束. <br>并且将所调用的系统调用的名称、参数和返回值输出到标准输出或者输出到-o指定的文件. <br>strace是一个功能强大的调试,分析诊断工具.你将发现他是一个极好的帮手在你要调试一个无法看到源码或者源码无法在编译的程序. <br>你将轻松的学习到一个软件是如何通过系统调用来实现他的功能的.而且作为一个程序设计师,你可以了解到在用户态和内核态是如何通过系统调用和信号来实现程序的功能的. <br>strace的每一行输出包括系统调用名称,然后是参数和返回值.这个例子: <br>strace cat /dev/null <br>他的输出会有: <br>open(\"/dev/null\",O_RDONLY) = 3 <br>有错误产生时,一般会返回-1.所以会有错误标志和描述: <br>open(\"/foor/bar\",)_RDONLY) = -1 ENOENT (no such file or directory) <br>信号将输出喂信号标志和信号的描述.跟踪并中断这个命令\"sleep 600\": <br>sigsuspend({} <unfinished .=""><br>--- SIGINT (Interrupt) --- <br>+++ killed by SIGINT +++ <br>参数的输出有些不一致.如shell命令中的 \"&gt;&gt;tmp\",将输出: <br>open(\"tmp\",O_WRONLY|O_APPEND|A_CREAT,0666) = 3 <br>对于结构指针,将进行适当的显示.如:\"ls -l /dev/null\": <br>lstat(\"/dev/null\",{st_mode=S_IFCHR|0666},st_rdev=makdev[1,3],...}) = 0 <br>请注意\"struct stat\" 的声明和这里的输出.lstat的第一个参数是输入参数,而第二个参数是向外传值. <br>当你尝试\"ls -l\" 一个不存在的文件时,会有: <br>lstat(/foot/ball\",0xb004) = -1 ENOENT (no such file or directory) <br>char*将作为C的字符串类型输出.没有字符串输出时一般是char* 是一个转义字符,只输出字符串的长度. <br>当字符串过长是会使用\"...\"省略.如在\"ls -l\"会有一个gepwuid调用读取password文件: <br>read(3,\"root::0:0:System Administrator:/\"...,1024) = 422 <br>当参数是结构数组时,将按照简单的指针和数组输出如: <br>getgroups(4,[0,2,4,5]) = 4 <br>关于bit作为参数的情形,也是使用方括号,并且用空格将每一项参数隔开.如: <br>sigprocmask(SIG_BLOCK,[CHLD TTOU],[]) = 0 <br>这里第二个参数代表两个信号SIGCHLD 和 SIGTTOU.如果bit型参数全部置位,则有如下的输出: <br>sigprocmask(SIG_UNBLOCK,~[],NULL) = 0 <br>这里第二个参数全部置位. <br><br>参数说明: <br>-c 统计每一系统调用的所执行的时间,次数和出错的次数等. <br>-d 输出strace关于标准错误的调试信息. <br>-f 跟踪由fork调用所产生的子进程. <br>-ff 如果提供-o filename,则所有进程的跟踪结果输出到相应的filename.pid中,pid是各进程的进程号. <br>-F 尝试跟踪vfork调用.在-f时,vfork不被跟踪. <br>-h 输出简要的帮助信息. <br>-i 输出系统调用的入口指针. <br>-q 禁止输出关于脱离的消息. <br>-r 打印出相对时间关于,,每一个系统调用. <br>-t 在输出中的每一行前加上时间信息. <br>-tt 在输出中的每一行前加上时间信息,微秒级. <br>-ttt 微秒级输出,以秒了表示时间. <br>-T 显示每一调用所耗的时间. <br>-v 输出所有的系统调用.一些调用关于环境变量,状态,输入输出等调用由于使用频繁,默认不输出. <br>-V 输出strace的版本信息. <br>-x 以十六进制形式输出非标准字符串 <br>-xx 所有字符串以十六进制形式输出. <br>-a column <br>设置返回值的输出位置.默认为40. <br>-e expr <br>指定一个表达式,用来控制如何跟踪.格式如下: <br>[qualifier=][!]value1[,value2]... <br>qualifier只能是 trace,abbrev,verbose,raw,signal,read,write其中之一.value是用来限定的符号或数字.默认的qualifier是 trace.感叹号是否定符号.例如: <br>-eopen等价于 -e trace=open,表示只跟踪open调用.而-etrace!=open表示跟踪除了open以外的其他调用.有两个特殊的符号 all 和 none. <br>注意有些shell使用!来执行历史记录里的命令,所以要使用\\. <br>-e trace=set <br>只跟踪指定的系统调用.例如:-e trace=open,close,rean,write表示只跟踪这四个系统调用.默认的为set=all. <br>-e trace=file <br>只跟踪有关文件操作的系统调用. <br>-e trace=process <br>只跟踪有关进程控制的系统调用. <br>-e trace=network <br>跟踪与网络有关的所有系统调用. <br>-e strace=signal <br>跟踪所有与系统信号有关的系统调用 <br>-e trace=ipc <br>跟踪所有与进程通讯有关的系统调用 <br>-e abbrev=set <br>设定strace输出的系统调用的结果集.-v 等与 abbrev=none.默认为abbrev=all. <br>-e raw=set <br>将指定的系统调用的参数以十六进制显示. <br>-e signal=set <br>指定跟踪的系统信号.默认为all.如signal=!SIGIO(或者signal=!io),表示不跟踪SIGIO信号. <br>-e read=set <br>输出从指定文件中读出的数据.例如: <br>-e read=3,5 <br>-e write=set <br>输出写入到指定文件中的数据. <br>-o filename <br>将strace的输出写入文件filename <br>-p pid <br>跟踪指定的进程pid. <br>-s strsize <br>指定输出的字符串的最大长度.默认为32.文件名一直全部输出. <br>-u username <br>以username的UID和GID执行被跟踪的命令. </unfinished>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><!--startfragment --><strong>用strace调试程序</strong><br><br></p>
<ul>&nbsp;&nbsp;&nbsp;&nbsp; 在理想世界里，每当一个程序不能正常执行一个功能时，它就会给出一个有用的错误提示，告诉你在足够的改正错误的线索。但遗憾的是，我们不是生活在理想世界里，起码不总是生活在理想世界里。有时候一个程序出现了问题，你无法找到原因。<br><br>这就是调试程序出现的原因。strace是一个必不可少的调试工具，strace用来监视系统调用。你不仅可以调试一个新开始的程序，也可以调试一个已经在运行的程序（把strace绑定到一个已有的PID上面）。<br><br>首先让我们看一个真实的例子：<br><br>[BOLD]启动KDE时出现问题[/BOLD]<br><br>前一段时间，我在启动KDE的时候出了问题，KDE的错误信息无法给我任何有帮助的线索。<br><br><strong>代码：</strong><br>
    <table class="tInner" bgcolor="#edf4f8" cellpadding="4" cellspacing="1">
        <tbody>
            <tr class="tBody2">
                <td><br>_KDE_IceTransSocketCreateListener: failed to bind listener<br>_KDE_IceTransSocketUNIXCreateListener: ...SocketCreateListener() failed<br>_KDE_IceTransMakeAllCOTSServerListeners: failed to create listener for local<br><br>Cannot establish any listening sockets DCOPServer self-test failed.<br></td>
            </tr>
        </tbody>
    </table>
    <br><br>对我来说这个错误信息没有太多意义，只是一个对KDE来说至关重要的负责进程间通信的程序无法启动。我还可以知道这个错误和ICE协议（Inter Client Exchange）有关，除此之外，我不知道什么是KDE启动出错的原因。<br><br>我决定采用strace看一下在启动dcopserver时到底程序做了什么：<br><br><strong>代码：</strong><br>
    <table class="tInner" bgcolor="#edf4f8" cellpadding="4" cellspacing="1">
        <tbody>
            <tr class="tBody2">
                <td><br>strace -f -F -o ~/dcop-strace.txt dcopserver<br></td>
            </tr>
        </tbody>
    </table>
    <br><br>这里 -f -F选项告诉strace同时跟踪fork和vfork出来的进程，-o选项把所有strace输出写到~/dcop-strace.txt里面，dcopserver是要启动和调试的程序。<br><br>再次出现错误之后，我检查了错误输出文件dcop-strace.txt，文件里有很多系统调用的记录。在程序运行出错前的有关记录如下：<br><br><strong>代码：</strong><br>
    <table class="tInner" bgcolor="#edf4f8" cellpadding="4" cellspacing="1">
        <tbody>
            <tr class="tBody2">
                <td><br>27207 mkdir("/tmp/.ICE-unix", 0777) = -1 EEXIST (File exists)<br>27207 lstat64("/tmp/.ICE-unix", {st_mode=S_IFDIR|S_ISVTX|0755, st_size=4096, ...}) = 0<br>27207 unlink("/tmp/.ICE-unix/dcop27207-1066844596") = -1 ENOENT (No such file or directory)<br>27207 bind(3, {sin_family=AF_UNIX, path="/tmp/.ICE-unix/dcop27207-1066844596"}, 38) = -1 EACCES (Permission denied) <br>27207 write(2, "_KDE_IceTrans", 13) = 13<br>27207 write(2, "SocketCreateListener: failed to "..., 46) = 46<br>27207 close(3) = 0 27207 write(2, "_KDE_IceTrans", 13) = 13<br>27207 write(2, "SocketUNIXCreateListener: ...Soc"..., 59) = 59<br>27207 umask(0) = 0 27207 write(2, "_KDE_IceTrans", 13) = 13<br>27207 write(2, "MakeAllCOTSServerListeners: fail"..., 64) = 64<br>27207 write(2, "Cannot establish any listening s"..., 39) = 39<br></td>
            </tr>
        </tbody>
    </table>
    <br><br>其
    中第一行显示程序试图创建/tmp/.ICE-unix目录，权限为0777，这个操作因为目录已经存在而失败了。第二个系统调用（lstat64）检查
    了目录状态，并显示这个目录的权限是0755，这里出现了第一个程序运行错误的线索：程序试图创建属性为0777的目录，但是已经存在了一个属性为
    0755的目录。第三个系统调用（unlink）试图删除一个文件，但是这个文件并不存在。这并不奇怪，因为这个操作只是试图删掉可能存在的老文件。<br><br>但
    是，第四行确认了错误所在。他试图绑定到/tmp/.ICE-unix/dcop27207-1066844596，但是出现了拒绝访问错误。.
    ICE_unix目录的用户和组都是root，并且只有所有者具有写权限。一个非root用户无法在这个目录下面建立文件，如果把目录属性改成0777，
    则前面的操作有可能可以执行，而这正是第一步错误出现时进行过的操作。<br><br>所以我运行了chmod 0777 /tmp/.ICE-unix之后KDE就可以正常启动了，问题解决了，用strace进行跟踪调试只需要花很短的几分钟时间跟踪程序运行，然后检查并分析输出文件。<br><br>说
    明：运行chmod 0777只是一个测试，一般不要把一个目录设置成所有用户可读写，同时不设置粘滞位(sticky
    bit)。给目录设置粘滞位可以阻止一个用户随意删除可写目录下面其他人的文件。一般你会发现/tmp目录因为这个原因设置了粘滞位。KDE可以正常启动
    之后，运行chmod +t /tmp/.ICE-unix给.ICE_unix设置粘滞位。<br><br>[BOLD]解决库依赖问题[/BOLD]<br><br>starce
    的另一个用处是解决和动态库相关的问题。当对一个可执行文件运行ldd时，它会告诉你程序使用的动态库和找到动态库的位置。但是如果你正在使用一个比较老
    的glibc版本（2.2或更早），你可能会有一个有bug的ldd程序，它可能会报告在一个目录下发现一个动态库，但是真正运行程序时动态连接程序
    （/lib/ld-linux.so.2）却可能到另外一个目录去找动态连接库。这通常因为/etc/ld.so.conf和
    /etc/ld.so.cache文件不一致，或者/etc/ld.so.cache被破坏。在glibc
    2.3.2版本上这个错误不会出现，可能ld-linux的这个bug已经被解决了。<br><br>尽管这样，ldd并不能把所有程序依赖的动态库列出
    来，系统调用dlopen可以在需要的时候自动调入需要的动态库，而这些库可能不会被ldd列出来。作为glibc的一部分的NSS（Name
    Server
    Switch）库就是一个典型的例子，NSS的一个作用就是告诉应用程序到哪里去寻找系统帐号数据库。应用程序不会直接连接到NSS库，glibc则会通
    过dlopen自动调入NSS库。如果这样的库偶然丢失，你不会被告知存在库依赖问题，但这样的程序就无法通过用户名解析得到用户ID了。让我们看一个例
    子：<br><br>whoami程序会给出你自己的用户名，这个程序在一些需要知道运行程序的真正用户的脚本程序里面非常有用，whoami的一个示例输出如下：<br><strong>代码：</strong><br>
    <table class="tInner" bgcolor="#edf4f8" cellpadding="4" cellspacing="1">
        <tbody>
            <tr class="tBody2">
                <td><br># whoami<br>root<br></td>
            </tr>
        </tbody>
    </table>
    <br><br>假设因为某种原因在升级glibc的过程中负责用户名和用户ID转换的库NSS丢失，我们可以通过把nss库改名来模拟这个环境：<br><strong>代码：</strong><br>
    <table class="tInner" bgcolor="#edf4f8" cellpadding="4" cellspacing="1">
        <tbody>
            <tr class="tBody2">
                <td><br># mv /lib/libnss_files.so.2 /lib/libnss_files.so.2.backup <br># whoami<br>whoami: cannot find username for UID 0 <br></td>
            </tr>
        </tbody>
    </table>
    <br><br>这里你可以看到，运行whoami时出现了错误，ldd程序的输出不会提供有用的帮助：<br><strong>代码：</strong><br>
    <table class="tInner" bgcolor="#edf4f8" cellpadding="4" cellspacing="1">
        <tbody>
            <tr class="tBody2">
                <td><br># ldd /usr/bin/whoami<br>libc.so.6 =&gt; /lib/libc.so.6 (0x4001f000)<br>/lib/ld-linux.so.2 =&gt; /lib/ld-linux.so.2 (0x40000000)<br></td>
            </tr>
        </tbody>
    </table>
    <br><br>你只会看到whoami依赖Libc.so.6和ld-linux.so.2，它没有给出运行whoami所必须的其他库。这里时用strace跟踪whoami时的输出：<br><strong>代码：</strong><br>
    <table class="tInner" bgcolor="#edf4f8" cellpadding="4" cellspacing="1">
        <tbody>
            <tr class="tBody2">
                <td><br>strace -o whoami-strace.txt whoami<br><br>open("/lib/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)<br>open("/lib/i686/mmx/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)<br>stat64("/lib/i686/mmx", 0xbffff190) = -1 ENOENT (No such file or directory) <br>open("/lib/i686/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)<br>stat64("/lib/i686", 0xbffff190) = -1 ENOENT (No such file or directory)<br>open("/lib/mmx/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)<br>stat64("/lib/mmx", 0xbffff190) = -1 ENOENT (No such file or directory) <br>open("/lib/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)<br>stat64("/lib", {st_mode=S_IFDIR|0755, st_size=2352, ...}) = 0<br>open("/usr/lib/i686/mmx/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)<br>stat64("/usr/lib/i686/mmx", 0xbffff190) = -1 ENOENT (No such file or directory) <br>open("/usr/lib/i686/libnss_files.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)<br></td>
            </tr>
        </tbody>
    </table>
    <br><br>你可以发现在不同目录下面查找libnss.so.2的尝试，但是都失败了。如果没有strace这样的工具，很难发现这个错误是由于缺少动态库造成的。现在只需要找到libnss.so.2并把它放回到正确的位置就可以了。<br><br>[BOLD]限制strace只跟踪特定的系统调用[/BOLD]<br><br>如果你已经知道你要找什么，你可以让strace只跟踪一些类型的系统调用。例如，你需要看看在configure脚本里面执行的程序，你需要监视的系统调用就是execve。让strace只记录execve的调用用这个命令：<br><br><strong>代码：</strong><br>
    <table class="tInner" bgcolor="#edf4f8" cellpadding="4" cellspacing="1">
        <tbody>
            <tr class="tBody2">
                <td><br>strace -f -o configure-strace.txt -e execve ./configure<br></td>
            </tr>
        </tbody>
    </table>
    <br><br>部分输出结果为：<br><strong>代码：</strong><br>
    <table class="tInner" bgcolor="#edf4f8" cellpadding="4" cellspacing="1">
        <tbody>
            <tr class="tBody2">
                <td><br>2720 execve("/usr/bin/expr", ["expr", "a", ":", "(a)"], [/* 31 vars */]) = 0<br>2725 execve("/bin/basename", ["basename", "./configure"], [/* 31 vars */]) = 0<br>2726 execve("/bin/chmod", ["chmod", "+x", "conftest.sh"], [/* 31 vars */]) = 0<br>2729 execve("/bin/rm", ["rm", "-f", "conftest.sh"], [/* 31 vars */]) = 0<br>2731 execve("/usr/bin/expr", ["expr", "99", "+", "1"], [/* 31 vars */]) = 0<br>2736 execve("/bin/ln", ["ln", "-s", "conf2693.file", "conf2693"], [/* 31 vars */]) = 0<br></td>
            </tr>
        </tbody>
    </table>
    <br><br>你
    已经看到了，strace不仅可以被程序员使用，普通系统管理员和用户也可以使用strace来调试系统错误。必须承认，strace的输出不总是容易理
    解，但是很多输出对大多数人来说是不重要的。你会慢慢学会从大量输出中找到你可能需要的信息，像权限错误，文件未找到之类的，那时strace就会成为一
    个有力的工具了。<br>from:
    <br>http://blog.chinaunix.net/u1/55468/showart_2003061.html
    <br><br></ul>
    <br> <img src ="http://www.cppblog.com/beautykingdom/aggbug/107991.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-02-18 00:05 <a href="http://www.cppblog.com/beautykingdom/archive/2010/02/18/107991.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux系统调用函数</title><link>http://www.cppblog.com/beautykingdom/archive/2010/01/22/106233.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Fri, 22 Jan 2010 09:00:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/01/22/106233.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/106233.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/01/22/106233.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/106233.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/106233.html</trackback:ping><description><![CDATA[
由操作系统实现的所有系统调用所构成的集合即程序接口或应用编程接口(Application Programming Interface，API)。是应用程序同系统之间的接口。<br>
操作系统的主要功能是为应用程序的运行创建良好的环境，为了达到这个目的，内核提供一系列具备预定功能的的内核函数，通过一组称为系统调用的
（system
call)的接口呈现给用户。系统调用把应用程序的请求传给内核，调用相应的的内核函数完成所需的处理，将处理结果返回给应用程序，如果没有系统调用和内
核函数，用户将不能编写大型应用程序。<br>　　Linux系统调用，包含了大部分常用系统调用和由系统调用派生出的的函数。<br>　　一、进程控制：<br>　　fork 创建一个新进程<br>　　clone 按指定条件创建子进程<br>　　execve 运行可执行文件<br>　　exit 中止进程<br>　　_exit 立即中止当前进程<br>　　getdtablesize 进程所能打开的最大文件数<br>　　getpgid 获取指定进程组标识号<br>　　setpgid 设置指定进程组标志号<br>　　getpgrp 获取当前进程组标识号<br>　　setpgrp 设置当前进程组标志号<br>　　getpid 获取进程标识号<br>　　getppid 获取父进程标识号<br>　　getpriority 获取调度优先级<br>　　setpriority 设置调度优先级<br>　　modify_ldt 读写进程的本地描述表<br>　　nanosleep 使进程睡眠指定的时间<br>　　nice 改变分时进程的优先级<br>　　pause 挂起进程，等待信号<br>　　personality 设置进程运行域<br>　　prctl 对进程进行特定操作<br>　　ptrace 进程跟踪<br>　　sched_get_priority_max 取得静态优先级的上限<br>　　sched_get_priority_min 取得静态优先级的下限<br>　　sched_getparam 取得进程的调度参数<br>　　sched_getscheduler 取得指定进程的调度策略<br>　　sched_rr_get_interval 取得按RR算法调度的实时进程的时间片长度<br>　　sched_setparam 设置进程的调度参数<br>　　sched_setscheduler 设置指定进程的调度策略和参数<br>　　sched_yield 进程主动让出处理器,并将自己等候调度队列队尾<br>　　vfork 创建一个子进程，以供执行新程序，常与execve等同时使用<br>　　wait 等待子进程终止<br>　　wait3 参见wait<br>　　waitpid 等待指定子进程终止<br>　　wait4 参见waitpid<br>　　capget 获取进程权限<br>　　capset 设置进程权限<br>　　getsid 获取会晤标识号<br>　　setsid 设置会晤标识号<br>　　二、文件系统控制<br>　　1、文件读写操作<br>　　fcntl 文件控制<br>　　open 打开文件<br>　　creat 创建新文件<br>　　close 关闭文件描述字<br>　　read 读文件<br>　　write 写文件<br>　　readv 从文件读入数据到缓冲数组中<br>　　writev 将缓冲数组里的数据写入文件<br>　　pread 对文件随机读<br>　　pwrite 对文件随机写<br>　　lseek 移动文件指针<br>　　_llseek 在64位地址空间里移动文件指针<br>　　dup 复制已打开的文件描述字<br>　　dup2 按指定条件复制文件描述字<br>　　flock 文件加/解锁<br>　　poll I/O多路转换<br>　　truncate 截断文件<br>　　ftruncate 参见truncate<br>　　umask 设置文件权限掩码<br>　　fsync 把文件在内存中的部分写回磁盘<br>　　2、文件系统操作<br>　　access 确定文件的可存取性<br>　　chdir 改变当前工作目录<br>　　fchdir 参见chdir<br>　　chmod 改变文件方式<br>　　fchmod 参见chmod<br>　　chown 改变文件的属主或用户组<br>　　fchown 参见chown<br>　　lchown 参见chown<br>　　chroot 改变根目录<br>　　stat 取文件状态信息<br>　　lstat 参见stat<br>　　fstat 参见stat<br>　　statfs 取文件系统信息<br>　　fstatfs 参见statfs<br>　　readdir 读取目录项<br>　　getdents 读取目录项<br>　　mkdir 创建目录<br>　　mknod 创建索引节点<br>　　rmdir 删除目录<br>　　rename 文件改名<br>　　link 创建链接<br>　　symlink 创建符号链接<br>　　unlink 删除链接<br>　　readlink 读符号链接的值<br>　　mount 安装文件系统<br>　　umount 卸下文件系统<br>　　ustat 取文件系统信息<br>　　utime 改变文件的访问修改时间<br>　　utimes 参见utime<br>　　quotactl 控制磁盘配额<br>　　三、系统控制<br>　　ioctl I/O总控制函数<br>　　_sysctl 读/写系统参数<br>　　acct 启用或禁止进程记账<br>　　getrlimit 获取系统资源上限<br>　　setrlimit 设置系统资源上限<br>　　getrusage 获取系统资源使用情况<br>　　uselib 选择要使用的二进制函数库<br>　　ioperm 设置端口I/O权限<br>　　iopl 改变进程I/O权限级别<br>　　outb 低级端口操作<br>　　reboot 重新启动<br>　　swapon 打开交换文件和设备<br>　　swapoff 关闭交换文件和设备<br>　　bdflush 控制bdflush守护进程<br>　　sysfs 取核心支持的文件系统类型<br>　　sysinfo 取得系统信息<br>　　adjtimex 调整系统时钟<br>　　alarm 设置进程的闹钟<br>　　getitimer 获取计时器值<br>　　setitimer 设置计时器值<br>　　gettimeofday 取时间和时区<br>　　settimeofday 设置时间和时区<br>　　stime 设置系统日期和时间<br>　　time 取得系统时间<br>　　times 取进程运行时间<br>　　uname 获取当前UNIX系统的名称、版本和主机等信息<br>　　vhangup 挂起当前终端<br>　　nfsservctl 对NFS守护进程进行控制<br>　　vm86 进入模拟8086模式<br>　　create_module 创建可装载的模块项<br>　　delete_module 删除可装载的模块项<br>　　init_module 初始化模块<br>　　query_module 查询模块信息<br>　　*get_kernel_syms 取得核心符号,已被query_module代替<br>　　四、内存管理<br>　　brk 改变数据段空间的分配<br>　　sbrk 参见brk<br>　　mlock 内存页面加锁<br>　　munlock 内存页面解锁<br>　　mlockall 调用进程所有内存页面加锁<br>　　munlockall 调用进程所有内存页面解锁<br>　　mmap 映射虚拟内存页<br>　　munmap 去除内存页映射<br>　　mremap 重新映射虚拟内存地址<br>　　msync 将映射内存中的数据写回磁盘<br>　　mprotect 设置内存映像保护<br>　　getpagesize 获取页面大小<br>　　sync 将内存缓冲区数据写回硬盘<br>　　cacheflush 将指定缓冲区中的内容写回磁盘<br>　　五、网络管理<br>　　getdomainname 取域名<br>　　setdomainname 设置域名<br>　　gethostid 获取主机标识号<br>　　sethostid 设置主机标识号<br>　　gethostname 获取本主机名称<br>　　sethostname 设置主机名称<br>　　六、socket控制<br>　　socketcall socket系统调用<br>　　socket 建立socket<br>　　bind 绑定socket到端口<br>　　connect 连接远程主机<br>　　accept 响应socket连接请求<br>　　send 通过socket发送信息<br>　　sendto 发送UDP信息<br>　　sendmsg 参见send<br>　　recv 通过socket接收信息<br>　　recvfrom 接收UDP信息<br>　　recvmsg 参见recv<br>　　listen 监听socket端口<br>　　select 对多路同步I/O进行轮询<br>　　shutdown 关闭socket上的连接<br>　　getsockname 取得本地socket名字<br>　　getpeername 获取通信对方的socket名字<br>　　getsockopt 取端口设置<br>　　setsockopt 设置端口参数<br>　　sendfile 在文件或端口间传输数据<br>　　socketpair 创建一对已联接的无名socket<br>　　七、用户管理<br>　　getuid 获取用户标识号<br>　　setuid 设置用户标志号<br>　　getgid 获取组标识号<br>　　setgid 设置组标志号<br>　　getegid 获取有效组标识号<br>　　setegid 设置有效组标识号<br>　　geteuid 获取有效用户标识号<br>　　seteuid 设置有效用户标识号<br>　　setregid 分别设置真实和有效的的组标识号<br>　　setreuid 分别设置真实和有效的用户标识号<br>　　getresgid 分别获取真实的,有效的和保存过的组标识号<br>　　setresgid 分别设置真实的,有效的和保存过的组标识号<br>　　getresuid 分别获取真实的,有效的和保存过的用户标识号<br>　　setresuid 分别设置真实的,有效的和保存过的用户标识号<br>　　setfsgid 设置文件系统检查时使用的组标识号<br>　　setfsuid 设置文件系统检查时使用的用户标识号<br>　　getgroups 获取后补组标志清单<br>　　setgroups 设置后补组标志清单<br>　　八、进程间通信<br>　　ipc 进程间通信总控制调用<br>　　1、信号<br>　　sigaction 设置对指定信号的处理方法<br>　　sigprocmask 根据参数对信号集中的信号执行阻塞/解除阻塞等操作<br>　　sigpending 为指定的被阻塞信号设置队列<br>　　sigsuspend 挂起进程等待特定信号<br>　　signal 参见signal<br>　　kill 向进程或进程组发信号<br>　　*sigblock 向被阻塞信号掩码中添加信号,已被sigprocmask代替<br>　　*siggetmask 取得现有阻塞信号掩码,已被sigprocmask代替<br>　　*sigsetmask 用给定信号掩码替换现有阻塞信号掩码,已被sigprocmask代替<br>　　*sigmask 将给定的信号转化为掩码,已被sigprocmask代替<br>　　*sigpause 作用同sigsuspend,已被sigsuspend代替<br>　　sigvec 为兼容BSD而设的信号处理函数,作用类似sigaction<br>　　ssetmask ANSI C的信号处理函数,作用类似sigaction<br>　　2、消息<br>　　msgctl 消息控制操作<br>　　msgget 获取消息队列<br>　　msgsnd 发消息<br>　　msgrcv 取消息<br>　　3、管道<br>　　pipe 创建管道<br>　　4、信号量<br>　　semctl 信号量控制<br>　　semget 获取一组信号量<br>　　semop 信号量操作<br>　　5、共享内存<br>　　shmctl 控制共享内存<br>　　shmget 获取共享内存<br>　　shmat 连接共享内存<br>　　shmdt 拆卸共享内存<img src ="http://www.cppblog.com/beautykingdom/aggbug/106233.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-01-22 17:00 <a href="http://www.cppblog.com/beautykingdom/archive/2010/01/22/106233.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>解决Linux pthread_create内存泄漏问题</title><link>http://www.cppblog.com/beautykingdom/archive/2010/01/14/105664.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Thu, 14 Jan 2010 08:40:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/01/14/105664.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/105664.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/01/14/105664.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/105664.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/105664.html</trackback:ping><description><![CDATA[
<span style="color: rgb(51, 51, 51); font-family: verdana, 'ms song', Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px; "><p style="margin-top: 0px; margin-right: auto; margin-bottom: 1em; margin-left: auto; text-indent: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">昨天解决了一个隐蔽的内存泄漏问题，原因是pthread_create后的僵死线程没有释放导致的内存持续增长。<br>现象是这样的：短时间内程序运行正常，但跑了12小时左右，用top查看其内存占用居然高达2G，于是马上意识到有内存泄漏。</p><p style="margin-top: 0px; margin-right: auto; margin-bottom: 1em; margin-left: auto; text-indent: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">最先想到的是malloc/free、new/delete没有配对，申请的内存没有释放。于是写了个跟踪malloc/free调用的模块，不过检查中并没有找到未释放的内存。之后怀疑是不是 free then malloc 导致的内存管理错误（事实证明虽然free后不是立即回收内存，但是接连调用free &amp; malloc并不会影响操作系统的内存管理），不过写了个小程序发现并不是这么回事。</p><p style="margin-top: 0px; margin-right: auto; margin-bottom: 1em; margin-left: auto; text-indent: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">陷入窘境了，只好用最小系统法把功能部分和内存分配都给屏蔽掉，这时发现内存泄漏依然存在！仔细看top的输出，几乎是每次创建线程时内存就往上涨一点，只是增长速度不是很快，看来是线程的问题了。仔细分析发现，之前图简单&nbsp;<strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">pthread_create (&amp;thread, NULL, &amp;thread_function, NULL);</strong>&nbsp;就这么写了，参数2没有设置线程结束后自动detach，并且没有使用pthread_join或pthread_detach释放执行结束后线程的空间！</p><p style="margin-top: 0px; margin-right: auto; margin-bottom: 1em; margin-left: auto; text-indent: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp;</p><p style="margin-top: 0px; margin-right: auto; margin-bottom: 1em; margin-left: auto; text-indent: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">Linux man page</strong>&nbsp;里有已经说明了这个问题：<br>&nbsp;&nbsp;&nbsp; When a joinable thread terminates, its memory resources (thread descriptor and stack) are not deallocated until another thread performs pthread_join on it. Therefore,&nbsp;<span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: red; ">pthread_join must be called&nbsp; once&nbsp; for&nbsp;each joinable thread created to avoid&nbsp;<strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">memory leaks</strong>.</span><br></p><p style="margin-top: 0px; margin-right: auto; margin-bottom: 1em; margin-left: auto; text-indent: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">也就说线程执行完后如果不join的话，线程的资源会一直得不到释放而导致内存泄漏！一时的图快后患无穷啊。</p><p style="margin-top: 0px; margin-right: auto; margin-bottom: 1em; margin-left: auto; text-indent: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp;</p><p style="margin-top: 0px; margin-right: auto; margin-bottom: 1em; margin-left: auto; text-indent: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: red; ">解决办法</strong>：</p><div class="cnblogs_code" onclick="cnblogs_code_show('c16318a4-97b7-4cc0-85e1-5d5afa68b275')" twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; background-color: rgb(245, 245, 245); font-family: 'Courier New'; font-size: 13px; border-left-color: rgb(204, 204, 204); word-break: break-all; overflow-x: auto; overflow-y: auto; "><img class="code_img_opened" id="code_img_opened_c16318a4-97b7-4cc0-85e1-5d5afa68b275" onclick="cnblogs_code_hide('c16318a4-97b7-4cc0-85e1-5d5afa68b275',event)" src="http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 5px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; vertical-align: middle; "><span class="cnblogs_code_collapse" twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 2px; padding-right: 2px; padding-bottom: 2px; padding-left: 2px; border-right-color: rgb(128, 128, 128); border-right-width: 1px; border-right-style: solid; border-top-color: rgb(128, 128, 128); border-top-width: 1px; border-top-style: solid; border-left-color: rgb(128, 128, 128); border-left-width: 1px; border-left-style: solid; border-bottom-color: rgb(128, 128, 128); border-bottom-width: 1px; border-bottom-style: solid; background-color: rgb(255, 255, 255); font-family: 'Courier New'; ">代码</span><div id="cnblogs_code_open_c16318a4-97b7-4cc0-85e1-5d5afa68b275" twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><div twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 128, 128); ">&nbsp;1</span>&nbsp;<span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 128, 0); ">//</span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 128, 0); ">&nbsp;最简单的办法，在线程执行结束后调用pthread_detach让他自己释放</span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 128, 0); "><br></span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 128, 128); ">&nbsp;2</span>&nbsp;<span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 128, 0); "></span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 0, 0); "><strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">pthread_detach(pthread_self());<br></strong></span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 128, 128); ">&nbsp;3</span>&nbsp;<span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 0, 0); "><br></span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 128, 128); ">&nbsp;4</span>&nbsp;<span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 0, 0); "><br></span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 128, 128); ">&nbsp;5</span>&nbsp;<span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 0, 0); "></span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 128, 0); ">//</span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 128, 0); ">&nbsp;或者创建线程前设置&nbsp;PTHREAD_CREATE_DETACHED&nbsp;属性</span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 128, 0); "><br></span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 128, 128); ">&nbsp;6</span>&nbsp;<span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 128, 0); "></span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 0, 0); ">pthread_attr_t&nbsp;attr;<br></span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 128, 128); ">&nbsp;7</span>&nbsp;<span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 0, 0); ">pthread_t&nbsp;thread;<br></span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 128, 128); ">&nbsp;8</span>&nbsp;<span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 0, 0); ">pthread_attr_init&nbsp;(</span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 0, 0); ">&amp;</span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 0, 0); ">attr);<br></span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 128, 128); ">&nbsp;9</span>&nbsp;<span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 0, 0); ">pthread_attr_setdetachstate&nbsp;(</span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 0, 0); "><strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&amp;</strong></span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 0, 0); "><strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">attr</strong>,&nbsp;<strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">PTHREAD_CREATE_DETACHED</strong>);<br></span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 128, 128); ">10</span>&nbsp;<span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 0, 0); ">pthread_create&nbsp;(</span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 0, 0); ">&amp;</span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 0, 0); ">thread,&nbsp;</span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: red; "><strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&amp;</strong></span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: red; "><strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">attr</strong></span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 0, 0); ">,&nbsp;</span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 0, 0); ">&amp;</span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 0, 0); ">thread_function,&nbsp;NULL);<br></span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 128, 128); ">11</span>&nbsp;<span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 0, 0); ">pthread_attr_destroy&nbsp;(</span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 0, 0); ">&amp;</span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 0, 0); ">attr);</span><span twffan="done" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-family: 'Courier New'; color: rgb(0, 0, 0); "><br></span></div></div></div><p style="margin-top: 0px; margin-right: auto; margin-bottom: 1em; margin-left: auto; text-indent: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp;</p><p style="margin-top: 0px; margin-right: auto; margin-bottom: 1em; margin-left: auto; text-indent: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">第2行的那种方法最简单，在线程函数尾部加上这句话就可以将线程所占用的资源给释放掉；或者像 5-11 所示的方法设置detach属性，这样也会在线程return/pthread_exit后释放内存。</p><p style="margin-top: 0px; margin-right: auto; margin-bottom: 1em; margin-left: auto; text-indent: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">其实仔细想想，valgrind检查时已经提示了pthread_create没有释放的问题，只是之前没引起注意。其实这样的问题也只有在长时间运行时，慢慢积累这一点点的内存才会暴露出来，看来valgrind的提示也不能置之不理啊。</p><p style="margin-top: 0px; margin-right: auto; margin-bottom: 1em; margin-left: auto; text-indent: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">from：</p><p style="margin-top: 0px; margin-right: auto; margin-bottom: 1em; margin-left: auto; text-indent: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; "><a href="http://www.cnblogs.com/bits/archive/2009/12/04/no_join_or_detach_memory_leak.html">http://www.cnblogs.com/bits/archive/2009/12/04/no_join_or_detach_memory_leak.html</a></p></span><img src ="http://www.cppblog.com/beautykingdom/aggbug/105664.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-01-14 16:40 <a href="http://www.cppblog.com/beautykingdom/archive/2010/01/14/105664.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux进程的状态和调度</title><link>http://www.cppblog.com/beautykingdom/archive/2010/01/11/105437.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Mon, 11 Jan 2010 14:01:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/01/11/105437.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/105437.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/01/11/105437.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/105437.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/105437.html</trackback:ping><description><![CDATA[<span style="LINE-HEIGHT: 16px; FONT-FAMILY: Verdana, Geneva, Arial, Helvetica, sans-serif; FONT-SIZE: 13px">
<p style="LINE-HEIGHT: 19px; TEXT-INDENT: 0px; MARGIN: 5px auto; FONT-SIZE: 13px">进程是一个动态的实体，所以他是有生命的。从创建到消亡，是一个进程的整个生命周期。在这个周期中，进程可能会经历各种不同的状态。一般来说，所有进程都要经历以下的3个状态：</p>
<ol>
    <li style="LIST-STYLE-TYPE: decimal">就绪态。指进程已经获得所有所需的其他资源，正在申请处理处理器资源，准备开始执行。这种情况下，称进程处于就绪态。
    <li style="LIST-STYLE-TYPE: decimal">阻塞态。指进程因为需要等待所需资源而放弃处理器，或者进程本不拥有处理器，且其他资源也没有满足，从而即使得到处理器也不能开始运行。这种情况下，进程处于阻塞态。阻塞状态也称休眠状态或者等待状态。
    <li style="LIST-STYLE-TYPE: decimal">运行态。进程得到了处理器，并不需要等待其他任何资源，正在执行的状态，称之为运行态。只有在运行态时，进程才可以使用所申请到的资源。</li>
</ol>
<p style="LINE-HEIGHT: 19px; TEXT-INDENT: 0px; MARGIN: 5px auto; FONT-SIZE: 13px">在Linux系统中，将各种状态进行了重新组织，由此得到了Linux进程的几个状态：</p>
<ul>
    <li>RUNNING：正在运行或者在就绪队列中等待运行的进程。也就是上面提到的运行态和就绪态进程的综合。一个进程处于RUNNING状态，并不代表他一定在被执行。由于在多任务系统中，各个就绪进程需要并发执行，所以在某个特定时刻，这些处于RUNNING状态的进程之中，只有一个能得到处理器，而其他进程必须在一个就绪队列中等待。即使是在多处理器的系统中，Linux也只能同时让一个处理器执行任务。
    <li>UNINTERRUPTABLE:不可中断阻塞状态。处于这种状态的进程正在等待队列中，当资源有效时，可由操作系统进行唤醒，否则，将一直处于等待状态。
    <li>INTERRUPTABLE：可中断阻塞状态。与不可中断阻塞状态一样，处于这种状态的进程在等待队列中，当资源有效时，可以有操作系统进行唤醒。与不可中断阻塞状态有所区别的是，处于此状态中的进程亦可被其他进程的信号唤醒。
    <li>STOPPED：挂起状态。进程被暂停，需要通过其它进程的信号才能被唤醒。导致这种状态的原因有两种。其一是受到相关信号(SIGSTOP,SIGSTP,SIGTTIN或SIGTTOU)的反应。其二是受到父进程ptrace调用的控制，而暂时将处理器交给控制进程。
    <li>ZOMBIE：僵尸状态。表示进程结束但尚未消亡的一种状态。此时进程已经结束运行并释放掉大部分资源，但尚未释放进程控制块。</li>
</ul>
<p style="LINE-HEIGHT: 19px; TEXT-INDENT: 0px; MARGIN: 5px auto; FONT-SIZE: 13px"><a style="COLOR: navy; TEXT-DECORATION: none" href="http://images.cnblogs.com/cnblogs_com/chenglei/WindowsLiveWriter/Linux_12ADE/image_2.png"><img style="BORDER-RIGHT-WIDTH: 0px; DISPLAY: block; FLOAT: none; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; MARGIN-LEFT: auto; BORDER-LEFT-WIDTH: 0px; MARGIN-RIGHT: auto" title=image border=0 alt=image src="http://images.cnblogs.com/cnblogs_com/chenglei/WindowsLiveWriter/Linux_12ADE/image_thumb.png" width=458 height=309></a></p>
<div style="TEXT-ALIGN: center; MARGIN-TOP: 10px" id=digg_block><font color=#075db3 size=4 face=Verdana><span style="LINE-HEIGHT: 30px; FONT-SIZE: 14px">转自：</span></font></div>
<div style="TEXT-ALIGN: center; MARGIN-TOP: 10px" id=digg_block><font color=#075db3 size=4 face=Verdana><span style="LINE-HEIGHT: 30px; FONT-SIZE: 14px"><a href="http://www.cnblogs.com/chenglei/archive/2009/11/20/1606881.html">http://www.cnblogs.com/chenglei/archive/2009/11/20/1606881.html</a></span></font></div>
</span>
<img src ="http://www.cppblog.com/beautykingdom/aggbug/105437.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-01-11 22:01 <a href="http://www.cppblog.com/beautykingdom/archive/2010/01/11/105437.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>