RT-Thread论坛
直播中

李郝荫

8年用户 1414经验值
私信 关注
[问答]

alloc_socket在不断创建socket时会不断新建信号量和互斥锁,导致内存泄漏,怎么解决?

alloc_socket在不断创建socket时会不断新建信号量和互斥锁,导致内存泄漏。
修改前:

  • static struct wiz_socket *alloc_socket(void)
  • {
  •     static rt_mutex_t wiz_slock = RT_NULL;
  •     struct wiz_socket *sock = RT_NULL;
  •     char name[RT_NAME_MAX] = {0};
  •     int idx = 0;

  •     if (wiz_slock == RT_NULL)
  •     {
  •         /* create WIZnet socket lock */
  •         wiz_slock = rt_mutex_create("w_lock", RT_IPC_FLAG_FIFO);
  •         if (wiz_slock == RT_NULL)
  •         {
  •             LOG_E("No memory for WIZnet socket lock!");
  •             return RT_NULL;
  •         }
  •     }

  •     rt_mutex_take(wiz_slock, RT_WAITING_FOREVER);

  •     /* find an empty WIZnet socket entry */
  •     for (idx = 0; idx < WIZ_SOCKETS_NUM && sockets[idx].magic; idx++);

  •     /* can't find an empty protocol family entry */
  •     if (idx == WIZ_SOCKETS_NUM)
  •     {
  •         goto __err;
  •     }

  •     sock = &(sockets[idx]);
  •     sock->magic = WIZ_SOCKET_MAGIC;
  •     sock->socket = idx;
  •     sock->port = 0;
  •     sock->state = SOCK_CLOSED;
  •     sock->remote_addr = RT_NULL;
  •     sock->recv_timeout = 0;
  •     sock->send_timeout = 0;
  •     sock->rcvevent = 0;
  •     sock->sendevent = 0;
  •     sock->errevent = 0;
  •     /* for server socket */
  •     sock->svr_info = RT_NULL;

  •     rt_snprintf(name, RT_NAME_MAX, "%s%d", "wiz_sr", idx);
  •     /* create WIZnet socket receive mailbox */
  •     if ((sock->recv_notice = rt_sem_create(name, 0, RT_IPC_FLAG_FIFO)) == RT_NULL)
  •     {
  •         goto __err;
  •     }

  •     rt_snprintf(name, RT_NAME_MAX, "%s%d", "wiz_sr", idx);
  •     /* create WIZnet socket receive ring buffer lock */
  •     if ((sock->recv_lock = rt_mutex_create(name, RT_IPC_FLAG_FIFO)) == RT_NULL)
  •     {
  •         goto __err;
  •     }

  •     rt_mutex_release(wiz_slock);
  •     return sock;

  • __err:
  •     rt_mutex_release(wiz_slock);
  •     return RT_NULL;
  • }


修改后:

  • static struct wiz_socket *alloc_socket(void)
  • {
  •     static rt_mutex_t wiz_slock = RT_NULL;
  •     struct wiz_socket *sock = RT_NULL;
  •     char name[RT_NAME_MAX] = {0};
  •     int idx = 0;

  •     if (wiz_slock == RT_NULL)
  •     {
  •         /* create WIZnet socket lock */
  •         wiz_slock = rt_mutex_create("w_lock", RT_IPC_FLAG_FIFO);
  •         if (wiz_slock == RT_NULL)
  •         {
  •             LOG_E("No memory for WIZnet socket lock!");
  •             return RT_NULL;
  •         }
  •     }

  •     rt_mutex_take(wiz_slock, RT_WAITING_FOREVER);

  •     /* find an empty WIZnet socket entry */
  •     for (idx = 0; idx < WIZ_SOCKETS_NUM && sockets[idx].magic; idx++);

  •     /* can't find an empty protocol family entry */
  •     if (idx == WIZ_SOCKETS_NUM)
  •     {
  •         goto __err;
  •     }

  •     sock = &(sockets[idx]);
  •     sock->magic = WIZ_SOCKET_MAGIC;
  •     sock->socket = idx;
  •     sock->port = 0;
  •     sock->state = SOCK_CLOSED;
  •     sock->remote_addr = RT_NULL;
  •     sock->recv_timeout = 0;
  •     sock->send_timeout = 0;
  •     sock->rcvevent = 0;
  •     sock->sendevent = 0;
  •     sock->errevent = 0;
  •     /* for server socket */
  •     sock->svr_info = RT_NULL;

  •     rt_snprintf(name, RT_NAME_MAX, "%s%d", "wiz_sr", idx);
  •     /* create WIZnet socket receive mailbox */
  •     if (sock->recv_notice == RT_NULL) {
  •         if ((sock->recv_notice = rt_sem_create(name, 0, RT_IPC_FLAG_FIFO)) == RT_NULL)
  •         {
  •             goto __err;
  •         }
  •     }

  •     rt_snprintf(name, RT_NAME_MAX, "%s%d", "wiz_sr", idx);
  •     /* create WIZnet socket receive ring buffer lock */
  •     if (sock->recv_lock == RT_NULL) {
  •         if ((sock->recv_lock = rt_mutex_create(name, RT_IPC_FLAG_FIFO)) == RT_NULL)
  •         {
  •             goto __err;
  •         }
  •     }

  •     rt_mutex_release(wiz_slock);
  •     return sock;

  • __err:

  •     // 释放资源
  •     rt_sem_delete(sock->recv_notice);
  •     rt_mutex_delete(sock->recv_lock);
  •     sock->recv_notice = RT_NULL;
  •     sock->recv_lock = RT_NULL;

  •     rt_mutex_release(wiz_slock);
  •     return RT_NULL;
  • }


