• 排查file-max limit 65536 reached错误


    近期遇到服务器宕机,重启后排查系统日志,看到/var/log/messages中在宕机前出现大量file-max limit 65536 reached错误:

    报file-max limit reached,说明机器上文件句柄的使用量超过了设定值,以下是排查过程的整理。先说怎么看文件句柄数,这个数据记在/proc/sys/fs/file-nr中:

    图中1056表示当前已打开文件句柄数量,65536表示最大数量。最大值由/proc/sys/fs/file-max控制,可以通过echo 100000 > /proc/sys/fs/file-max来修改。由于出现宕机前新部署了应用,因此怀疑与它有关,通过不断刷新,发现此应用运行时确实导致文件句柄上升,一段时间后上升至6000多。在linux下很多操作都会占用文件句柄,比如打开文件、打开目录、socket、pipe、共享内存等,首先怀疑有文件open后没有close,用lsof查下:

    可以看到数量很少,排查系统内其它进程,lsof -n | awk '{print $2}' | sort | uniq -c | sort -nr | head,看到没有哪个进程占用大量文件,那多出的5000多个句柄应该不是文件,往共享内存方向排查,用pmap看看进程是否有mmap相关操作:

    5392,这下对上了,用pmap进一步分析,发现有大量config.dat存在:

    找到开发排查源码,发现对此文件的使用涉及了mmap操作,先open文件,然后用mmap把文件映射到内存,再close文件,结果用完后没有munmap操作,导致文件句柄不断上涨。

    问题定位了,翻回来看为什么文件close了依然会导致文件句柄上涨。每个打开的文件都会有一个句柄用于描述文件属性,进程中用一个整数型的文件描述符指向具体的句柄。由于linux内核中对文件描述符是使用引用计数管理,mmap后,引用计数+1,此时尽管close了文件描述符,但引用计数不为0,内核不会回收文件句柄。

    写个小程序验证一下:

    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <sys/mman.h>
    
    int main()
    {
        int i;
        for(i = 0;i < 1000;++i)
        {
            int fd;
            char * addr;
            fd = open("/dev/zero", O_RDONLY);        //打开文件
            if(!fd)
                exit(1);
    
            addr = mmap(NULL, 4096, PROT_READ, MAP_PRIVATE, fd, 0);        //映射
            //munmap(addr, 4096);                    //此行不执行就会导致句柄上涨
            close(fd);                                //关闭文件
        }
    
        pause();
    }

    重复1000次,每次open和close是匹配的,但mmap没有munmap,执行后的效果:

    和预期一致,加上munmap后,对比测试则不会再出现这1000个句柄占用。

  • 相关阅读:
    SD卡性能测试
    在程序内动态获取svn版本号
    在SharePoint 2010程序中使用Session
    图片预读
    CSS图片垂直居中方法整理集合 !(常见问题解答)
    cpld的入门交流之二:秒信号发生器
    基于json数据的jQuery无限级下拉菜单插件
    MySQL 按指定字段自定义列表排序
    10张图让你更了解博客
    IE6 CSS bug: position:relative变成了absolute
  • 原文地址:https://www.cnblogs.com/BoyTNT/p/15011207.html
Copyright © 2020-2023  润新知