一种对共享资源和独享资源的检查方法

一种对共享资源和独享资源的检查方法

1. 背景

当程序的子模块数量和规模扩大之后,在开发阶段,系统长时间允许后经常会碰到下面一些bug:

  • 内存泄漏。随着时间允许,系统可用的内存越来越少,最后kernel 出现oom 错误;
  • 文件句柄耗尽。程序可以打开的文件、套接字、管道越来越少,最后出错在用完了最后一个可用句柄的代码附近;
  • 死锁。线程拥有一把锁A,正在申请锁B;但在此时锁B被另外一个线程拥有,且那个线程又在申请锁A。形成一个循环等待、占用且不可释放的状态。

调试这些问题,当然可以从代码流程和逻辑出发,结合ps/gdb/proc/core等命令和信息,一步步挖出root cause。但一般要求对代码、线程关系和相关命令比较熟悉,一般耗时较长。所以,一般大型公司都封装了标准的glibc,做了一个wraaper,然后再wrapper里面加入了对上面调试的支持。还有的可采用专业内存泄漏等检查工具,去做代码检测。那么,对于咱工程师而言,能否能自己设计并实现一个资源检查工具呢?

2. 原理

针对上面的三个例子使用中的资源,我们可以归纳成两类:数量有限的共享资源,比如上面空间有限的内存和数量有限的文件句柄;需要独占的互斥资源,比如上面例子中提到的锁。 下面就分别针对这两种情况,分别展开分析。

2.1 对共享资管的检查

共享资源的特点是:总量有限,通过申请接口获得,使用完了之后通过释放接口归还。为了保证不浪费资源,这就要求程序在使用完了申请得到的资源之后,必须及时释放。而共享资源出现问题的情况,大部分是由于程序员遗忘没有释放造成的。因此,需要一种内部机制能够记录哪些资源使用了还没有释放,可以通过下面的步骤实现:

  • 预备一张表,初始化为空;
  • 分配的时候,把刚分配的资源的地址等信息记录到表中去;
  • 释放的时候,把将释放的资源的地址对应的信息从表中移除;
  • 检查的时候:表为空就表明申请的资源都已释放,否则还有资源没被释放;

2.2 对独享资管的检查

独享资源的特点是:互斥使用,基本上是先到先得,通过标志设置是否以备占有。为了保证不死锁,这就要求:程序在申请某个互斥资源的时候,需要检查它已经拥有的资源,是否被它正在申请的互斥资源的拥有者申请。
如果是,会死锁;否则,不会死锁。同样也可以通过下面的步骤实现:

  • 预备一张映射表,初始化为空:它描述一个用户拥有哪些互斥资源,同时根据互斥资源能够索引到它的拥有者;
  • 分配检查的时候:检查当前用户已经拥有的资源,是否被它正在申请的互斥资源的拥有者申请。同时让这个互斥资源能够索引到当前正在申请它的用户;
  • 执行分配的时候:把刚分配的互斥资源的地址添加到当前用户拥有的互斥资源的列表中去,同时让这个互斥资源能够索引到当前拥有它的用户。
  • 释放的时候,把将释放的资源的地址从互斥资源列表移除,断开这个互斥资源和当前用户的索引关系。
  • 多个用户死锁时的分析:

3. 实现

根据上面原理的分析,我们不难结合之前讲过的xlink、程序堆栈等技巧,选用合适的数据结构来实现。

3.1 共享资源检查的实现

根据2.1中的分析,需要先构造一张表来记录这些资源的地址,这张表要求插入方便,删去也迅速。为此,我们可以用基于平衡二叉树、优先级队列或者hash的方法去实现这个表。对这个表的操作包括PQInsert()/PQRemove()/PQEmpty()等。 此后,就可以开始参考下面列出的针对共享资源泄漏检查的步骤去实现了。

3.1.1 声明支持资源泄漏检查的wrapper函数

可以基于标准的open/close/malloc/free等直接申请、是否公共资源的函数,去实现wrapper。
下面以open()、close()为例,伪码示例如下:
int wrapper_open(char * dev);
int wrapper_free(int fd);

3.1.2 实现支持资源泄漏检查的wrapper函数

还是下面以open()、close()为例:

#define FILE (‘f‘<<24|‘i<<16|‘l‘<<8|‘e‘)

int wrapper_open(char * dev)
{
    int fd = real_open(dev);
    PQInsert(FILE, fd);
    return fd;
}