还得添加修改:
return -1前需要释放socket

  • int wiz_socket(int domain, int type, int protocol)
  • {
  •     struct wiz_socket *sock = RT_NULL;
  •     uint8_t socket_type = 0;
  •     uint8_t socket_state = 0;

  •     /* check WIZnet initialize status */
  •     WIZ_INIT_STATUS_CHECK;

  •     /* check socket family protocol */
  •     RT_ASSERT(domain == 46 || domain == 2);

  •     switch (type)
  •     {
  •     case SOCK_STREAM:
  •         socket_type = Sn_MR_TCP;
  •         break;

  •     case SOCK_DGRAM:
  •         socket_type = Sn_MR_UDP;
  •         break;

  •     case SOCK_RAW:
  •         socket_type = Sn_MR_IPRAW;
  •         break;

  •     default:
  •         LOG_E("don't support socket type (%d)!", type);
  •         return -1;
  •     }

  •     /* allocate and initialize a new WIZnet socket */
  •     sock = alloc_socket();
  •     if (sock == RT_NULL)
  •     {
  •         LOG_E("allocate a new WIZnet socket failed!");
  •         return -1;
  •     }
  •     sock->type = socket_type;

  • #ifdef SAL_USING_POSIX
  •     rt_wqueue_init(&sock->wait_head);
  • #endif

  •     socket_state = getSn_SR(sock->socket);
  •     if (socket_state == SOCK_CLOSED)
  •     {
  •         switch (sock->type)
  •         {
  •         case Sn_MR_TCP:
  •             if (wizchip_socket(sock->socket, sock->type, wiz_port, Sn_MR_ND) != sock->socket)
  •             {
  •                 LOG_E("WIZnet TCP socket(%d) create failed!", sock->socket);
  •                 free_socket(sock);
  •                 rt_memset(sock, 0x00, sizeof(struct wiz_socket));
  •                 return -1;
  •             }
  •             sock->port = wiz_port++;
  •             break;

  •         case Sn_MR_UDP:
  •         case Sn_MR_IPRAW:
  •             if (wizchip_socket(sock->socket, sock->type, wiz_port, 0) != sock->socket)
  •             {
  •                 LOG_E("WIZnet UDP socket(%d) create failed!", sock->socket);
  •                 free_socket(sock);
  •                 rt_memset(sock, 0x00, sizeof(struct wiz_socket));
  •                 return -1;
  •             }
  •             sock->port = wiz_port++;
  •             break;

  •         default:
  •             LOG_E("Socket (%d) type %d is not support.", sock->socket, sock->type);
  •             free_socket(sock);
  •             rt_memset(sock, 0x00, sizeof(struct wiz_socket));
  •             return -1;
  •         }
  •     }
  •     else
  •     {
  •         free_socket(sock);
  •         rt_memset(sock, 0x00, sizeof(struct wiz_socket));
  •         LOG_E("socket(%d) is not closed(0x%x).", sock->socket, socket_state);
  •         return -1;
  •     }
  •     sock->state = SOCK_INIT;

  •     return sock->socket;
  • }




回帖(1)

刘丰标

2025-9-10 17:38:30
sock释放时,对应的recv_notice和recv_lock没有释放吗?
感觉在那里释放更合理些,不然只要申请过,后面即使不用了,也会一直占用资源。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分