Skip to content

{ Monthly Archives } 六月 2008

C indent

在unix痛恨者手册中, indent 被当作一个臭名昭著的反面例子给出.不过,从客观角度讲,目前的indent,还是挺讨人喜欢的. 对于indent的参数,建议使用: -bad -bap -bbb -bbo -nbc -bl -bli0 -bls -c33 -cd33 -ncdb -ncdw -nce -cli0 -cp33 -cs -d0 -nbfda -di2 -nfc1 -nfca -hnl -ip5 -l75 -lp -pcs -nprs -psl -saf -sai -saw -nsc -nsob -nss -i4 -ts4 -ut 这些参数可写入用户目录下的文件,作为运行indent的缺省参数: echo “-bad -bap -bbb -bbo -nbc -bl -bli0 -bls -c33 -cd33 -ncdb -ncdw [...]

使用gprof分析程序

gprof介绍 gprof是一个GNU profiler工具。可以显示程序运行的“flat profile”,包括每个函数的调用次数,每个函数消耗的处理器时间,也可以显示“调用图”,包括函数的调用关系,每个函数调用花费了多少时间。还可以 显示“注释的源代码”--是程序源代码的一个复本,标记有程序中每行代码的执行次数。 基本用法: 1. 使用-pg选项编译和链接你的应用程序。 2. 执行你的应用程序,使之运行完成后生成供gprof分析的数据文件(默认是gmon.out)。 3. 使用gprof程序分析你的应用程序生成的数据,例如:gporf a.out gmon.out。 gprof 实现原理: gprof并不神奇,在编译和链接程序的时 候(使用 -pg 编译和链接选项),gcc 在你应用程序的每个函数中都加入了一个名为mcount(or“_mcount”, or“__mcount”)的函数,也就是说-pg编译的应用程序里的每一个函数都会调用mcount, 而mcount会在内存中保存一张函数调用图,并通过函数调用堆栈的形式查找子函数和父函数的地址。这张调用图也保存了所有与函数相关的调用时间,调用次 数等等的所有信息。 1. 在内存中分配一些内存,存储程序执行期间的统计数据 2. 在GCC使用-pg选项编译后,gcc会在程序的入口处(main 函数之前)调用 void monstartup(lowpc, highpc) 在每个函数的入口处调用 void _mcount() 在程序退出时(在 atexit () 里)调用 void _mcleanup() monstartup:负责初始化profile环境,分配内存空间 _mcount:       记录每个函数代码的caller和callee的位置 _mcleanup:清除profile环境,保存结果数据为gmon.out,供gprof分析结果 3.在_mcount函数中跟踪程序的执行状况,记录程序代码的执行次数,时间等数据。 常用的gprof命令选项: -b                 不再输出统计图表中每个字段的详细描述。 -p                 只输出函数的调用图(Call graph的那部分信息)。 [...]

转:内存泄漏的检测

一.内存泄漏的介绍: 内存泄漏以发生的方式来分类,内存泄漏可以分为4类: 1.常发性内存泄漏。发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏。 2.偶发性内存泄漏。发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生。常发性和偶发性是相对的。对于特定的环境,偶发性的也许就变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关重要。 3.一次性内存泄漏。发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块仅且一块内存发生泄漏。 二.C程序内存泄漏和其它内存常见错误及例子 1.malloc之后没有free引起的内存泄漏 2.指针访问越界 ##############Explame1########################### p = (char *)malloc(10); p[24] = ’0′; free(p); ################################################# 3.两次对同一个地址使用free() ##############Explame2########################### char *p = NULL; char *q = NULL; p = (char *)malloc( 2 ); free(p); free(p); 可以检测出这一行 free(p+2)这样写也可以检测出 free(q); 不能检测出 ################################################# 4.让未初始化数据作为赋值量 ##############Explame1########################### int n,m; m = n; ################################################# 5.将未初始化值作为判断条件 ##############Explame1########################### int n; if(n){ n++; [...]

转:MySQL参数说明

