ESP32中直接调用lwip_close无法正确释放资源,导致后续文件描述符无法正确创建

12 篇文章 3 订阅
6 篇文章 1 订阅
本文分析了lwip_close函数为何无法完全释放Socket资源,重点在于select_waiting计数的管理。通过探究select函数的细节,发现资源假占用源于lwip_close时机的不确定性。解决方案是调整close和shutdown接口的调用顺序。关键词:lwip_close, select_waiting, Socket资源, 资源释放, lwip_close问题
摘要由CSDN通过智能技术生成

        由最开始进行Socket创建开始:

         后面按照这个接口中的调用情况,查看到了接口函数alloc_socket,该函数的主要功能为为给定的Socket连接分配一个新的套接字。

        在该函数里面有如下的一个逻辑:

        可以看到,判断socket资源是否有人在使用时,除了判断socket->conn是否为空,还会判断select_waiting是否等于0。其中select_waiting标识该socket正在被多少个线程在使用。即要释放socket资源两个重要条件是,socket->conn必须为空,并且select_waiting要为0。
接下来看看lwip_close函数的实现,看为啥会导致资源释放不完全。


在lwip_close里面还未调用free_socket(sock, is_tcp);

        free_socket(sock, is_tcp);该函数功能为对数据空间进行释放和对socket->conn置空,该函数的调用在这个函数的最后一步:

    但值接调用也会出现问题:
        上述函数分析可知,lwip_close函数只能使socket->conn为空,并不能使select_waiting为0,所以其实只有lwip_close函数是不能使socket资源完全释放的。
从select_waiting名字中能比较容易的猜到,该变量跟select函数肯定是强相关的。全局搜索select_waiting,果然只有select函数有进行写操作。下面分析select函数:


        参考上述代码分析,特别注意socket->select_waiting加1和减1的地方,可以看到,如果socket存在且的确需要监听事件,且并不是进来事件就已经产生或者已经超时,一定会加1;然后线程会有可能会进行休眠;正常情况下,休眠结束后,socket->select_waiting减1,离开该函数,socket->select_waiting恢复原值。但是,如果在线程休眠期间,恰巧在另外一个线程进行了lwip_close操作,事件就会有问题。
        如果在休眠期间进行了lwip_close(socket),则通过tyr_socket(socket)获取不到socket结构体,则socket->select_waiting不会进行减1,后面执行一系列语句后,退出该函数,socket->select_waiting没有恢复原值,且比进来时大1。针对该函数,socket->select_waiting加1的次数是>=减1的次数,所以如果只要在函数退出时没有恢复原值,则socket->select_waiting永远不可能再减为0了,此时socket资源就出现了假占用,该socket再也不能被其他人使用了。


由此多了如下操作:

        接口LWIP_API_LOCK();的功能为在等待信号量时阻塞线程发出信号。如果“超时”参数非零,线程应该仅在指定时间内被阻止。主要达到让socket->select_waiting清零的效果,而接口LWIP_SET_CLOSE_FLAG();主要是设置标志位,让接口LWIP_API_UNLOCK();调用free_socket进行空间释放和socket->conn清零的效果。

         最后的解决方案就是:将lwip_close和lwip_shutdown接口调换为close和shutdown。

        扩展:1. close  把描述符的引用计数减一,仅在该计数变为0时才关闭套接字。而shutdown可以并以不管引用计数就激发TCP的正常连接终止序列
        2. close终止读和写两个方向的数据传送,而shutdown可以指定哪个方向被关闭,读端还是写端还是两个都关闭

  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浮若于心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值