int wrapper_close(int fd)
{
    int ret = 0;
    PQRemove(FILE, fd);
    ret = real_close(fd);
    return ret;
}

3.1.3 调用支持资源泄漏检查的wrapper函数

有两种方式可以使用支持资源泄漏检查的wrapper函数,一种是代码中之间调用open/close等函数对应的wrapper函数,另外一种是借助gcc Xlink 的支持让标准的open/close函数“重定向”到wrapper_open/wrapper_close函数。显然,后面一种方法工作量最小、最优雅。具体的实现,可以参考前面关于Xlink的博文,下面列出了主要的几个步骤:

  • gcc编译的flag中加入Xlinker改动

     Xlinker --wrap=open -Xlinker --undefined=wrapper_open Xlinker --wrap=close -Xlinker --undefined=wrapper_close
  • 新的头文件中加入声明
    typeof(open)         wrapper_open;
    typeof(close)        wrapper_close;
    typeof(open)         real_open;
    typeof(close)        real_close;

3.1.4 检查资源是否泄漏的函数

通常,在程序快要结束退出的时候,会释放资源,末了可以通过共享资源泄漏检查函数去检查是否正的有资源泄漏。这个函数的主要实现的示例如下:

int FileRes_check(void)
{
    if PQEmpty(FILE) {
        return PASS;
    } esle {
        PQDump(FILE);
        return FAIL;
    }
}

3.1.5 记录可能申请了被泄漏的资源代码的位置

根据上一篇博文中,关于如何得到程序堆栈中介绍的方法,我们可以在申请共享资源的时候,具体来说就是调用PQInsert(FILE, fd)时,取得当前程序的stack, 把堆栈信息和fd一起作为一项纪录插入到基于优先级队列、散列或者平衡二叉树实现的表中去。 同样,PQDump()除了打印没有关闭的文件句柄之外,还输出这个句柄对应打开时候的程序堆栈,根据这个堆栈信息,程序员能够定位到打开了这个没被关闭的句柄的代码的位置。而通常,这个句柄的关闭应该在它之后附近。

3.2 独享资源检查的实现

对独享资源死锁的检查的具体实现依赖的技术同上,差别就在死锁检查的逻辑和流程。读者可以自行尝试,等有时间了我也可以再来完善。

4. 总结

通过上面的这么多介绍可以看到,基于对共享资源和互斥资源使用特点的分析,我们能够提出一种针对共享资源泄漏和独享资源死锁检查的通用原理。借助于合适的数据结构(二叉树、优先级队列或散列),基于 Xlinker方法、堆栈获取的API,我们能够实现一种轻巧的、几乎不用改动已有代码的对开发者非常友好的资源检查功能。

原文地址:http://blog.51cto.com/xiamachao/2065841

时间: 2024-10-15 01:39:17

一种对共享资源和独享资源的检查方法的相关文章

CPU100%不限性能和100%独享资源的区别

CPU100%不限性能和100%独享资源的区别是什么,最近这类问题突然激增,这里为大家科普一下 1,什么是独享100%独享资源通常看到独享100%资源的云服务器是S1.S2名称,像阿里云双十一和阿里云双十二的都有这样服务器的区别,通常也被称之为"计算网络增强型sn1ne实例". 2,什么是100%CPU性能这类一般我们看到的是共享基本型xn4和共享计算型n4实例,例如阿里云双十一和双十二活动里看到的.从价格上看,一般是独享100%资源的价格比较高的,这个就相当于一个CPU个人用,而10

租用服务器选独享带宽好还是共享带宽好?

在租用服务器时,除了关注服务器硬件配置外,还要关注带宽问题.大部分服务商会提供独享带宽和共享带宽两种带宽,根据带宽的选择价格也相差甚远,那什么是共享带宽,什么是独享带宽呢?我们如何选择呢?想了解这两种带宽的含义,我们先要知道什么是带宽,带宽是如何工作的.什么是带宽?带宽是有线或无线网络通信链路在给定时间内通过计算机网络或互联网连接将最大数据量从一个点传输到另一个点的容量,通常为一秒.带宽是如何工作的?服务商会给每个区域设置一个机架,并给每个机架配备一定的带宽资源,然后再将这些资源分配到这个区域内

Java 中15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁,乐观锁,分段锁,自旋锁等等(转)