1. back_log 指定MySQL可能的连接数量。当MySQL主线程在很短的时间内得到非常多的连接请求,该参数就起作用,之后主线程花些时间(尽管很短)检查连接并且启动一个新线程。 back_log参数的值指出在MySQL暂时停止响应新请求之前的短时间内多少个请求可以被存在堆栈中。如果系统在一个短时间内有很多连接,则需要增大 该参数的值,该参数值指定到来的TCP/IP连接的侦听队列的大小。不同的操作系统在这个队列大小上有它自己的限制。试图设定back_log高于你的操 作系统的限制将是无效的。 当观察MySQL进程列表,发现大量 264084 | unauthenticated user | xxx.xxx.xxx.xxx | NULL | Connect | NULL | login | NULL 的待连接进程时,就要加大 back_log 的值。back_log默认值为50。 2. basedir MySQL主程序所在路径,即:–basedir参数的值。 3. bdb_cache_size 分配给BDB类型数据表的缓存索引和行排列的缓冲区大小,如果不使用DBD类型数据表,则应该在启动MySQL时加载 –skip-bdb 参数以避免内存浪费。 4.bdb_log_buffer_size 分配给BDB类型数据表的缓存索引和行排列的缓冲区大小,如果不使用DBD类型数据表,则应该将该参数值设置为0,或者在启动MySQL时加载 –skip-bdb 参数以避免内存浪费。 5.bdb_home 参见 –bdb-home 选项。 6. bdb_max_lock 指定最大的锁表进程数量(默认为10000),如果使用BDB类型数据表,则可以使用该参数。如果在执行大型事物处理或者查询时发现 bdb: Lock table is out of available locks or Got [...]

BDB Replication 三

Network partitions bdb replication 的实现可能被网络隔离的问题影响。 例如,考虑replication组有n个成员。网络隔离让master在一边,多于一半(n/2)的站点在另外一边。和master在一边的站点将继续 前进,master继续接受数据库的写请求。不幸的是,隔离在另一边的站点,意思到他们的master不在了,将举行一个选举。这个选举将取得成功,因为 这儿有总数n/2以上的站点在这边,然后这个组内将会有两个master。既然两个master都可能潜在地接受写请求,那么数据库将可能产生分歧,使得 数据不一致。 如果曾经在一个组内发现了多个master,一个master检测到这个问题的时候将会返回DB_REP_DUPMASTER。如果一个应用程序看到这个 返回,它应该重新配置自己作为一个client(通过调用ENV->rep_start),然后发起一场选举(通过调用 DB_ENV->rep_elect)。赢得这次选举的可能是先前的两个master之一,也可能完全就是另外的站点。无论如何,这个胜出的系统将 引导其它系统达到一致。 作为另外一个例子,考虑一个replication组有一个master环境和两个client,A和B,在那A可能会升级为master地位而B不可能。然后,假设client A从其他的两个数据库环境中被隔离出来了,它的数据变的过期。然后假设这个master倒掉了,而且不再上线。随后,网络隔离被修复了,client A和B进行了一次选举。因为client B不能赢得选举,client A将会默认地赢得这次选举,为了重新和B同步,可能在B上提交的事务将不能回滚直到这两个站点能再次地一起前进。 在这两个例子中,都有一步就是新选举出的master引导组内的成员和它自己一致,以便它可以开始发送新信息给它们。这可能会丢失信息,因为以前提交的事务没有回滚。 在体系结构上网络隔离是个问题,应用程序可能想实现一个心跳协议以最小化一个糟糕的网络隔离的影响。只要一个master至少可以和组内一半的站点通信的 时候,就不可能出现两个master。如果一个master不再能和足够的站点取得联系的时候,它应该重新配置自己作为一个client,和举行一次选 举。 这儿有另外一个工具应用程序可以用来最小化网络隔离情况下的损失。通过指定一个 nsites 参数给DB_ENV->rep_elect ,也就是说,比组内的实际成员的数目大,应用程序可以阻止系统宣布他们自己成为master,除非它们可以和组内绝大部分站点通话。例如,如果组内有20 个数据库环境,把参数30指定给DB_ENV->rep_elect方法,那么这个系统至少要和16个站点通话才可以宣布自己为master。 指定一个小于组内世界成员数目的nsites参数给DB_ENV->rep_elect,也有它的用处。例如,考虑一个组有只有两个数据库环境。如果他们被隔离了,其中任何一个都不能取得足够的选票数成为master。一个合理的选择是,指定一个系统的nsites 参数为2,另一个为1。那样,当被隔离的时候,其中一个系统可以赢得选举权,而另一个不能。这能允许当网络被隔离的时候其中一个系统能继续接受写请求。 这些关卡强调了bdb replicated环境中好的网络底层构造的重要性。当replicating数据库环境在严重丢包的网络环境中,最好的解决可能是拣选一个单一的master,只有当人工干涉决定这个被选择的master不能再恢复上线时,才举行选举。 Replication FAQ Does Berkeley DB provide support for forwarding write queries from clients to masters? No, it does not. The Berkeley DB RPC server [...]

