最近在做Android P蓝牙协议栈的适配,由于原生的android系统在关闭蓝牙时,协议栈所在的进程会退出,所以协议栈中的资源释放做的很不完善,项目开发完成后做开关蓝牙的压力测试,100多次就会crash,原因是semaphore_new失败。
而semaphore_new失败的原因是Too many open files导致eventfd(...)返回INVALID_FD。
eventfd失败可以通过添加log定位到哪些thread\Alarm\Fixed_queue没有free,处理之后,可以确认eventfd不会再有泄漏;
但开关蓝牙400+以后再次测到了相同问题“Too many open files”,这次的原因是系统中fd超过上限,导致eventfd无法分配出fd。
而找到这个泄漏的fd的方法是通过linux指令:lsof
android系统使用:adb shell lsof PID
结果打印如下,可以发现/sys/power/wake_lock及wake_unlock发生了泄漏。
查看指定进程的所有线程
ps -t -p <pid>
“SID”栏表示线程ID,而“CMD”栏则显示了线程名称。
以下才是精华,内容摘自lkforce 的文章,学习了!原文:https://blog.csdn.net/lkforce/article/details/80710459
Linux中所有的事物或资源都是以文件的形式存在,比如消息、共享内存、连接等,句柄可以理解为指向这些文件的指针。
对于这些句柄,Linux是有数量限制的,单个进程默认可以打开的句柄数上限,可以用以下命令来查看:
ulimit –a
执行结果如下:
其中的open files一项就是默认的句柄数,此时默认的句柄数是1024
还可以设置某个进程的句柄数上限,命令是:
ulimit –a PID
执行结果如下:
也是看open files一项,可以看到,该进程的句柄上限也是1024
这个句柄数是可以改的,修改默认的句柄数,命令如下:
ulimit –n 2000
这个命令可以把默认的句柄数改为2000,但系统重启后会恢复默认值
这个文件在系统中的默认值配置在/etc/security/limits.conf文件中,加入以下配置:
* soft nofile 2000
* hard nofile 2000
或者
* - nofile 2000
其中hard的设置是实际的默认值,也就是上限,而soft的配置只是用来警告的,如果超过了soft的值,会有warn,而第三种用短横线– 的配置,则是hard和soft同时配置的方式。
下面看一下如何查询系统中进程占用的句柄数
使用的命令是:
lsof -n|awk '{print $2}'|sort|uniq -c|sort-nr|more
lsof命令是Linux中的一个系统监视命令,可以查看进程打开的文件、端口等,功能强大,上面的命令通过一串的管道后只保留了句柄数和PID,执行结果如下:
第一列是句柄数,第二列是进程id
可以看到前两个进程的句柄数已经超过上限了,这正是这两个进程的日志正在报文章最上方的异常。
下面查询某个进程都占用了一些什么样的句柄
比如查询PID为25950的进程,使用的命令是
lsof |grep 25950
执行结果如下:
这里是截取的一部分,每列的含义如下:
1,进程名称
2,PID
3,进程所有者
4,文件描述符
5,文件类型
文件类型有以下几种:
DIR:表示目录。
CHR:表示字符类型。
BLK:块设备类型。
UNIX: UNIX 域套接字。
FIFO:先进先出 (FIFO) 队列。
IPv4:网际协议 (IP) 套接字。
DEVICE:指定磁盘的名称
SIZE:文件的大小
NODE:索引节点(文件在磁盘上的标识)
NAME:打开文件的确切名称