问题描述
所以我有下面的代码。如果我直接在 loopTask 中调用 //next.config.js
const rehypePrism = require("@mapBox/rehype-prism");
const withMDX = require("@next/mdx")({
extension: /\.mdx?$/,options: {
rehypePlugins: [rehypePrism],},});
module.exports = withMDX({
pageExtensions: ["js","jsx","ts","tsx","md","mdx"],});
函数,空闲堆是稳定的。但是,如果我使用该函数使用 signKey()
创建任务,空闲堆总是在减少。我错过了什么吗?
xTaskCreate()
这是使用任务的串行监视器上的输出:
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
FreeHeap: 358312
这是代码:
FreeHeap: 338364
FreeHeap: 337776
FreeHeap: 337228
FreeHeap: 336632
FreeHeap: 336080
FreeHeap: 335508
FreeHeap: 334960
FreeHeap: 334372
FreeHeap: 333812
FreeHeap: 333220
FreeHeap: 332672
FreeHeap: 332108
FreeHeap: 331552
FreeHeap: 330964
FreeHeap: 330416
FreeHeap: 329856
FreeHeap: 329304
FreeHeap: 328716
FreeHeap: 328152
更新:
我尝试在 #include "mbedtls/pk.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
static String privateKey = "-----BEGIN PRIVATE KEY-----\nMIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCID48Vp/9ydCMU\nzZ4n4iQ6pzr6eK+VCL7Lcpy8j/tBwLWk3jZ3ETmMm6Ua4MhUMc3ABN84uz0RgDi9\nb4RhOUy2SVbvfm5WZhlvpPmDD0yeTgWEyM3h3fBYPnRzMn/6KjsmCUgcfTWjdA+C\nj9vTL41j7bVCkU0/glBh5Rk3rKeImeX/lf4KfstguvJ+OlznCn039+tDlsCNrRgw\ni+L2AeI4UDZEDGWYRbONzU2WgJ11fr9J+Y6rSCwommDcxhdTtdlorZj2CFEtxRp5\nFCDm6Tvu0+aur8zpuhC+NFUWmYEHxztz18X1I4Pcy5cJpuqKL5t/Hxy5Yu7y32Ek\nE8DZv1DFAgMBAAECggEBAIBF+uW13tSuvSwttf9v6iwJ4UamZRKijg4MV6t9KqoQ\n3q8yeDLE4Ha5fmzaosMNuSZg8XnwvGA1fEjMTAfFF5d7iSR9E9UMqMpixIFU+Sz9\n7aIEFmXs8VygdPTuFU1qZx0y/vMs8FbLYpv6uIpfeHNPdeXuSt+nIdVJQf8FHWVg\nH7EJHJPCh0SoQZHQhV0M/n7K6iacXdC2k4AW2f2KtwPBOV19S+4Ymq7S6ycIyghd\nmMzMhWLgZYoPycMYQRDErEZOSHQHs+BqvKYqp/UVJNKAVihiqYXHmT8hnWMaaj8d\nQzVmcsq7dZO7vX+0Zfjd+krj9gbpCG30ESeNOx5sLAECgYEA0wDiGFyFAu6fVhm5\np4pHhGhFK765Ys3b5bapEgD1uN92BttPat2Qj11TKGdAERa8X0uuBB8McGcWUcvV\nFUIKYE0qj4k/oo7OEw5KmrQVlQLsWv4rls8XTEJcUnoq2lCTXzefuwEJFBkk4Bkb\nhioZE3CU0cV/Jg78vl37SJZbE4ECgYEApRNmRPCDWH8Jeo7OSqgee8Qy46R+JpBb\nmaaQ9dCO8pp5MYLQSA4C4BeHEpKq4v6C3HL7gf+Z6N/6/WU1X1bqDtXPdito5Zxc\nQ0Sa6URIPu7/txnu4Nc4GOfB6nG0/bxiqrDkxf7Kwk2E8xpmoCAQwDhg58Y1k61q\nO/iTjIJOj0UCgYEAo7yDtrPU47mYG5BK6R/871qakp+l7G4ivddIy5fDFnsRc7Cr\nqBnXG+knpqq4pIooEyr/FmOhm3fjcgXijGR6+M/ovwmaP+LhNxhX/ETSmpdyIgoq\neRSq15qHWdlDd7YfJPSA0vSyvs3kN6JEIZB5dQRf94hyam4m4vK7FFDYzAECgYEA\nlBiva7ILZF20d0ufL8NcddUzgp+UvaxNQa/55U7SsDx99jlR+xL26WyyNat3vGZx\nqK1PjvVtc0tete8SzxH+soiHs5CGb1i0PXVTNWuZFTz+FZU2VPFA1rc1dcvFgM59\np7osRKWt6lv5ptBMueOKo6jw538fmfm+kUcVuL0/FbECgYBx9ADNvyUaPq/3rQEa\n4Nzp+yyBL8r7iguLvI8EAYbCil9lACL+xXtScQ7mCY8EW8D8w/0cqA3Wjamb5ntS\n4T9Id1Iqq6MvzgJlTjNAYrsgoEC+fmU8iPnHNjxXrf74j4Mlh9pm5j6yeYsHQnMI\nv60FP7rcRiL2XnDJ5/ev/BWXaQ==\n-----END PRIVATE KEY-----";
static bool isTask = false;
static bool printSerial = false;
const char base64_chars[] = "ABCDEFGHIJKLMnopQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
static String base64_encode(const uint8_t *bytesToEncode,uint16_t len) {
String ret;
int i = 0;
int j = 0;
unsigned char char_array_3[3];
unsigned char char_array_4[4];
while (len--) {
char_array_3[i++] = *(bytesToEncode++);
if (i == 3) {
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (i = 0; (i < 4); i++) {
ret += base64_chars[char_array_4[i]];
}
i = 0;
}
}
if (i) {
for (j = i; j < 3; j++) {
char_array_3[j] = '\0';
}
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (j = 0; (j < i + 1); j++) {
ret += base64_chars[char_array_4[j]];
}
}
return ret;
}
static String base64_encode(String str) {
return base64_encode((const unsigned char *) str.c_str(),str.length());
}
uint8_t buffer[2000];
static void signKey(void *parameter) {
String header = "{\"typ\":\"JWT\",\"alg\":\"RS256\"}";
String payload = "{\"payload\":\"my-payload\"}";
String content = base64_encode(header) + "." + base64_encode(payload);
mbedtls_pk_context pk_context;
mbedtls_pk_init(&pk_context);
int rc = mbedtls_pk_parse_key(&pk_context,(uint8_t*)privateKey.c_str(),privateKey.length() + 1,NULL,0);
if (rc != 0) {
mbedtls_pk_free(&pk_context);
if (printSerial)Serial.println("Failed to parse private key (err_code: 0x" + String(rc,HEX) + ")");
if (isTask)vTaskDelete(NULL);
}
mbedtls_entropy_context entropy;
mbedtls_entropy_init(&entropy);
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_ctr_drbg_init(&ctr_drbg);
const char* pers = "firebase-jwt";
mbedtls_ctr_drbg_seed(&ctr_drbg,mbedtls_entropy_func,&entropy,(const unsigned char*)pers,strlen(pers));
uint8_t digest[32];
rc = mbedtls_md(mbedtls_md_info_from_type(MbedTLS_MD_SHA256),(uint8_t*)content.c_str(),content.length(),digest);
if (rc != 0) {
mbedtls_pk_free(&pk_context);
mbedtls_entropy_free(&entropy);
mbedtls_ctr_drbg_free(&ctr_drbg);
if (printSerial)Serial.println("Failed to digest content (err_code: 0x" + String(rc,HEX) + ")");
if (isTask)vTaskDelete(NULL);
}
size_t retSize;
rc = mbedtls_pk_sign(&pk_context,MbedTLS_MD_SHA256,digest,sizeof(digest),buffer,&retSize,mbedtls_ctr_drbg_random,&ctr_drbg);
if (rc != 0) {
mbedtls_pk_free(&pk_context);
mbedtls_entropy_free(&entropy);
mbedtls_ctr_drbg_free(&ctr_drbg);
if (printSerial)Serial.println("Failed to sign content (err_code: 0x" + String(rc,HEX) + ")");
if (isTask)vTaskDelete(NULL);
}
String signature = base64_encode(buffer,retSize);
if (printSerial)Serial.println(signature);
mbedtls_pk_free(&pk_context);
mbedtls_entropy_free(&entropy);
mbedtls_ctr_drbg_free(&ctr_drbg);
if (isTask)vTaskDelete(NULL);
}
void tryTask() {
isTask = true;
xTaskCreate(signKey,"signKey",4096,1,NULL);
}
void tryDirectCall() {
isTask = false;
signKey(NULL);
}
void setup() {
Serial.begin(115200);
}
void loop() {
tryTask();
//tryDirectCall();
Serial.println("FreeHeap: " + String(ESP.getFreeHeap()));
delay(5000);
}
上创建任务并使任务不断循环,没有发生减少的空闲堆!所以这个问题只存在于我动态创建和删除任务时。为什么会发生这种情况?
解决方法
ESP32 有两种类型的内存——数据和指令。 Arduino 包装器返回 rather liberal interpretation 的空闲堆 - 查询的 cabability MALLOC_CAP_INTERNAL 可能包括这两种类型。所以可能只是代码缓存被一次性线程的垃圾填满了。
那个,或者你正在泄漏。在任何情况下,一次性线程都不是 micros 上常用的做法 - 它们使一切变得更加困难,包括此类分析。标准方法是在启动时创建一个永久的 FreeRTOS 任务,并在它必须执行某些操作时通过消息队列将工作项传递给它。我可以推荐 FreeRTOS tutorial 作为一个很好的资源。