BDB Replication 二

Synchronizing with a master 当一个client探测到replication组内一个新的master后,在它能去处理新的数据库变化之前,这个client必须去同步这个新的master。同步是一个重量级操作,它能同时给这个client和master增加负担。这儿有一些措施,一个应用程序可以用来减轻同步的负担: 延迟client同步: 当组内有了一个新的master,不论是被应用程序指定的还是因为选举的结果,所有的clients必须去同步这个新的master。这会使新的 master的资源过度损耗,因为很多clients可能都试图去和它通信和从它那儿取得记录。clients应用程序如果想延迟client的同步,应 该用DB_REP_CONF_DELAYCLIENT标志去调用DB_ENV->rep_set_config 方法。这个配置使得client总从DB_ENV->rep_process_message方法返回DB_REP_NEWMASTER,但是这个 client将不会继续去同步这个新的master。Client端应用程序选择延迟同步,用这种方法,那么将来再用 DB_ENV->rep_sync方法去同步将是可靠的。 client-to-client的同步: Clients可以接受和服务其他clients的请求。Clients请求记录调用这个Client应用程序的传输回调函数。可以由其他Clients 满足的请求,传输函数的标志被设置成DB_REP_ANYWHERE。应用程序可以选择发送这些请求到任意client,或者忽略这个标志,而把请求发送 到这个消息的环境id所指定的站点。 Client应用程序可以用不管什么算法,它们选择来负载均衡到其它clients的请求。任何client接受到一个它不能满足的请求,都将回复给请求的client,告诉它,自己不能够提供请求的信息,而那个最初的请求者,将重新请求这个信 息。另外,如果这个最初的请求没有到达发要发送给的那个目标client端,这个最初的发送请求的client也将重新请求这个信息。这这些任意一种情况 下,这个重新的请求将把传输函数的标志设置成DB_REP_REREQUEST 。应用程序可能通过把这个请求进一步传递给naster来响应这个DB_REP_REREQUEST 标志(因为是被这个消息的环境id指定的),或继续把这个请求传送给另一个client。 这延迟的同步和client-to-client的同步特性允许应用程序在replication组内做负载均衡。例如,考虑到一个组内有5个站点, A, B, C, D 和 E,站点E刚刚倒掉了,站点A被选举为master。站点C 和 D 被配置成延迟同步的,当B注意到站点A是一个新master,它立即进行同步。当B完成和master的同步的时候,站点C 和 D 上的应用程序调用 DB_ENV->rep_sync 方法,使它们也进行同步。站点C 和 D (和 E, 当它完成了重新引导) 可以发送他们的请求到站点 B, 而B可以负担因为同步而产生的工作和网络流量的冲击, 使的master,站点A,有空去处理正常的应用程序工作量和由于选举而暂停的写请求。 阻塞client的操作: Clients在处理和master的同步的时候将阻塞bdb其它的操作。默认的,许多bdb方法将阻塞,直到client同步完成,然后,这些被阻塞的方法才继续调用。 那些不能等待的Client应用程序,将更愿意立即得到一个错误返回而不是阻塞,那么就应该用DB_REP_CONF_NOWAIT 标志调用DB_ENV->rep_set_config方法。如果这个clinet现在正在同步一个master,这个配置使得bdb方法调用立即返回一个DB_REP_LOCKOUT 错误,而不是阻塞。 Clients太落伍以至于不能同步: Clients试图去和master同步的时候可能会发现,同步是不可能的了,因为client和master 已经失去联系很久了。默认地,client和master自动的检测这个状态和执行clinet内部初始化。因为内部初始化需要传输整个数据库到clinet,这可能会发费一个相对较长的时间,可能需要clinet应用程序的数据库句柄重新被打开。 那些不能等待的应用程序,更愿意推后内部初始化直到一个更加便利的时间,或者更希望做一个热备份而不是执行内部初始化,应该用REP_CONF_NOAUTOINIT 标志来调用DB_ENV->rep_set_config方法。这个配置使得bdb返回DB_REP_JOIN_FAILURE到应用程序而不是执行内部初始化。 [...]

BDB Replication 一

