﻿<?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>IT博客-学而不思则罔，思而不学则殆-随笔分类-linux 编程</title><link>http://www.cnitblog.com/schkui/category/2840.html</link><description>有其事必有其理，
有其理必有其事 </description><language>zh-cn</language><lastBuildDate>Wed, 15 May 2013 12:54:52 GMT</lastBuildDate><pubDate>Wed, 15 May 2013 12:54:52 GMT</pubDate><ttl>60</ttl><item><title>美团云计算方面面试题 </title><link>http://www.cnitblog.com/schkui/archive/2013/05/15/87416.html</link><dc:creator>易道</dc:creator><author>易道</author><pubDate>Wed, 15 May 2013 02:52:00 GMT</pubDate><guid>http://www.cnitblog.com/schkui/archive/2013/05/15/87416.html</guid><wfw:comment>http://www.cnitblog.com/schkui/comments/87416.html</wfw:comment><comments>http://www.cnitblog.com/schkui/archive/2013/05/15/87416.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/schkui/comments/commentRss/87416.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/schkui/services/trackbacks/87416.html</trackback:ping><description><![CDATA[<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"><span style="font-size: 18px">1、Linux进程间的通信方式？两个进程是如何来共享内存的？两个进程如何通过信号量通信？</span></p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"></p>
<blockquote style="border-bottom-style: none; padding-bottom: 0px; border-right-style: none; margin: 0px 0px 0px 40px; padding-left: 0px; padding-right: 0px; border-top-style: none; border-left-style: none; padding-top: 0px">
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">（1）Linux下进程间通信的方式有： 管道(有名/无名) 、消息、信号、信号量、共享内存、邮箱、socket。</p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">（2）Linux下共享内存是进程间通信的方式之一，共享内存允许两个或多个进程访问同一块内存，比如像 malloc函数 向不同的进程返回执行同一块物理内存区域的指针。当一个进程改变了这块地址中的内容的时候，其他拥有这块物理内存指针的进程也会察觉到这个更改。在进程间的通信方式中，共享内存是通信效率最高的，访问共享内存区域和访问进程独有的内存区域一样快，并不需要通过系统调用或者其他通过内核的过程来完成，同时也避免了各种不必要的复制。对共享内存的操作涉及到多个进程间的同步问题，数据应该先写，在读，通常采用用信号量来协调这个过程。</p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"><br /></p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"><span style="color: rgb(255,0,0)">进程与线程的区别？回答方式：</span></p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">线程是进程中的一个逻辑执行单元，也是进程中可调度的实体；一个进程中可以包含多个线程，但是一个线程只能隶属于一个进程</p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">与进程的区别：</p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">1、CPU调度方面：CPU调度是以线程为基本单位进行的；</p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">2、拥有资源方面：进程是拥有资源的基本单位，线程不拥有系统的资源，但是可以使用隶属于进程的资源；</p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">3、并发方面： 线程 和 进程都支持并发；</p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">4、系统开销方面： 创建进程的时候需要为进程分配资源，销毁进程时需要回收资源，所以使用进程的开销要大于使用线程的开销。</p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"><br /></p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">进程控制块?</p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">操作系统通过进程控制块来对进程控制和管理的。PCB通常在系统内存中占用一块连续的分区，它存放着操作系统用于描述进程情况以及控制进程运行情况所需的全部信息，</p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">为什么要CPU调度？</p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">CPU调度的目标是在任何时候都有某些进程在运行，是CPU使用率最大化。 &nbsp;同一时刻 只有一个进程占有CPU资源，但一个进程在等待IO时等等一些阻塞进程的动作时，CPU就回空闲出来，这时候，我们应该让这个阻塞的进程让出CPU资源，让其他已经处于就绪状态的进程执行。这样就可以使CPU使用率最大化。</p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">什么是死锁？</p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">在多道程序环境下，多个进程可能竞争一定数量的资源，某个进程申请资源，如果这时这个资源不可用，那么这个进程就进入等待状态。如果所申请的资源被其他等待进程占有，那么该等待进程可能再也无法改变其状态，一直等待下去，这种情况称之为 死锁。</p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"><br /></p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">cache的作用？</p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">cache是处于 CPU寄存器 和 内存之间的一层缓存，用来加快CPU的取指速率， 使用时： CPU需要数据时，首先会查找cache中有没有需要的数据，如果有，则取走，如果没有，则查询内存，并将数据更新到缓存中，以供下次取指。</p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"><br /></p></blockquote>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">2、DNS (Domain name system)域名系统，简单描述其工作原理。</p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"></p>
<blockquote style="border-bottom-style: none; padding-bottom: 0px; border-right-style: none; margin: 0px 0px 0px 40px; padding-left: 0px; padding-right: 0px; border-top-style: none; border-left-style: none; padding-top: 0px">
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">DNS客户机需要在程序中使用名称时，它会查询DNS服务器来解析该名称。客户机发送的每条查询信息包括三条信息：包括：指定的DNS域名，指定的查询类型，DNS域名指定的类别。它是基于UDP的服务，端口是53，该应用一般不直接为用户使用，而是为其他应用服务 如 HTTP、SMTP等在其中需要完成主机名到IP地址转换。</p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"><br /></p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"><span style="font-family: 'Comic Sans MS'; color: rgb(255,0,0)"><strong>在浏览器地址栏内敲 www.baidu.com 到这个页面显示在浏览器上，这个过程中都发生了什么？</strong></span></p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">（1） 当我们在浏览器上敲入一个url是， 浏览器会解析出该url的域名，接下来的动作，是将域名转化为 ID 地址，依次查询 浏览器DNS缓存、系统缓存、路由器缓存、如果没有找到 则一直查询到 根域名服务器缓存，找到域名所对应的的 IP地址。</p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">（2）向IP所对应的的服务器发送请求数据，</p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">（3）服务器响应请求，发回网页内容；</p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">（4）客户端浏览器获取网页内容，解析，并显示在浏览器上。</p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">这就是我们所看到的的 百度页面显现的过程。</p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"><br /></p></blockquote>3、TCP/UDP的区别？ 
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"></p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"></p>
<blockquote style="border-bottom-style: none; padding-bottom: 0px; border-right-style: none; margin: 0px 0px 0px 40px; padding-left: 0px; padding-right: 0px; border-top-style: none; border-left-style: none; padding-top: 0px">
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">（1）TCP是面向连接的、可靠数据传输协议，UDP是不面向连接的，非可靠数据传输协议；（2） 从传输速度上考虑： TCP 由于要建立连接、保证数据传输的可靠性等造成数据传输速度比较慢，UDP不需要这些，数据传输速度相对比较快；（3）从安全方面考虑，TCP的安全性能更高，UDP的安全性能比较低 （4）从传输数据的格式来比较，TCP传输的单位称为报文段，UDP传输的数据单位被称为 数据报</p></blockquote>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"></p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">4、ICMP协议</p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"></p>
<blockquote style="border-bottom-style: none; padding-bottom: 0px; border-right-style: none; margin: 0px 0px 0px 40px; padding-left: 0px; padding-right: 0px; border-top-style: none; border-left-style: none; padding-top: 0px">
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">ICMP (Internet Control Message Protocol) ，因特网控制消息协议。它是TCP/IP协议族的一个子协议，用于在IP主机、路由器之间传输控制消息。控制消息包括：网络不同、主机是否可达、路由器是否可用等网络本身的消息。这些控制消息虽然并不传输用户数据，但对用户数据的传递起着很重要的作用。ICMP报文格式两种： 差错报告报文和询问报文。</p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"><br /></p></blockquote>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">5、数据库</p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"></p>
<blockquote style="border-bottom-style: none; padding-bottom: 0px; border-right-style: none; margin: 0px 0px 0px 40px; padding-left: 0px; padding-right: 0px; border-top-style: none; border-left-style: none; padding-top: 0px">
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"><span style="font-family: 'Comic Sans MS'; color: rgb(255,0,0)">数据库 一个 逻辑执行单元 如何才能被称的上是一个事务？ 必须满足的性质？</span></p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"><span style="font-family: 'Comic Sans MS'">数据库的事务是指 一个逻辑单元，这个逻辑单元可包含一系列的执行操作， 一个逻辑单元要想成为一个事务，必须满足所谓的 ACID （原子性、隔离性、一致性、持久性）；</span></p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"><span style="font-family: 'Comic Sans MS'">原子性：指的是 一个事务执行，要么全部执行成功，要么执行失败回滚到执行之前的状态；</span></p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"><span style="font-family: 'Comic Sans MS'">一致性：事务执行过后，数据库中数据的状态都必须是一致的，必须遵从数据库的完整性约束；</span></p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"><span style="font-family: 'Comic Sans MS'">隔离性：对于多个事务并发的时候，</span></p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"><span style="font-family: 'Comic Sans MS'">持久性： 事务的完成后对系统的影响是持久的，任何一个事务的操作不会对其他事务造成干扰；比如一个事务在读数据库，一个事务在写数据库，读数据库的这个事务读到的数据，要么是这个写数据库事务 写前的状态，要么为写后的状态，不存在 读到的数据是 另一个事务写的过程中的一个状态。</span></p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"><span style="font-family: 'Comic Sans MS'; color: rgb(255,0,0)">数据库索引？</span></p></blockquote>
<blockquote style="border-bottom-style: none; padding-bottom: 0px; border-right-style: none; margin: 0px 0px 0px 40px; padding-left: 0px; padding-right: 0px; border-top-style: none; border-left-style: none; padding-top: 0px">
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"><br /></p></blockquote>6、内存管理<br />
<blockquote style="border-bottom-style: none; padding-bottom: 0px; border-right-style: none; margin: 0px 0px 0px 40px; padding-left: 0px; padding-right: 0px; border-top-style: none; border-left-style: none; padding-top: 0px" sizset="27" sizcache="0">
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"><span style="font-family: 'Comic Sans MS'">内存的段页式管理的优缺点？</span></p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"><span style="font-family: 'Comic Sans MS'">分段：</span></p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"><span style="font-family: 'Comic Sans MS'">在段式存储管理中，将程序的地址空间（进程地址空间）划分为若干个段(segment)，这样每个进程都有一个二维的地址空间，相互独立，互不干扰。程序通过分段来划分为多个模块，如代码段、数据段、共享段等，这样做的优点是：可以分别编译源程序的一个文件，并且可以针对不同类型的段采取不同的保护，也可以按段为单位进行共享。段式存储管理的优点是：没有内碎片，外碎片可以通过内存紧缩来消除，便于实现内存共享。</span></p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"><span style="font-family: 'Comic Sans MS'"><br /></span></p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"><span style="font-family: 'Comic Sans MS'">分页：将程序的逻辑地址空间划分为固定大小的页 (page)，而物理内存划分为同样大小的页框(pageframe)。程序加载时，可以将任意一页放入内存中的任意一个页框，这些页框不必连续，从而实现了离散分配。这种管理的优势是：没有外碎片，且一个程序不必连续存放，这样就便于更改程序占用的空间大小。</span></p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"><span style="font-family: 'Comic Sans MS'">页式 和 段式系统有许多相似之处，比如，两者都采用离散的分配方式，都通过地址映射机构来实现地址变换。但概念上两者是有很多区别的，主要表现在：</span></p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"><span style="font-family: 'Comic Sans MS'">[1]、页是信息的物理单位， 段是信息的逻辑单位，每个逻辑单元分为一个段。</span></p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"><span style="font-family: 'Comic Sans MS'">[2]、页大小固定由系统决定，把逻辑地址划分为页号和页内地址两部分，段的长度不固定，且决定于用户编写的程序</span></p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"><span style="font-family: 'Comic Sans MS'">[3]、页式系统地址空间是一维的，即为单一的线性地址空间，程序员只需利用一个标识符，即可表示一个地址。分段的作业地址空间是二维的，程序员在标识一个地址时，既需给出段名，又需给出段内地址。</span></p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px" sizset="27" sizcache="0"><span style="font-family: 'Comic Sans MS'" sizset="27" sizcache="0"><a style="color: rgb(202,0,0); text-decoration: none" href="http://dongxicheng.org/os/linux-memory-management-basic/">http://dongxicheng.org/os/linux-memory-management-basic/</a></span><br /></p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"><br /></p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">内存：</p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">（1）虚拟内存： 计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续可用的内存（一块连续完整的地址空间），而实际上，他/她通常被分割成多个物理内存碎片，还有部分占时存储在外部磁盘存储器上，在需要时进行交换数据。与没有虚拟内存技术的系统相比，使用这种技术的系统使得大型程序编写变得更容易，对真正的物理内存使用的更有效率。</p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">（2）物理内存：实际的内存，物理地址被分成离散的单元，称为页，页面大小是跟操作系统的位数有关系，一般为4K</p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"><br /></p></blockquote>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px">7、程序内存分区</p>
<p style="padding-bottom: 0px; margin-top: 0px; margin-bottom: 0px; padding-top: 0px"></p>
<blockquote style="border-bottom-style: none; padding-bottom: 0px; border-right-style: none; margin: 0px 0px 0px 40px; padding-left: 0px; padding-right: 0px; border-top-style: none; border-left-style: none; padding-top: 0px">
<p style="padding-bottom: 0px; line-height: 26px; margin-top: 0px; font-family: Arial; margin-bottom: 0px; font-size: 14px; padding-top: 0px">5个分区：</p>
<p style="padding-bottom: 0px; line-height: 26px; margin-top: 0px; font-family: Arial; margin-bottom: 0px; font-size: 14px; padding-top: 0px">堆区：用户在这进行动态内存分配区，</p>
<p style="padding-bottom: 0px; line-height: 26px; margin-top: 0px; font-family: Arial; margin-bottom: 0px; font-size: 14px; padding-top: 0px">栈区：系统自动分配，自动回收，速度快，效率高，但是栈区比较小，小心 栈溢出</p>
<p style="padding-bottom: 0px; line-height: 26px; margin-top: 0px; font-family: Arial; margin-bottom: 0px; font-size: 14px; padding-top: 0px">全局区： &nbsp;存储全局变量和静态变量，</p>
<p style="padding-bottom: 0px; line-height: 26px; margin-top: 0px; font-family: Arial; margin-bottom: 0px; font-size: 14px; padding-top: 0px">文字常量区：常量字符串就存储在这，程序结束后，由系统同一释放。</p>
<p style="padding-bottom: 0px; line-height: 26px; margin-top: 0px; font-family: Arial; margin-bottom: 0px; font-size: 14px; padding-top: 0px">程序代码区：存放程序的二进制代码。</p></blockquote><img src ="http://www.cnitblog.com/schkui/aggbug/87416.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/schkui/" target="_blank">易道</a> 2013-05-15 10:52 <a href="http://www.cnitblog.com/schkui/archive/2013/05/15/87416.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux 串口编程 主要代码 </title><link>http://www.cnitblog.com/schkui/archive/2013/03/22/87134.html</link><dc:creator>易道</dc:creator><author>易道</author><pubDate>Fri, 22 Mar 2013 03:57:00 GMT</pubDate><guid>http://www.cnitblog.com/schkui/archive/2013/03/22/87134.html</guid><wfw:comment>http://www.cnitblog.com/schkui/comments/87134.html</wfw:comment><comments>http://www.cnitblog.com/schkui/archive/2013/03/22/87134.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/schkui/comments/commentRss/87134.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/schkui/services/trackbacks/87134.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->&nbsp;&nbsp;1#include&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;stdio.h&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...&nbsp;&nbsp;<a href='http://www.cnitblog.com/schkui/archive/2013/03/22/87134.html'>阅读全文</a><img src ="http://www.cnitblog.com/schkui/aggbug/87134.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/schkui/" target="_blank">易道</a> 2013-03-22 11:57 <a href="http://www.cnitblog.com/schkui/archive/2013/03/22/87134.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]在Linux下产生并调试core文件</title><link>http://www.cnitblog.com/schkui/archive/2008/03/05/40513.html</link><dc:creator>易道</dc:creator><author>易道</author><pubDate>Wed, 05 Mar 2008 04:09:00 GMT</pubDate><guid>http://www.cnitblog.com/schkui/archive/2008/03/05/40513.html</guid><wfw:comment>http://www.cnitblog.com/schkui/comments/40513.html</wfw:comment><comments>http://www.cnitblog.com/schkui/archive/2008/03/05/40513.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/schkui/comments/commentRss/40513.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/schkui/services/trackbacks/40513.html</trackback:ping><description><![CDATA[转载自: <a href="http://blog.china-pub.com/more.asp?name=uniware&amp;id=35478" target="_blank">http://blog.china-pub.com/more.asp?name=uniware&amp;id=35478</a>
<p>uname -a<br>Linux dev 2.4.21-9.30AXsmp #1 SMP Wed May 26 23:37:09 EDT 2004 i686 i686 i386 GNU/Linux</p>
<p><br></p>
<p>再看看默认的一些参数，注意core file size是个0，程序出错时不会产生core文件了。</p>
<p>$ ulimit -a<br>core file size (blocks, -c) 0<br>data seg size (kbytes, -d) unlimited<br>file size (blocks, -f) unlimited<br>max locked memory (kbytes, -l) 4<br>max memory size (kbytes, -m) unlimited<br>open files (-n) 2048<br>pipe size (512 bytes, -p) 8<br>stack size (kbytes, -s) 10240<br>cpu time (seconds, -t) unlimited<br>max user processes (-u) 7168<br>virtual memory (kbytes, -v) unlimited</p>
<p>写个简单的程序，看看core文件是不是会被产生。</p>
<p>$ more foo.c</p>
<p>#include <stdio.h></stdio.h></p>
<p>static void sub(void);</p>
<p>int main(void)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;sub();<br>&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br>}</p>
<p>static void sub(void)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;int *p = NULL;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;/* derefernce a null pointer, expect core dump. */<br>&nbsp;&nbsp;&nbsp;&nbsp;printf("%d", *p);<br>}</p>
<p>$ gcc -Wall -g foo.c<br>$ ./a.out<br>Segmentation fault</p>
<p>$ ls -l core.*<br>ls: core.*: No such file or directory</p>
<p>没有找到core文件，我们改改ulimit的设置，让它产生。1024是随便取的，要是core文件大于1024个块，就产生不出来了。</p>
<p>$ ulimit -c 1024</p>
<p>$ ulimit -a<br>core file size (blocks, -c) 1024<br>data seg size (kbytes, -d) unlimited<br>file size (blocks, -f) unlimited<br>max locked memory (kbytes, -l) 4<br>max memory size (kbytes, -m) unlimited<br>open files (-n) 2048<br>pipe size (512 bytes, -p) 8<br>stack size (kbytes, -s) 10240<br>cpu time (seconds, -t) unlimited<br>max user processes (-u) 7168<br>virtual memory (kbytes, -v) unlimited</p>
<p>$ ./a.out<br>Segmentation fault (core dumped)<br>$ ls -l core.*<br>-rw------- 1 uniware uniware 53248 Jun 30 17:10 core.9128</p>
<p>注意看上述的输出信息，多了个(core dumped)。确实产生了一个core文件，9128是该进程的PID。我们用GDB来看看这个core。</p>
<p>$ gdb --core=core.9128<br>GNU gdb Asianux (6.0post-0.20040223.17.1AX)<br>Copyright 2004 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. Type "show warranty" for details.<br>This GDB was configured as "i386-asianux-linux-gnu".<br>Core was generated by `./a.out'.<br>Program terminated with signal 11, Segmentation fault.<br>#0 0x08048373 in ?? ()<br>(gdb) bt<br>#0 0x08048373 in ?? ()<br>#1 0xbfffd8f8 in ?? ()<br>#2 0x0804839e in ?? ()<br>#3 0xb74cc6b3 in ?? ()<br>#4 0x00000000 in ?? ()<br><br>此时用bt看不到backtrace，也就是调用堆栈，原来GDB还不知道符号信息在哪里。我们告诉它一下：</p>
<p>(gdb) file ./a.out<br>Reading symbols from ./a.out...done.<br>Using host libthread_db library "/lib/tls/libthread_db.so.1".<br>(gdb) bt<br>#0 0x08048373 in sub () at foo.c:17<br>#1 0x08048359 in main () at foo.c:8<br><br>此时backtrace出来了。</p>
<p>(gdb) l<br>8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sub();<br>9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>10&nbsp;&nbsp;&nbsp;&nbsp; }<br>11<br>12 &nbsp;&nbsp;&nbsp;&nbsp;static void sub(void)<br>13 &nbsp;&nbsp;&nbsp;&nbsp;{<br>14 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int *p = NULL;<br>15<br>16 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* derefernce a null pointer, expect core dump. */<br>17 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("%d", *p);<br>(gdb)</p>
<br> <img src ="http://www.cnitblog.com/schkui/aggbug/40513.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/schkui/" target="_blank">易道</a> 2008-03-05 12:09 <a href="http://www.cnitblog.com/schkui/archive/2008/03/05/40513.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]用gdbserver调试共享库.txt</title><link>http://www.cnitblog.com/schkui/archive/2008/03/05/40509.html</link><dc:creator>易道</dc:creator><author>易道</author><pubDate>Wed, 05 Mar 2008 03:34:00 GMT</pubDate><guid>http://www.cnitblog.com/schkui/archive/2008/03/05/40509.html</guid><wfw:comment>http://www.cnitblog.com/schkui/comments/40509.html</wfw:comment><comments>http://www.cnitblog.com/schkui/archive/2008/03/05/40509.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/schkui/comments/commentRss/40509.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/schkui/services/trackbacks/40509.html</trackback:ping><description><![CDATA[在开发嵌入式系统时，调试往往是一大难题。面试过不少嵌入式linux工程师，当问及调试手段时，他们的调试手段一般是两种：首先是在PC上的模拟环境中运行，若有问题，可以很方便的调试。其次，若在板子上运行时才出错，就用printf输出log信息，根据log信息定位错误。有少部分人用gdbserver调试板子上的程序，但问到如何在共享库里设置断点时，都说没有办法。<br><br>&nbsp;&nbsp;&nbsp; 去年，Tinyx的一个内存越界BUG，花了我2天时间。gcc的一个浮点数BUG让我查了3天时间。这类BUG在PC上根本重现不了，在板子上用printf要花费大量的时间才能把错误的范围缩小一点。后来想了想，与其花时间去加printf，还不如把gdbserver调试共享库的问题解决了，可以为以后的调试节省不少时间。<br><br>&nbsp;&nbsp;&nbsp; 在网上找了半天资料，没有什么收获，看来只好自己动手研究。花了一个周末的时间去研究gdbserver的运行方式。办法是找到了，不过仍然有点麻烦，等有时间了，修改一下gdb的代码，把这个过程自动化了。<br><br>&nbsp;&nbsp;&nbsp; 先调试运行gdbserver，对gdbserver有了一些感性认识，然后研究linux-low.c中的代码。原来，设置断点只是在对应的内存中写入断点指令（x86上为0xcc）。<br><br>&nbsp;&nbsp;&nbsp; gdbserver为什么不能在共享库中设置断点呢？设置断点只是写内存，调试时，所有的代码段都是可写的，在exe中可以设置断点，没有理由不让在共享库中设置啊。所以这应该与是否是共享库关系不大。<br><br>&nbsp;&nbsp;&nbsp; 猜测可能是符号与地址对应关系有误，如果你的本意为function1设置断点，结果gdb搞错了，设置一个毫不相干的地方，可能永远都不会执行到那里，这个断点自然没什么效果。<br><br>&nbsp;&nbsp;&nbsp; 如果是这样，有两种方法可以解决：要么手动计算符号的地址，再设置断点，当然这样太累。另外就让gdb自动对应起来。经过反得尝试，用下列方法可以在共享库中设置断点，虽然有点麻烦，还是可行的。<br><br>1. 准备工作，编写下面几个文件：<br><br>test.c:<br>#include <br>int test(int a, int b)<br>{<br>int s = a + b;<br>printf("%d\n", s);<br>return s;<br>}<br><br>main.c:<br>#include <br>extern int test(int a, int b);<br>int main(int argc, char* argv[])<br>{<br>int s = test(10, 20);<br>return s;<br>}<br><br>Makefile:<br>all: so main<br>so:<br>gcc -g test.c -shared -o libtest.so<br>main:<br>gcc -g main.c -L./ -ltest -o test.exe<br>clean:<br>rm -f *.exe *.so<br><br>（为了便于演示，整个过程在PC上测试，后来证实在实验板上能够正常工作）<br><br>2. 编译并设置环境变量<br>make<br>export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./<br><br>3. 运行gdbserver<br>gdbserver localhost:2000 ./test.exe<br><br>4. 运行gdb客户端<br>gdb<br>symbol-file test.exe<br>target remote localhost:2000<br>b main<br>c<br><br>5. 查看libtest.so的代码在内存中的位置。<br>（从gdbserver的输出或者用ps可以得到test.exe的进程ID，这里假设PID是11547）<br>cat /proc/11547/maps<br>输出：<br><br>00624000-0063e000 r-xp 00000000 03:01 718192 /lib/ld-2.3.5.so<br>0063e000-0063f000 r-xp 00019000 03:01 718192 /lib/ld-2.3.5.so<br>0063f000-00640000 rwxp 0001a000 03:01 718192 /lib/ld-2.3.5.so<br>00642000-00766000 r-xp 00000000 03:01 718193 /lib/libc-2.3.5.so<br>00766000-00768000 r-xp 00124000 03:01 718193 /lib/libc-2.3.5.so<br>00768000-0076a000 rwxp 00126000 03:01 718193 /lib/libc-2.3.5.so<br>0076a000-0076c000 rwxp 0076a000 00:00 0 <br>00bbe000-00bbf000 r-xp 00bbe000 00:00 0 <br>00fcc000-00fcd000 r-xp 00000000 03:01 1238761 /root/test/gdbservertest/libtest.so<br>00fcd000-00fce000 rwxp 00000000 03:01 1238761 /root/test/gdbservertest/libtest.so<br>08048000-08049000 r-xp 00000000 03:01 1238765 /root/test/gdbservertest/test.exe<br>08049000-0804a000 rw-p 00000000 03:01 1238765 /root/test/gdbservertest/test.exe<br>b7f8a000-b7f8b000 rw-p b7f8a000 00:00 0 <br>b7f99000-b7f9a000 rw-p b7f99000 00:00 0 <br>bfd85000-bfd9a000 rw-p bfd85000 00:00 0 [stack]<br><br>由此可以知道：libtest.so的代码在00fcc000-00fcd000之间。<br><br>6. 查看libtest.so的.text段在内存中的偏移位置：<br>objdump -h libtest.so |grep .text<br>输出：<br>9 .text 00000130 00000450 00000450 00000450 2**4<br>即偏移位置为0x00000450<br><br>7. 回到gdb窗口，加载libtest.so的符号表。<br>add-symbol-file libtest.so 0x00fcc450<br>(这里0x00fcc450 = 0x00fcc000 0x00000450)<br><br>8. 在共享库的函数中设置断点。<br>b test<br><br>9. 继续调试，可以发现在共享库中设置的断点，能够正常工作。<br>这个方法仍然有点麻烦，写在这里算抛砖引玉吧，望大家不吝赐教，谢谢。<br><br>http://www.dzkf.cn/html/qianrushixitong/2007/0626/2293.html
<br><img src ="http://www.cnitblog.com/schkui/aggbug/40509.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/schkui/" target="_blank">易道</a> 2008-03-05 11:34 <a href="http://www.cnitblog.com/schkui/archive/2008/03/05/40509.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> 转， 基于英文单词的快速HASH索引算法。</title><link>http://www.cnitblog.com/schkui/archive/2007/07/02/29322.html</link><dc:creator>易道</dc:creator><author>易道</author><pubDate>Mon, 02 Jul 2007 01:32:00 GMT</pubDate><guid>http://www.cnitblog.com/schkui/archive/2007/07/02/29322.html</guid><wfw:comment>http://www.cnitblog.com/schkui/comments/29322.html</wfw:comment><comments>http://www.cnitblog.com/schkui/archive/2007/07/02/29322.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/schkui/comments/commentRss/29322.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/schkui/services/trackbacks/29322.html</trackback:ping><description><![CDATA[<br>
<div class="postText">
<div class="Section1">
<p>因为有项目需要，要做一个类似ispell
的软件，其中会产生大量的对单词的查找操作，于是经过一翻研究，得出以下HASH算法，经过验证比一般的查表的FNV
HASH算法产生的分布曲线基本没什么两样，并且在大部分的不同字典下，本算法要比查表的FNV
HASH算法表现出速度更快，分布更均匀。但是因为是实验结果，所以暂时还没得出有效的数学推论，但是从大量的不同的字典测试数据来看，此算法确实效率不
错。<br><br>由于以前没有涉及过相关的纯算法的设计，所以刚刚开始的时候，打算随便选用一种HASH，比如说用%除大质数，然后借此搭建一个比较强壮的测试环境，然后打算根据测试结果来改进HASH算法的模型。<br><br>最开始，我的HASH函数是这样的：<br>unsigned int hash_func(char *str, int len)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;register unsigned int sum = 0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;register char *p = str;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(p - str &lt; len)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sum += *(p++);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;sum % MAX_PRIME_LESS_THAN_HASH_LEN;<br>}<br>非常简单，但是这是绝对不可取的，通过这个函数，我选取了一个23w词的字典做为测试，当HASH SIZE=1024的时候，得到了以下的图象：<br></p>
<p><img alt="" src="http://tarkey.kmip.net/image001.gif" align="bottom" border="0" hspace="0"><br>看得出震荡幅度相当大，那么如何来改进呢？首先想到可能产生的冲突的是这种情况：abcd和acbd，对于这两种单词来说，如果用上面的HASH函数，就一定会发生碰撞，为什么呢？因为每个字符少了关于它自己的位置信息，于是第一次改进版本的HASH函数就给每个字符加上了它的位置信息，将上面所描述的函数改进为：</p>
<p>unsigned int hash_func(char *str, int len)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;register unsigned int sum = 0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;register char *p = str;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(p - str &lt; len)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sum += *(p++) * (p&#8211;str);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;sum % MAX_PRIME_LESS_THAN_HASH_LEN;<br>} <br>得到以下图象：</p>
<p>&#160;</p>
<p><img alt="" src="http://tarkey.kmip.net/image002.gif" align="bottom" border="0" hspace="0"><br>某种程度上来说，比不带位置信息产生的分布图要好多了，但是仍然非常的不均匀。那么接来分析产生分布不均匀的原因，因为是用的乘法，所以仍然太过于依赖字母产生的结果了。于是改用XOR操作，选用以下函数：</p>
<p>unsigned int hash_func(char *str, int len)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;register unsigned int sum = 0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;register char *p = str;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(p - str &lt; len)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sum += (*(p++) * (p&#8211;str)) ^ sum;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;sum % MAX_PRIME_LESS_THAN_HASH_LEN;<br>} <br>得到以下图象：</p>
<p>&nbsp;<img alt="" src="http://tarkey.kmip.net/image003.gif" align="bottom" border="0" hspace="0"></p>
<p>&#160;</p>
<p>上图虽然震荡幅度比较，不过做出来的regression
line明显比上两张图片平得多了。但是结果仍然非常不好，从800到100的range太大。原因还是因为数据分布得不够均匀，于是思考单独的用加法来
算是不是不太好，根据其他查表类HASH算法的过程，发现其大多都用了高低位来组合成最后的结果，于是我也采用了他们的方法：</p>
<p>unsigned int hash_func(char *str, int len)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;register unsigned int sum = 0; <br>&nbsp;&nbsp;&nbsp;&nbsp; register unsigned int h = 0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;register char *p =&nbsp;str;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(p - s &lt; len) <br>&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;register unsigned short a = *(p++);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sum ^=&nbsp; a * (p - str); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; h ^= a&nbsp;/ (p - str);<br>&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;((sum &lt;&lt; 16) | h) % MAX_PRIME_LESS_THAN_HASH_LEN;<br>}</p>
<p>得到最终近似完美的图象：</p>
<p>&#160;</p>
<p>&nbsp;<img alt="" src="http://tarkey.kmip.net/image004.gif" align="bottom" border="0" hspace="0"></p>
<p>最后得出结论，不用查表的方法，而通过字符串本身的位置对字符本身进行修正的方法也能得到结果相当满意的HASH函数，之后换了几个大小不同的字典进行测试，得出的图象都大致和上图一致，非常令人满意。对于这个项目，包括如何检查单词错误，和自动修正等等相关的内容，会随着项目的完成一一在整理成文档，希望大家支持。</p>
</div>
<br><br>
<p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=167909</p>
</div>
<br><br><img src ="http://www.cnitblog.com/schkui/aggbug/29322.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/schkui/" target="_blank">易道</a> 2007-07-02 09:32 <a href="http://www.cnitblog.com/schkui/archive/2007/07/02/29322.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> 若干经典的字符串哈希函数</title><link>http://www.cnitblog.com/schkui/archive/2007/07/02/29320.html</link><dc:creator>易道</dc:creator><author>易道</author><pubDate>Mon, 02 Jul 2007 01:17:00 GMT</pubDate><guid>http://www.cnitblog.com/schkui/archive/2007/07/02/29320.html</guid><wfw:comment>http://www.cnitblog.com/schkui/comments/29320.html</wfw:comment><comments>http://www.cnitblog.com/schkui/archive/2007/07/02/29320.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/schkui/comments/commentRss/29320.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/schkui/services/trackbacks/29320.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: // &nbsp;RS&nbsp;Hash&nbsp;Function  unsigned&nbsp; int &nbsp;RSHash( char &nbsp; * str)  {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp; int &nbsp;b&nbsp; = &nbsp; 378551 ;&nbsp;&nbsp...&nbsp;&nbsp;<a href='http://www.cnitblog.com/schkui/archive/2007/07/02/29320.html'>阅读全文</a><img src ="http://www.cnitblog.com/schkui/aggbug/29320.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/schkui/" target="_blank">易道</a> 2007-07-02 09:17 <a href="http://www.cnitblog.com/schkui/archive/2007/07/02/29320.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> C语言中用bsearch()实现查找操作</title><link>http://www.cnitblog.com/schkui/archive/2007/06/19/28742.html</link><dc:creator>易道</dc:creator><author>易道</author><pubDate>Tue, 19 Jun 2007 03:18:00 GMT</pubDate><guid>http://www.cnitblog.com/schkui/archive/2007/06/19/28742.html</guid><wfw:comment>http://www.cnitblog.com/schkui/comments/28742.html</wfw:comment><comments>http://www.cnitblog.com/schkui/archive/2007/06/19/28742.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/schkui/comments/commentRss/28742.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/schkui/services/trackbacks/28742.html</trackback:ping><description><![CDATA[C语言中可以用bsearch()实现二分查找。同qsort()一样，bsearch()也包含在&lt;stdlib.h&gt;库中，且同样要自定义比较子函数。其原型如下：<br>
<p style="margin: 5px; line-height: 150%;"><code>void *bsearch(const void *key, const void *base, size_t nmem, size_t size, int (*comp)(const void *, const void *));</code></p>
<p style="margin: 5px; line-height: 150%;"><br><code></code></p>
<p>key指向所要查找的元素，base指向进行查找的数组，nmem为查找长度，一般为数组长度，size为每个元素所占的字节数，一般用sizeof(...)表示，comp指向比较子函数，它定义比较的规则。需要注意的是，<font color="#0000ff">数据必须是经过预先排序的，而排序的规则要和comp所指向比较子函数的规则相同。</font>如果查找成功则返回数组中匹配元素的地址，反之则返回空。对于有多于一个的元素匹配成功的情况，bsearch()未定义返回哪一个。</p>
<p>例：</p>
<table style="border-collapse: collapse;" bgcolor="#f1f1f1" border="1" bordercolor="#999999" cellpadding="0" cellspacing="0" width="95%">
    <tbody>
        <tr>
            <td>
            <p style="margin: 5px; line-height: 150%;"><code>#include &lt;stdio.h&gt;<br>#include &lt;stdlib.h&gt;<br><br>#define NUM 8<br><br>int compare(const void *p, const void *q)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;return (*(int *)p - *(int *)q);<br>}<br><br>int main(int argc, char *argv[])<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;int array[NUM] = {9, 2, 7, 11, 3, 87, 34, 6};<br>&nbsp;&nbsp;&nbsp;&nbsp;int key = 3;<br>&nbsp;&nbsp;&nbsp;&nbsp;int *p;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;qsort(array, NUM, sizeof(int), compare);<br>&nbsp;&nbsp;&nbsp;&nbsp;p = (int *)bsearch(&amp;key, array, NUM, sizeof(int), compare);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;(p == NULL) ? puts("not found") : puts("found");<br><br>&nbsp;&nbsp;&nbsp;&nbsp;return 0;<br>}</code></p>
            </td>
        </tr>
    </tbody>
</table>
<p>结果如下：</p>
<p style="margin: 5px; line-height: 150%;">found</p>
<br>
<br><img src ="http://www.cnitblog.com/schkui/aggbug/28742.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/schkui/" target="_blank">易道</a> 2007-06-19 11:18 <a href="http://www.cnitblog.com/schkui/archive/2007/06/19/28742.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c语言和脚本编程 </title><link>http://www.cnitblog.com/schkui/archive/2007/05/29/27749.html</link><dc:creator>易道</dc:creator><author>易道</author><pubDate>Tue, 29 May 2007 09:43:00 GMT</pubDate><guid>http://www.cnitblog.com/schkui/archive/2007/05/29/27749.html</guid><wfw:comment>http://www.cnitblog.com/schkui/comments/27749.html</wfw:comment><comments>http://www.cnitblog.com/schkui/archive/2007/05/29/27749.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/schkui/comments/commentRss/27749.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/schkui/services/trackbacks/27749.html</trackback:ping><description><![CDATA[#include &lt;stdio.h&gt;<br>#include &lt;stdlib.h&gt;<br>#include &lt;unistd.h&gt;<br>#include &lt;stdio.h&gt;<br>#include &lt;string.h&gt;<br><br><br>int main()<br>{<br>#define RECV_BUF&nbsp;&nbsp; &nbsp;1024<br>&nbsp;&nbsp; &nbsp;int fd[2] ;<br>&nbsp;&nbsp;&nbsp; char _recv_buf[RECV_BUF&nbsp;&nbsp; &nbsp;] ;&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; memset(_recv_buf,0, RECV_BUF&nbsp;&nbsp; &nbsp;) ;<br><br>&nbsp;&nbsp; &nbsp;if(pipe(fd))&nbsp;&nbsp; &nbsp;<br>&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; return -1 ;<br>&nbsp;&nbsp; &nbsp;}<br>&nbsp;&nbsp; <br>&nbsp; 将输出于写管道建立关联, system的屏幕输出到fd[1],&nbsp; ,可以在fd[0] 读取数据&nbsp;  <br>&nbsp;&nbsp; &nbsp;close(1) ;<br>&nbsp;&nbsp;&nbsp; dup2(fd[1] ,1) ;&nbsp;&nbsp; <br>&nbsp;&nbsp; &nbsp;close(fd[1]) ;<br><br><br>&nbsp;&nbsp; &nbsp;//sed -n '/eth0/p' /proc/net/dev | awk '{print $1, $2}' | sed -n 's/eth0://p<br>&nbsp;&nbsp; &nbsp;// mpstat | sed -n '$p'| awk '{print $9}'<br><br><br><br>&nbsp;&nbsp; &nbsp;system("sed -n '1,2p' /proc/meminfo&nbsp; |awk '{print $2} '") ;<br>&nbsp;&nbsp;&nbsp; // 从读管道读入数据&nbsp; <br>&nbsp;&nbsp; &nbsp;read(fd[0], _recv_buf, RECV_BUF);&nbsp;&nbsp;&nbsp; <br><br>&nbsp;&nbsp;&nbsp; // 显示 到屏幕&nbsp; <br>&nbsp; &nbsp; write(2 ,&nbsp; _recv_buf, strlen(_recv_buf)) ;&nbsp; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; // 关闭读 管道<br>&nbsp;&nbsp; &nbsp;close(fd[0]) ;&nbsp;&nbsp;&nbsp; <br><br><br>&nbsp;&nbsp; &nbsp;return 0 ;<br>}<br><br>    <img src ="http://www.cnitblog.com/schkui/aggbug/27749.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/schkui/" target="_blank">易道</a> 2007-05-29 17:43 <a href="http://www.cnitblog.com/schkui/archive/2007/05/29/27749.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux 内存调试工具- Valgrind 使用初探</title><link>http://www.cnitblog.com/schkui/archive/2007/04/20/25944.html</link><dc:creator>易道</dc:creator><author>易道</author><pubDate>Fri, 20 Apr 2007 09:58:00 GMT</pubDate><guid>http://www.cnitblog.com/schkui/archive/2007/04/20/25944.html</guid><wfw:comment>http://www.cnitblog.com/schkui/comments/25944.html</wfw:comment><comments>http://www.cnitblog.com/schkui/archive/2007/04/20/25944.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/schkui/comments/commentRss/25944.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/schkui/services/trackbacks/25944.html</trackback:ping><description><![CDATA[<stdlib.h><br>
<div id="fontzoom" class="content">
<p>&nbsp; Valgrind 是在linux系统下开发应用程序时用于调试内存问题的工具。它尤其擅长发现内存管理的问题，它可以检查程序运行时的内存泄漏问题。
</p>
<p>&nbsp;&nbsp; 它的官方网址是 <a href="http://www.valgrind.org/"><u>http://www.valgrind.org/</u></a></p>
<p>&nbsp;&nbsp; 下载最新版本的Valgrind，目前是3.2.0。 wget <a href="http://www.valgrind.org/downloads/valkyrie-1.2.0.tar.bz2"><u>http://www.valgrind.org/downloads/valkyrie-1.2.0.tar.bz2</u></a></p>
<p>&nbsp;&nbsp; 执行常规的安装步骤：./confgure &amp;&amp; make &amp;&amp; make install。注意：
系统必须安装QT的开发包。即便这样在make
时还是出现qplatformdefs.h这个文件找不到的情况，导致make失败。查找系统中的qplatformdefs.h
之后，发现没有存在于qt的标准头文件目录/usr/lib/qt-3.3/include。如是将/usr/lib/qt-
3.3/mkspecs/linux-g++/ 目录下该头文件复制标准头文件目录，重新make ，后面一切OK。</p>
<pre class="programlisting">初次使用</pre>
<pre class="programlisting">    编译如下代码:  gcc -Wall example.c -g -o example </pre>
<p>
<table style="border: 1px solid #999999; font-size: 12px; width: 80%;" align="center">
    <tbody>
        <tr>
            <td>
            <pre class="programlisting">#include &lt;stdlib.h&gt;<br><br>void f(void)<br>{<br>   int* x = malloc(10 * sizeof(int));<br>   x[10] = 0;        // problem 1: heap block overrun<br>}                    // problem 2: memory leak -- x not freed<br><br>int main(void)<br>{<br>     f();<br>     return 0;<br>}</pre>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 注意：gcc 的-g 选项让Valgrind调试输出时指出相应信息的代码所在的行号。</p>
<p>&nbsp;
<table style="border: 1px solid #999999; font-size: 12px; width: 94.47%; height: 24px;" align="center">
    <tbody>
        <tr>
            <td>valgrind --tool=memcheck --leak-check=yes&nbsp;./example</td>
        </tr>
    </tbody>
</table>
</p>
<p>
<table style="border: 1px solid #999999; font-size: 12px; width: 97.36%; height: 23px;" align="center">
    <tbody>
        <tr>
            <td>==6742== Memcheck, a memory error detector for x86-linux.<br>==6742== Copyright (C) 2002-2004, and GNU GPL'd, by Julian Seward et al.<br>==6742== Using valgrind-2.2.0, a program supervision framework for x86-linux.<br>==6742== Copyright (C) 2000-2004, and GNU GPL'd, by Julian Seward et al.<br>==6742== For more details, rerun with: -v<br>==6742== <br>==6742== Invalid write of size 4<br>==6742==&nbsp;&nbsp;&nbsp; at 0x8048384: f (example.c:6)<br>==6742==&nbsp;&nbsp;&nbsp; by 0x80483AC: main (example.c:12)<br>==6742==&nbsp; Address 0x1B908050 is 0 bytes after a block of size 40 alloc'd<br>==6742==&nbsp;&nbsp;&nbsp; at 0x1B904984: malloc (vg_replace_malloc.c:131)<br>==6742==&nbsp;&nbsp;&nbsp; by 0x8048377: f (example.c:5)<br>==6742==&nbsp;&nbsp;&nbsp; by 0x80483AC: main (example.c:12)<br>==6742== <br>==6742== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 12 from 1)<br>==6742== malloc/free: in use at exit: 40 bytes in 1 blocks.<br>==6742== malloc/free: 1 allocs, 0 frees, 40 bytes allocated.<br>==6742== For counts of detected errors, rerun with: -v<br>==6742== searching for pointers to 1 not-freed blocks.<br>==6742== checked 1360800 bytes.<br>==6742== <br>==6742== <br>==6742== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1<br>==6742==&nbsp;&nbsp;&nbsp; at 0x1B904984: malloc (vg_replace_malloc.c:131)<br>==6742==&nbsp;&nbsp;&nbsp; by 0x8048377: f (example.c:5)<br>==6742==&nbsp;&nbsp;&nbsp; by 0x80483AC: main (example.c:12)<br>==6742== <br>==6742== LEAK SUMMARY:<br>==6742==&nbsp;&nbsp;&nbsp; definitely lost: 40 bytes in 1 blocks.<br>==6742==&nbsp;&nbsp;&nbsp; possibly lost:&nbsp;&nbsp; 0 bytes in 0 blocks.<br>==6742==&nbsp;&nbsp;&nbsp; still reachable: 0 bytes in 0 blocks.<br>==6742==&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; suppressed: 0 bytes in 0 blocks.<br>==6742== Reachable blocks (those to which a pointer was found) are not shown.<br>==6742== To see them, rerun with: --show-reachable=yes</td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;&nbsp; 上面的C程序存在两个错误：1. 数组下标越界；2. 分配的内存没有释放，存在内存泄露的问题。对于错误1，看Valgrind的调试信息片断
<table style="border: 1px solid #999999; font-size: 12px; width: 98.6%; height: 23px;" align="center">
    <tbody>
        <tr>
            <td>==6742== Invalid write of size 4<br>==6742==&nbsp;&nbsp;&nbsp; at 0x8048384: f (example.c:6)<br>==6742==&nbsp;&nbsp;&nbsp; by 0x80483AC: main (example.c:12)<br>==6742==&nbsp; Address 0x1B908050 is 0 bytes after a block of size 40 alloc'd<br>==6742==&nbsp;&nbsp;&nbsp; at 0x1B904984: malloc (vg_replace_malloc.c:131)<br>==6742==&nbsp;&nbsp;&nbsp; by 0x8048377: f (example.c:5)</td>
        </tr>
    </tbody>
</table>
</p>
<p>对于错误2，看这个
<table style="border: 1px solid #999999; font-size: 12px; width: 97.36%; height: 56px;" align="center">
    <tbody>
        <tr>
            <td>
            <p>==6742== malloc/free: 1 allocs, 0 frees, 40 bytes allocated.</p>
            <p>......</p>
            <p>==6742== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1<br>==6742==&nbsp;&nbsp;&nbsp; at 0x1B904984: malloc (vg_replace_malloc.c:131)<br>==6742==&nbsp;&nbsp;&nbsp; by 0x8048377: f (example.c:5)<br>==6742==&nbsp;&nbsp;&nbsp; by 0x80483AC: main (example.c:12)</p>
            </td>
        </tr>
    </tbody>
</table>
</p>
<p>&nbsp;</p>
<p>&nbsp;相关链接：</p>
<p>&nbsp;&nbsp; <a href="http://www.valgrind.org/docs/manual/quick-start.html"><u>http://www.valgrind.org/docs/manual/quick-start.html</u></a></p>
<p>&nbsp;&nbsp; <a href="http://www-128.ibm.com/developerworks/cn/linux/l-pow-debug/"><u>http://www-128.ibm.com/developerworks/cn/linux/l-pow-debug/</u></a></p>
<p>&nbsp;</p>
</div>
</stdlib.h><img src ="http://www.cnitblog.com/schkui/aggbug/25944.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/schkui/" target="_blank">易道</a> 2007-04-20 17:58 <a href="http://www.cnitblog.com/schkui/archive/2007/04/20/25944.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转 Linux 2.6内核中提高网络I/O性能的新方法-epoll</title><link>http://www.cnitblog.com/schkui/archive/2007/04/18/25879.html</link><dc:creator>易道</dc:creator><author>易道</author><pubDate>Wed, 18 Apr 2007 08:36:00 GMT</pubDate><guid>http://www.cnitblog.com/schkui/archive/2007/04/18/25879.html</guid><wfw:comment>http://www.cnitblog.com/schkui/comments/25879.html</wfw:comment><comments>http://www.cnitblog.com/schkui/archive/2007/04/18/25879.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/schkui/comments/commentRss/25879.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/schkui/services/trackbacks/25879.html</trackback:ping><description><![CDATA[inux 2.6内核中提高网络I/O性能的新方法-epoll
<div class="date">2007-04-11  18:52</div>
<p>前一阵和同事讨论监控的时候，有同事提出用epool的方式管理线程，为了增长知识查找了一下资料：</p>
<p>1、为什么select是落后的？<br>
首先，在Linux内核中，select所用到的FD_SET是有限的，即内核中有个参数__FD_SETSIZE定义了每个FD_SET的句柄个数，在我用的2.6.15-25-386内核中，该值是1024，搜索内核源代码得到：<br>
include/linux/posix_types.h:#define __FD_SETSIZE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1024<br>
也就是说，如果想要同时检测1025个句柄的可读状态是不可能用select实现的。或者同时检测1025个句柄的可写状态也是不可能的。<br>
其次，内核中实现select是用轮询方法，即每次检测都会遍历所有FD_SET中的句柄，显然，select函数执行时间与FD_SET中的句柄个数有一个比例关系，即select要检测的句柄数越多就会越费时。<br>
当然，在前文中我并没有提及poll方法，事实上用select的朋友一定也试过poll，我个人觉得select和poll大同小异，个人偏好于用select而已。</p>
<p>2、2.6内核中提高I/O性能的新方法epoll</p>
<p>epoll是什么？按照man手册的说法：是为处理大批量句柄而作了改进的poll。要使用epoll只需要这三个系统调用：epoll_create(2)， epoll_ctl(2)， epoll_wait(2)。<br>
当然，这不是2.6内核才有的，它是在2.5.44内核中被引进的(epoll(4) is a new API introduced in Linux kernel 2.5.44)</p>
<p>epoll的优点</p>
<p>&lt;1&gt;支持一个进程打开大数目的socket描述符(FD)</p>
<p>select
最不能忍受的是一个进程所打开的FD是有一定限制的，由FD_SETSIZE设置，默认值是2048。对于那些需要支持的上万连接数目的IM服务器来说显
然太少了。这时候你一是可以选择修改这个宏然后重新编译内核，不过资料也同时指出这样会带来网络效率的下降，二是可以选择多进程的解决方案(传统的
Apache方案)，不过虽然linux上面创建进程的代价比较小，但仍旧是不可忽视的，加上进程间数据同步远比不上线程间同步的高效，所以也不是一种完
美的方案。不过
epoll则没有这个限制，它所支持的FD上限是最大可以打开文件的数目，这个数字一般远大于2048,举个例子,在1GB内存的机器上大约是10万左
右，具体数目可以cat /proc/sys/fs/file-max察看,一般来说这个数目和系统内存关系很大。</p>
<p>&lt;2&gt;IO效率不随FD数目增加而线性下降</p>
<p>传统的select/poll另一个致命弱点就是当你拥有一个很大的socket集合，不过由于网络延时，任一时间只有部分的socket是"活跃
"的，但是select/poll每次调用都会线性扫描全部的集合，导致效率呈现线性下降。但是epoll不存在这个问题，它只会对"活跃"的
socket进行操作---这是因为在内核实现中epoll是根据每个fd上面的callback函数实现的。那么，只有"活跃"的socket才会主动
的去调用
callback函数，其他idle状态socket则不会，在这点上，epoll实现了一个"伪"AIO，因为这时候推动力在os内核。在一些
benchmark中，如果所有的socket基本上都是活跃的---比如一个高速LAN环境，epoll并不比select/poll有什么效率，相
反，如果过多使用epoll_ctl,效率相比还有稍微的下降。但是一旦使用idle
connections模拟WAN环境,epoll的效率就远在select/poll之上了。</p>
<p>&lt;3&gt;使用mmap加速内核与用户空间的消息传递。</p>
<p>这点实际上涉及到epoll的具体实现了。无论是select,poll还是epoll都需要内核把FD消息通知给用户空间，如何避免不必要的内存
拷贝就很重要，在这点上，epoll是通过内核于用户空间mmap同一块内存实现的。而如果你想我一样从2.5内核就关注epoll的话，一定不会忘记手
工 mmap这一步的。</p>
<p>&lt;4&gt;内核微调</p>
<p>这一点其实不算epoll的优点了，而是整个linux平台的优点。也许你可以怀疑linux平台，但是你无法回避linux平台赋予你微调内核的
能力。比如，内核TCP/IP协议栈使用内存池管理sk_buff结构，那么可以在运行时期动态调整这个内存pool(skb_head_pool)的大
小--- 通过echo
XXXX&gt;/proc/sys/net/core/hot_list_length完成。再比如listen函数的第2个参数(TCP完成3次握手
的数据包队列长度)，也可以根据你平台内存大小动态调整。更甚至在一个数据包面数目巨大但同时每个数据包本身大小却很小的特殊系统上尝试最新的NAPI网
卡驱动架构。</p>
<p>epoll的使用</p>
<p>令人高兴的是，2.6内核的epoll比其2.5开发版本的/dev/epoll简洁了许多，所以，大部分情况下，强大的东西往往是简单的。唯一有点麻烦是epoll有2种工作方式:LT和ET。</p>
<p>LT(level triggered)是缺省的工作方式，并且同时支持block和no-block
socket.在这种做法中，内核告诉你一个文件描述符是否就绪了，然后你可以对这个就绪的fd进行IO操作。如果你不作任何操作，内核还是会继续通知你
的，所以，这种模式编程出错误可能性要小一点。传统的select/poll都是这种模型的代表．</p>
<p>ET (edge-triggered)是高速工作方式，只支持no-block
socket。在这种模式下，当描述符从未就绪变为就绪时，内核通过epoll告诉你。然后它会假设你知道文件描述符已经就绪，并且不会再为那个文件描述
符发送更多的就绪通知，直到你做了某些操作导致那个文件描述符不再为就绪状态了(比如，你在发送，接收或者接收请求，或者发送接收的数据少于一定量时导致
了一个EWOULDBLOCK 错误）。但是请注意，如果一直不对这个fd作IO操作(从而导致它再次变成未就绪)，内核不会发送更多的通知(only
once),不过在TCP协议中，ET模式的加速效用仍需要更多的benchmark确认。</p>
<p>epoll只有epoll_create,epoll_ctl,epoll_wait 3个系统调用，具体用法请参考<a href="http://www.xmailserver.org/linux-patches/nio-improve.html">http://www.xmailserver.org/linux-patches/nio-improve.html</a> ，<br>
在<a href="http://www.kegel.com/rn/">http://www.kegel.com/rn/</a>也有一个完整的例子，大家一看就知道如何使用了</p>
Leader/follower模式线程pool实现，以及和epoll的配合&nbsp; <br><br><img src ="http://www.cnitblog.com/schkui/aggbug/25879.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/schkui/" target="_blank">易道</a> 2007-04-18 16:36 <a href="http://www.cnitblog.com/schkui/archive/2007/04/18/25879.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux klibc 字符串比较函数是实现</title><link>http://www.cnitblog.com/schkui/archive/2006/06/02/11467.html</link><dc:creator>易道</dc:creator><author>易道</author><pubDate>Fri, 02 Jun 2006 07:07:00 GMT</pubDate><guid>http://www.cnitblog.com/schkui/archive/2006/06/02/11467.html</guid><wfw:comment>http://www.cnitblog.com/schkui/comments/11467.html</wfw:comment><comments>http://www.cnitblog.com/schkui/archive/2006/06/02/11467.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/schkui/comments/commentRss/11467.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/schkui/services/trackbacks/11467.html</trackback:ping><description><![CDATA[int strncasecmp(const char *s1, const char *s2, size_t n)<br />{<br />  const unsigned char *c1 = s1, *c2 = s2;<br />  unsigned char ch;<br />  int d = 0;<br /><br />  while ( n-- ) {<br />    /* toupper() expects an unsigned char (implicitly cast to int)<br />       as input, and returns an int, which is exactly what we want. */<br />    d = toupper(ch = *c1++) - toupper(*c2++);<br />    if ( d || !ch )<br />      break;<br />  }<br /><br />  return d;<br />}<br /><br /><br />int strcasecmp(const char *s1, const char *s2)<br />{<br />  const unsigned char *c1 = s1, *c2 = s2;<br />  unsigned char ch;<br />  int d = 0;<br /><br />  while ( 1 ) {<br />    /* toupper() expects an unsigned char (implicitly cast to int)<br />       as input, and returns an int, which is exactly what we want. */<br />    d = toupper(ch = *c1++) - toupper(*c2++);<br />    if ( d || !ch )<br />      break;<br />  }<br /><br />  return d;<br />}<br /><br /><br />int strcmp(const char *s1, const char *s2)<br />{<br />  const unsigned char *c1 = s1, *c2 = s2;<br />  unsigned char ch;<br />  int d = 0;<br /><br />  while ( 1 ) {<br />    d = (int)(ch = *c1++) - (int)*c2++;<br />    if ( d || !ch )<br />      break;<br />  }<br /><br />  return d;<br />}<br /><br /><br /><br />int strncmp(const char *s1, const char *s2, size_t n)<br />{<br />  const unsigned char *c1 = s1, *c2 = s2;<br />  unsigned char ch;<br />  int d = 0;<br /><br />  while ( n-- ) {<br />    d = (int)(ch = *c1++) - (int)*c2++;<br />    if ( d || !ch )<br />      break;<br />  }<br /><br />  return d;<br />}<br /><br /><img src ="http://www.cnitblog.com/schkui/aggbug/11467.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/schkui/" target="_blank">易道</a> 2006-06-02 15:07 <a href="http://www.cnitblog.com/schkui/archive/2006/06/02/11467.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>简单的智能指针-- 防止内存泄露..</title><link>http://www.cnitblog.com/schkui/archive/2006/05/31/11341.html</link><dc:creator>易道</dc:creator><author>易道</author><pubDate>Wed, 31 May 2006 09:57:00 GMT</pubDate><guid>http://www.cnitblog.com/schkui/archive/2006/05/31/11341.html</guid><wfw:comment>http://www.cnitblog.com/schkui/comments/11341.html</wfw:comment><comments>http://www.cnitblog.com/schkui/archive/2006/05/31/11341.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/schkui/comments/commentRss/11341.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/schkui/services/trackbacks/11341.html</trackback:ping><description><![CDATA[
		<br />// 一般用途<br />template&lt;class T&gt;struct SP_traits {<br />    static void Release(T* ptr)     {<br />        delete ptr;<br />    }<br />};<br /><br />// 特殊用途<br />template&lt;&gt; struct SP_traits&lt;somlist&gt;{<br />    static void Release(T* ptr)<br />    {<br />        somlist::iterator iter;<br />        for(iter= ptr-&gt;begin() ;iter!=ptr-&gt;end();iter++) <br />            delete (*iter) ;<br />        <br />        delete ptr;<br />    }    <br />}<br /><br /><br />template&lt;class T&gt;<br />class SP//simple smart pointer<br />{<br />public:<br />    SP():ptr(NULL)    {<br />    }<br />    SP(T*p):ptr(p)    {<br />    }<br /><br />    void Release()<br />    {<br />        if( ptr != NULL )<br />        {<br />            SP_traits&lt;T&gt;::Release(ptr);<br />        }<br />        ptr = NULL;<br />    }<br />    T* operator=(T*p){<br />        Release();<br />        ptr = p;<br />        return ptr;<br />    }<br />    T** operator &amp;() const    {<br />        return &amp;ptr;<br />    }<br />    T** operator &amp;()    {<br />        return &amp;ptr;<br />    }<br />    T&amp; operator *()    {<br />        return *ptr;<br />    }<br />    T&amp; operator *()    const {<br />        return *ptr;<br />    }<br />    T* operator-&gt;()    {<br />        return ptr;<br />    }<br />    T* operator-&gt;()    const {<br />        return ptr;<br />    }<br />    operator T*()    {<br />        return ptr;<br />    }<br />    operator T*() const    {<br />        return ptr;<br />    }<br />    T&amp; operator []( int i )    {<br />        return ptr[ i ];<br />    }<br />    T&amp; operator []( int i )    const {<br />        return ptr[ i ];<br />    }<br />    bool operator == ( const T* p ){<br />        return ptr == p;<br />    }<br />    bool operator != ( const T* p ){<br />        return ptr != p;<br />    }<br />    bool operator == ( const T* p ) const {<br />        return ptr == p;<br />    }<br />    bool operator != ( const T* p ) const {<br />        return ptr != p;<br />    }<br /><br />    ~SP()<br />    {<br />        Release();<br />    }<br />    PM_BOOL IsValid()    {<br />        return ptr != NULL;<br />    }<br />    void Attach( T* ptr_new )<br />    {<br />        Release();<br />        ptr = ptr_new;<br />    }<br />    void Detach( T* ptr_new )<br />    {<br />        ptr = NULL;<br />    }<br />    T* ptr;<br />};<br /><br /><br /><img src ="http://www.cnitblog.com/schkui/aggbug/11341.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/schkui/" target="_blank">易道</a> 2006-05-31 17:57 <a href="http://www.cnitblog.com/schkui/archive/2006/05/31/11341.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CPPunit 的简单的应用</title><link>http://www.cnitblog.com/schkui/archive/2006/05/31/11331.html</link><dc:creator>易道</dc:creator><author>易道</author><pubDate>Wed, 31 May 2006 08:42:00 GMT</pubDate><guid>http://www.cnitblog.com/schkui/archive/2006/05/31/11331.html</guid><wfw:comment>http://www.cnitblog.com/schkui/comments/11331.html</wfw:comment><comments>http://www.cnitblog.com/schkui/archive/2006/05/31/11331.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/schkui/comments/commentRss/11331.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/schkui/services/trackbacks/11331.html</trackback:ping><description><![CDATA[
		<br />/**********************************************************<br />*<br />*  测试的主函数<br />*<br />***********************************************************/<br /><br />#include &lt;cppunit/CompilerOutputter.h&gt;<br />#include &lt;cppunit/extensions/TestFactoryRegistry.h&gt;<br />#include &lt;cppunit/ui/text/TestRunner.h&gt;<br /><br /><br /><br />int main(int argc, char* argv[])<br />{<br />  // Get the top level suite from the registry<br />  CPPUNIT_NS::Test *suite = CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest();<br /><br />  // Adds the test to the list of test to run<br />  CPPUNIT_NS::TextUi::TestRunner runner;<br />  runner.addTest( suite );<br /><br />  // Change the default outputter to a compiler error format outputter<br />  runner.setOutputter( new CPPUNIT_NS::CompilerOutputter( &amp;runner.result(),<br />                                                       std::cerr ) );<br />  // Run the test.<br />  bool wasSucessful = runner.run(); <br /><br />  // Return error code 1 if the one of test failed.<br />  return wasSucessful ? 0 : 1;<br />}<br /><br /><br /><br />/**********************************************************<br />*<br />*  测试的类的头文件<br />*  testex.h<br />***********************************************************/<br />#include &lt;cppunit/extensions/HelperMacros.h&gt;<br /><br /><br />class CTestEx : public CPPUNIT_NS::TestFixture <br />{<br />    // 开始<br />    CPPUNIT_TEST_SUITE( CTestEx );<br />    // 申明自动测试的函数<br />    CPPUNIT_TEST( test_f ); <br />    // 结束<br />    CPPUNIT_TEST_SUITE_END();<br />public:<br />    CTestEx ();<br />    virtual ~CTestEx ();<br />    void test_f() ;<br />}<br /><br />/**********************************************************<br />*<br />*  测试的类的实现<br />*  testex.cpp<br />***********************************************************/<br /><br /><br />#include "testex.h"<br /><br /><br />CPPUNIT_TEST_SUITE_REGISTRATION( CTestEx );<br /><br />void CTestEx::test_f()<br />{<br />    ....;<br />}<br /><br /><img src ="http://www.cnitblog.com/schkui/aggbug/11331.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/schkui/" target="_blank">易道</a> 2006-05-31 16:42 <a href="http://www.cnitblog.com/schkui/archive/2006/05/31/11331.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>