Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
LWIP
STM32F407
5
tcpip线程被mu0锁住导致网络线程无法使用问题
发布于 2025-03-12 20:56:47 浏览:59
订阅该版
各位好,我使用rtthread开发STM32F407VGT6芯片,程序有多个线程,每个线程都会创建一个socket,建立tcp连接或者udp连接,现在出现一个问题,程序长时间运行有概率死机,但是没有任何hardfault打印,我加入了cmbacktrace也没有输出任何信息,我在串口的msh里输入任何数据都不会相应,多次输入会提示接收字符缓存区满了。 后来根据检查发现,我的CAN接收发送线程和RS485接收发送线程没死,我在程序里添加了一个接收指定字符后,打印一些函数结果的代码,代码如下: ```c ch = uart_sample_get_char(); // LOG_D("ch = %d",ch); if(ch == 0x01) { mem_monitor2(NULL); list_thread(); list_sem(); list_msgqueue(); list_mutex(); list_timer(); } else if(ch == 0x02) { for(int i=0;i < 8; i ++) { if(lock[i]->owner != RT_NULL) { rt_kprintf("Mutex %s held by thread: %s\n", lock[i]->parent.parent.name, lock[i]->owner->name); }else { rt_kprintf("Mutex %s is free\n", lock[i]->parent.parent.name); } } } else if(ch == 0x03) { msh_close_sockets(); } ``` 这里的msh_close_sockets()作用是关闭所有的socket,函数的代码如下,: ```c void msh_close_sockets(void) { for (int var = 0; var < 8; ++var) { rt_mutex_take(lock[var], RT_WAITING_FOREVER); if(sock[var] != server_cfg_num && sock[var] != server_execute_num && sock[var] != server_udp_num && sock[var] >= 0){ if(shutdown(sock[var], SHUT_RDWR) >= 0) { if(closesocket(sock[var]) >= 0) { LOG_D("===== close %d successs! =====",var); sock[var] = -1; } else { LOG_D("===== close %d fail! =====",var); } } else { LOG_D("===== shutdown %d fail! =====",var); } } rt_mutex_release(lock[var]); } rt_pin_write(ETH_RESET, 0); rt_thread_mdelay(1000); rt_pin_write(ETH_RESET, 1); } ``` 根据测试发现,list_mutex()函数,打印了一些线程锁,我看到一个tcpip线程被一个mu0锁住了,后面有4个线程在等待mu0,我估计问题就是这个情况导致的,但是我不知道该怎么查了,请问有没有人能够提供一些帮助的。。。
查看更多
2
个回答
默认排序
按发布时间排序
lchnu
3小时前
Witness, Understand, Skill
**先说说我知道的**,mu0互斥量是lwip的内部锁,实际上是lock_tcpip_core,在lwip的内部线程和相关回调函数中(如connect,socket,setsockopt,recv等)中进行调用。加锁使用宏LOCK_TCPIP_CORE,解锁使用UNLOCK_TCPIP_CORE。 对于recv而言,实际上对应lwip_recvfrom,其使用锁的层次比较深,是通过传入函数指针lwip_netconn_do_recv来调用的。但是流程要先拿到锁,才能调用lwip_netconn_do_recv。 而对于lwip内部而言,实际上只有一个tcpip单线程,在不停地的拿锁/解锁mu0。 **再说说我不知道的**,不清楚你的parse_sensor_data函数内部是否要获得lock[id]锁?这里没有提供代码,也无法深入分析了。 既然你的各个sensor线程都是独立的,仅仅是id不同,**可以考虑仅仅在替换sock[id]时进行加锁**(我不太懂你在此处用私有锁的原因)。这样可以规避lwip的核心锁被长时间占用和潜在的锁竞争,也减少分析难度。我还注意到,你的msh_close_sockets中的第一个for循环是++var,说明你的私有锁下标是从1开始的。如果该锁是必须的,建议从下标0开始。
Eternalxl
5小时前
这家伙很懒,什么也没写!
我的初始化socket的代码如下: ```c ret_t socket_init(int id){ // LOG_I("socket init:%d", id); rt_mutex_take(lock[id], RT_WAITING_FOREVER); if(sock[id] >= 0){ closesocket(sock[id]); sock[id] = -1; } int new_sock = socket(AF_INET, SOCK_STREAM, 0); if (new_sock == -1) { LOG_E("Socket[%d] error\n", id); // rt_kprintf("Socket[%d] create error\n", id); rt_mutex_release(lock[id]); return RET_FAIL; } struct timeval tv_out = {60, 0}; if(id >= 1 && id <= 4){ tv_out.tv_sec = 60; }else{ tv_out.tv_sec = 10; } // if(id == IDX_LIGHT){ // tv_out.tv_sec = 3; // } setsockopt(new_sock, SOL_SOCKET, SO_RCVTIMEO, &tv_out, sizeof(tv_out)); tv_out.tv_sec = 3; setsockopt(new_sock, SOL_SOCKET, SO_CONTIMEO, &tv_out, sizeof(tv_out)); int val = 1; setsockopt(new_sock, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)); // 设置 KeepAlive 时间(单位:秒) int keepidle = 5; // 5秒后开始发送探测包 setsockopt(new_sock, IPPROTO_TCP, TCP_KEEPIDLE, &keepidle, sizeof(keepidle)); // 设置 KeepAlive 探测间隔 int keepintvl = 1; // 每 1秒 发送一次探测包 setsockopt(new_sock, IPPROTO_TCP, TCP_KEEPINTVL, &keepintvl, sizeof(keepintvl)); // 设置 KeepAlive 探测次数 int keepcnt = 1; // 最多 1 次探测包 setsockopt(new_sock, IPPROTO_TCP, TCP_KEEPCNT, &keepcnt, sizeof(keepcnt)); // 直接解析IP地址 struct sockaddr_in server_addr = {0}; server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port[id]); // 关键:使用inet_pton替代getaddrinfo if (inet_pton(AF_INET, url[id], &server_addr.sin_addr) <= 0) { rt_kprintf("Invalid IP address: %s\n", url[id]); closesocket(new_sock); rt_mutex_release(lock[id]); return RET_FAIL; } // 连接服务器 if (connect(new_sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) == 0) { sock[id] = new_sock; rt_mutex_release(lock[id]); return RET_OK; } else { closesocket(new_sock); rt_mutex_release(lock[id]); return RET_FAIL; } } ```
撰写答案
登录
注册新账号
关注者
1
被浏览
59
关于作者
Eternalxl
这家伙很懒,什么也没写!
提问
2
回答
1
被采纳
0
关注TA
发私信
相关问题
1
RT-THREAD在STM32H747平台上移植lwip
2
{lwip}使能RT_LWIP_DHCP时可以获取到ip
3
stm32f103 LWIP 2.0.2 TCP收发问题
4
lwip2.1不重启修改IP
5
关于网络协议栈的测试
6
可否将LWIP升级到2.1.2 和 2.0.3?
7
socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
8
tcpclient 插拔网线问题?
9
两个tcpclient同时通讯可以吗?
10
SO_BINDTODEVICE 未定义该如何解决
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
【FRA156测评DM-MCX】- 环境配置篇
2
【基于HPM6750+RW007的网页服务器】---SD卡文件系统
3
有关RT_thread studio使用WDT的一点经验
4
ART-PI2 上手记录(一)
5
【基于HPM6750+RW007的网页服务器】---rw007软件包添加
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
rt-smart
FAL
I2C_IIC
ESP8266
UART
cubemx
WIZnet_W5500
ota在线升级
PWM
BSP
flash
freemodbus
packages_软件包
潘多拉开发板_Pandora
GD32
定时器
ADC
flashDB
编译报错
socket
中断
rt_mq_消息队列_msg_queue
Debug
keil_MDK
msh
ulog
SFUD
C++_cpp
MicroPython
本月问答贡献
张世争
1
个答案
2
次被采纳
crystal266
4
个答案
1
次被采纳
lchnu
3
个答案
1
次被采纳
聚散无由
2
个答案
1
次被采纳
sakumisu
1
个答案
1
次被采纳
本月文章贡献
出出啊
1
篇文章
3
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
1
次点赞
crystal266
2
篇文章
1
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部