Introduction bdb包括对构建基于复制(replication)的高可用性应用程序的支持。bdb replication组由一些独立配置的数据库环境组成。组里只有一个master数据库环境和一个或多个client环境。Master环境支持读和写,client环境支持只读。如果master环境倒掉 了,应用程序将可能提升一个client为新的master。数据库环境可能在单独的计算机上,在单独的硬件分区上(partitions)一个不统一的 内存访问系统上,或在一个单独的server的一个磁盘上。唯一的约束就是,replication组的所有的参与者必须在一个字节序 (endianness)相同的机器上(都是大数再前或都是小数在前的操作系统)。我们期望这个约束在以后的版本中会去掉。因为总是用bdb环境,任何数 量的并发进程或线程可能访问一个数据库环境。在master环境中,多个线程可能读写这个环境。在client环境中,多个线程可能要读这个环境。 应用程序可能被编写成在master和clients间提供不同程度的稳固性。系统能同步的运行以便复制品(replicas)能保证是最新的,对应于所 有已提交的事务。但是这样做可能回招致性能上的很大的下降。高性能解决方案有考虑全局的稳固性,允许clients的数据过时一个应用程序可控制的一段时 间。尽管bdb包括必要的构建高可用性数据库环境的底层基础,应用程序仍然必须提供一些鉴定的(critical)组成部分: 应用程序有责任提供通信下部构造。应用程序可能用任何适当的通信协议。例如RPC, TCP/IP, UDP, VI或底板(backplane)消息传递。 应用程序有责任命名。bdb涉及到一个replication组成员的时候是靠一个应用程序提供的id,应用程序必须映射那个id到一个特殊的数据库环境中或通信通道中。 应用程序有责任监视master和clients的状态,和识别任何不可用的(unavailable)数据库环境。应用程序必须提供所有的需要的安全策略。例如,应用程序可能选择去加密数据,用一个安全的套接层,或什么也不做。 最后,bdb replication实现还有一个附加的特性去增强可靠性。bdb中的replication实现成执行数据库更新用一个不同的编码路径而不是用标准的。这意味着,有bug的软件的操作可能会毁坏replication master,但不会把clients也毁坏。 Replication和相近的方法的描述: DB_ENV->rep_elect         举行一个replication竞选 DB_ENV->rep_process_message   处理一个replication消息 DB_ENV->rep_stat           Replication统计 DB_ENV->rep_sync           Replication同步 Replication 配置: DB_ENV->rep_set_config     配置replication系统 DB_ENV->rep_start         为replication配置一个环境 [...]