Java 中15种锁的介绍 在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类.介绍的内容如下: 公平锁 / 非公平锁 可重入锁 / 不可重入锁 独享锁 / 共享锁 互斥锁 / 读写锁 乐观锁 / 悲观锁 分段锁 偏向锁 / 轻量级锁 / 重量级锁 自旋锁 上面是很多锁的名词,这些分类并不是全是指锁的状态,有的指锁的特性,有的指锁的设计,下面总结的内容是对每个锁的名词进行一定的解释. 公平锁 / 非公平锁 公平锁 公平锁是指多个线程按照申请锁的顺序来获取锁. 非公

什么是带宽?宽带独享?共享?

所谓带宽(bandwidth)可以通俗理解为单位时间内访问网络的的最大数据流量.如果使用100M网络交换机,局域网带宽可以达到100M:如使用10M交换机则只能达到10M. 主要是访问互联网的速度,这个可以和电信部门推出的"宽带"和"窄带"用户一起综合理解,所谓"窄带"用户,一般指拨号上网用户,通过MODEM拨号上网速度一般不会超过64K,带宽很窄:而"宽带"用户指ADSL或社区宽带网用户,上网速度可以达到512K-100M(

服务器租用带宽独享还是共享

据中国互联网络信息中心(CNNIC)在京发布第38次<中国互联网络发展状况统计报告>中的统计数据显示,截至2016年6月,中国国际出口带宽为6,220,764Mbps,半年增长率为15.4%.主要骨干网络中国电信国际国际出口带宽为3,817,006Mbps,占据总量的一半以上. 国际出口带宽,一般是指国家的互联网国际出口的带宽也就是国家的互联网主干光纤的出口带宽.互联网由小网络组成的,有局域网,城域网.中国的所有网络又构成一个大的网络,这些中国网络要连接世界网络,于是就有了国际出口带宽,带宽越

下一代大数据处理引擎,阿里云实时计算独享模式重磅发布

摘要: 11月14日,阿里云重磅发布了实时计算独享模式,即用户独享一部分物理资源,这部分资源在网络/磁盘/CPU/内存等资源上跟其他用户完全独立,是实时计算在原有共享模式基础上的重大升级.(观看实时计算发布会直播:https://yq.aliyun.com/live/591) 独享模式优点更加突出1.UDX开放:实时计算的共享模式是多个用户共享一个物理机群,在网络/磁盘层面没有办法做到完全隔离. 11月14日,阿里云重磅发布了实时计算独享模式,即用户独享一部分物理资源,这部分资源在网络/磁盘/C

最全Java锁详解:独享锁/共享锁+公平锁/非公平锁+乐观锁/悲观锁

在Java并发场景中,会涉及到各种各样的锁如公平锁,乐观锁,悲观锁等等,这篇文章介绍各种锁的分类: 公平锁/非公平锁 可重入锁 独享锁/共享锁 乐观锁/悲观锁 分段锁 自旋锁 01.乐观锁 vs 悲观锁 乐观锁与悲观锁是一种广义上的概念,体现了看待线程同步的不同角度,在Java和数据库中都有此概念对应的实际应用. 1.乐观锁 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制. 乐观锁适用于多

服务器带宽限制10M独享,为何有时候会跑超呢?

问:10M独享,为什么有时候会跑超? 客 户托管在香港BGP机房的一台DELL服务器,因为应用是大流量类网站,就选择了10M独享:最近看了我们每周邮件发的服务器使用情况监控报表,无意中发现, 自己的网站有时下午两三点左右带宽是跑超的.这是什么怎么回事,是不是以后就不需要扩容带宽了,可以免费占用这部分资源? 答:其实这是一种正常现象. 限速都是基于一定策略实现的,比如QOS,无论数据中心,还是家庭宽带都是一样的方法,一些大数据包比如下载,有时就会超出限制.虽然是可以跑超,但只要超过限制的带宽,网络

韩国带宽最丰富机房 韩国10M-100M独享带宽套餐 联系QQ80584797

韩国带宽最丰富机房 韩国10M-100M独享带宽套餐  联系QQ80584797 韩国SK是韩国地区主要的通信运营商之一,该机房线路优越.硬件配置非常新,极适合长期商务用户使用. SK光州数据中心为韩国最新投入使用的绿色环保标榜企业,该数据中心提供目前韩国性价比最高的大带宽资源. 联邦在线是韩国八大主流机房的大陆总分销商,机房资源丰富 售后高效及时,服务器价格和售后服务方面均优秀于其他同行: 韩国SK全功能机房可以提供5IP机器,10M-100M独享带宽机器,以及高防机器 适合客户群体:商城网站