Neo_Matrix 0 August 29, 2021 Posted August 29, 2021 · Report post Рассматривал реализацию работы в стеке LWIP API, при вызовах API функций LWIP, можно встретить следующий код: err_t pppapi_close(ppp_pcb *pcb, u8_t nocarrier) { err_t err; PPPAPI_VAR_DECLARE(msg); PPPAPI_VAR_ALLOC(msg); PPPAPI_VAR_REF(msg).msg.ppp = pcb; PPPAPI_VAR_REF(msg).msg.msg.close.nocarrier = nocarrier; err = tcpip_api_call(pppapi_do_ppp_close, &PPPAPI_VAR_REF(msg).call); PPPAPI_VAR_FREE(msg); return err; } Внутри макроса PPPAPI_VAR_ALLOC вызывается malloc с соответствующими проверками, далее идет вызов функции tcpip_api_call из контекста задачи TCPIP, после вызывается макрос PPPAPI_VAR_FREE который внутри вызывает free с соответствующими проверками. Из кода видно,что зона видимости(существования) переменной msg ограничивается текущей функцией, соответственно возникает вопрос, для чего создавать переменную в динамической памяти, с возможной фрагментацией оной, если можно просто создать переменную на СТЕКЕ задачи, с такой же областью видимости? Или это необходимо для процессоров с MPU? Quote Share this post Link to post Share on other sites More sharing options...
jcxz 83 August 29, 2021 Posted August 29, 2021 · Report post 1 час назад, Neo_Matrix сказал: Из кода видно,что зона видимости(существования) переменной msg ограничивается текущей функцией, соответственно возникает вопрос, для чего создавать переменную в динамической памяти, с возможной фрагментацией оной, если можно просто создать переменную на СТЕКЕ задачи, с такой же областью видимости? Из вашего примера не видно даже что такое msg. Тем более не видна её область видимости (если это переменная). Можно только гадать. А использование дин.памяти, вместо стека, может быть например для того, чтобы не было необходимости раздувать до огромных значений стеки всех задач, которые будут вызывать эту функцию. И таким образом экономится ОЗУ. Quote Share this post Link to post Share on other sites More sharing options...
Neo_Matrix 0 August 29, 2021 Posted August 29, 2021 · Report post Копировать весь код и содержимое всех макросов достаточно накладно, скопирую основное. Это структура, внутри нее объединение, так что размер не велик, хотя и выглядит ужасающе. struct pppapi_msg_msg { ppp_pcb *ppp; union { #if PPP_NOTIFY_PHASE struct { ppp_notify_phase_cb_fn notify_phase_cb; } setnotifyphasecb; #endif /* PPP_NOTIFY_PHASE */ #if PPPOS_SUPPORT struct { struct netif *pppif; pppos_output_cb_fn output_cb; ppp_link_status_cb_fn link_status_cb; void *ctx_cb; } serialcreate; #endif /* PPPOS_SUPPORT */ #if PPPOE_SUPPORT struct { struct netif *pppif; struct netif *ethif; const char *service_name; const char *concentrator_name; ppp_link_status_cb_fn link_status_cb; void *ctx_cb; } ethernetcreate; #endif /* PPPOE_SUPPORT */ #if PPPOL2TP_SUPPORT struct { struct netif *pppif; struct netif *netif; API_MSG_M_DEF_C(ip_addr_t, ipaddr); u16_t port; #if PPPOL2TP_AUTH_SUPPORT const u8_t *secret; u8_t secret_len; #endif /* PPPOL2TP_AUTH_SUPPORT */ ppp_link_status_cb_fn link_status_cb; void *ctx_cb; } l2tpcreate; #endif /* PPPOL2TP_SUPPORT */ struct { u16_t holdoff; } connect; struct { u8_t nocarrier; } close; struct { u8_t cmd; void *arg; } ioctl; } msg; }; struct pppapi_msg { struct tcpip_api_call_data call; struct pppapi_msg_msg msg; }; Это некоторые макросы: #define PPPAPI_VAR_REF(name) API_VAR_REF(name) #define PPPAPI_VAR_DECLARE(name) API_VAR_DECLARE(struct pppapi_msg, name) #define PPPAPI_VAR_ALLOC(name) API_VAR_ALLOC_POOL(struct pppapi_msg, PPPAPI_MSG, name, ERR_MEM) #define PPPAPI_VAR_ALLOC_RETURN_NULL(name) API_VAR_ALLOC_POOL(struct pppapi_msg, PPPAPI_MSG, name, NULL) #define PPPAPI_VAR_FREE(name) API_VAR_FREE_POOL(PPPAPI_MSG, name) #define API_VAR_REF(name) (*(name)) #define API_VAR_DECLARE(type, name) type * name #define API_VAR_ALLOC_EXT(type, pool, name, errorblock) do { \ name = (type *)memp_malloc(pool); \ if (name == NULL) { \ errorblock; \ } \ } while(0) #define API_VAR_ALLOC(type, pool, name, errorval) API_VAR_ALLOC_EXT(type, pool, name, return errorval) #define API_VAR_ALLOC_POOL(type, pool, name, errorval) do { \ name = (type *)LWIP_MEMPOOL_ALLOC(pool); \ if (name == NULL) { \ return errorval; \ } \ } while(0) #define API_VAR_FREE(pool, name) memp_free(pool, name) Quote Share this post Link to post Share on other sites More sharing options...
jcxz 83 August 29, 2021 Posted August 29, 2021 · Report post Также иногда бывает необходимость в буфере в определённой памяти. Например - в памяти, с которой может работать DMA-контроллер (или ETHERNET-контроллер). А стеки задач могут находится например в TCM-памяти (к которой эта периферия не имеет доступа). Либо МК уходит в сон, а стек задачи находится в памяти, которая недоступна во сне, а периферия (для которрой выделяется память) должна продолжать работать и во сне. Quote Share this post Link to post Share on other sites More sharing options...
Neo_Matrix 0 August 29, 2021 Posted August 29, 2021 · Report post Спасибо. В целом так и предполагал, просто первое что пришло на ум, это MPU Quote Share this post Link to post Share on other sites More sharing options...