嵌入式数据库系统Berkeley DB

    施聪 高级程序员、网络设计师 2005 年 4 月    BerkeleyDB是历史悠久的嵌入式数据库系统,主要应用在UNIX/LINUX操作系统上,其设计思想是简单、小巧、可靠、高性能。本文是对DB开 发的一个入门级指南,重点讨论了DB的核心数据结构和数据访问算法,并通过实际的代码演示如何使用DB。最后有一个对DB的简单总结,并提出作者对工具选 择的一些感想。 前言 UNIX/LINUX平台下的数据库种类非常多,参考资料1中 列举了其中的大部分。通常,我们在设计UNIX/LINUX平台下的应用软件时,如果数据种类繁多,数据与数据之间关系比较复杂,就会选用一些大型的企业 级数据库系统,如DB2,ORACLE、SYBASE等,如果软件规模不大,就倾向选用如MYSQL、POSTGRESQL等中小型数据库。例如使用 PHP/PERL +MYSQL/POSTGRESQL设计网站基本上是一个很常规的做法。但是,当应用软件管理的数据类型较少(特别注意:这并不是说需要管理的数据量 小),数据管理本身不复杂,且对数据操作要求高效率,则由大名鼎鼎的Berkeley(美国加州大学伯克利分校)开发的 BerkeleyDB可能是一个很明智的选择。 DB综述 DB最初开发的目的是以新的HASH访问算法来代替旧的hsearch函数和大量的dbm实现(如AT&T的dbm,Berkeley的 ndbm,GNU项目的gdbm),DB的第一个发行版在1991年出现,当时还包含了B+树数据访问算法。在1992年,BSDUNIX第4.4发行版 中包含了DB1.85版。基本上认为这是DB的第一个正式版。在1996年中期,Sleepycat软件公司成立,提供对DB的商业支持。在这以后,DB得到了广泛的应用,当前最新版本是4.3.27。 DB支持几乎所有的现代操作系统,如LINUX、UNIX、WINDOWS等,也提供了丰富的应用程序接口,支持C、C++、JAVA、PERL、TCL、PYTHON、PHP等。DB的应用十分广泛,在很多知名的软件中都能看到其身影。例如参考资料2中作者谈到利用DB在LINUX下实现内核级文件系统;参考资料3中通过实际测试数据说明DB提高了OPENLDAP的效率。LINUX下的软件包管理器RPM也使用DB管理软件包相关数据,可以使用命令file查看RPM数据目录/var/lib/rpm下的文件,则有形式如下的输出: Dirnames: Berkeley DB (Btree, version 9, native byte-order) Filemd5s: Berkeley DB (Hash, version 8, native byte-order) 值得注意的是DB是嵌入式数据库系统,而不是常见的关系/对象型数据库,对SQL语言不支持,也不提供数据库常见的高级功能,如存储过程,触发器等。 DB的设计思想 DB 的设计思想是简单、小巧、可靠、高性能。如果说一些主流数据库系统是大而全的话,那么DB就可称为小而精。DB提供了一系列应用程序接口(API),调用 本身很简单,应用程序和DB所提供的库在一起编译成为可执行程序。这种方式从两方面极大提高了DB的效率。第一:DB库和应用程序运行在同一个地址空间, 没有客户端程序和数据库服务器之间昂贵的网络通讯开销,也没有本地主机进程之间的通讯;第二:不需要对SQL代码解码,对数据的访问直截了当。 DB对需要管理的数据看法很简单,DB数据库包含若干条记录,每一个记录由关键字和数据(KEY/VALUE)构成。数据可以是简单的数据类型,也可以是 复杂的数据类型,例如C语言中结构。DB对数据类型不做任何解释,完全由程序员自行处理,典型的C语言指针的”自由”风格。如果把记录看成一个有n个字段 的表,那么第1个字段为表的主键,第2–n个字段对应了其它数据。DB应用程序通常使用多个DB数据库,从某种意义上看,也就是关系数据库中的多个表。 DB库非常紧凑,不超过500K,但可以管理大至256T的数据量。 DB的设计充分体现了UNIX的基于工具的哲学,即若干简单工具的组合可以实现强大的功能。DB的每一个基础功能模块都被设计为独立的,也即意味着其使用 领域并不局限于DB本身。例如加锁子系统可以用于非DB应用程序的通用操作,内存共享缓冲池子系统可以用于在内存中基于页面的文件缓冲。 DB核心数据结构 数据库句柄结构DB:包含了若干描述数据库属性的参数,如数据库访问方法类型、逻辑页面大小、数据库名称等;同时,DB结构中包含了大量的数据库处理函数指针,大多数形式为 (*dosomething)(DB [...]

sqlite 入门初步

译者: zhuyubing@gmail.com 这里告诉你怎么开始实验 SQLite ,这里没有长长的说明和配置。 下载代码 http://www.sqlite.org/download.html 目前的最新版本: http://www.sqlite.org/sqlite-3.4.0.tar.gz 取得一份二进制拷贝, 或者是源代码并自己编译它. 关于下载页(download) 的更多信息.     ./configure      ;#  Run the configure script make                     ;#  Run the makefile. make install 创建一个新数据库 在命令行下, 输入: “sqlite3 test.db”. 将创建一个新的数据库文件名叫”test.db”. (你可以使用不同的名字) 输入 SQL 命令在提示符下创建和写入新的数据. $ sqlite3 ex1 SQLite version 3.3.10 Enter “.help” for instructions sqlite> create table tbl1(one varchar(10), two smallint); sqlite> [...]

The MySQL C API

简介 C APIs包含在mysqlclient库文件当中与MySQL的源代码一块发行,用于连接到数据库和执行数据库查询。有一些例子在MySQL原代码的clients目录里。 MySQL C 变量类型 以下变量类型在MySQL的库当中定义。我们需要这些变量是为了使用MySQL的函数。这些变量有详细的解释,但是这些解释对于写代码来说并不重要。 MYSQL 要连接MYSQL,必须建立MYSQL实例,通过mysql_init初始化方能开始进行连接。 [code=c]typedef struct st_mysql { NET           net;            /* Communication parameters */ gptr          connector_fd;   /* ConnectorFd for SSL */ char          *host,*user,*passwd,*unix_socket, *server_version,*host_info,*info,*db; unsigned int  port,client_flag,server_capabilities; unsigned int  protocol_version; unsigned int  field_count; unsigned int  server_status; unsigned long thread_id;      /* Id for connection in server */ my_ulonglong affected_rows; my_ulonglong insert_id;       [...]