首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >实现mbedtls和xTaskCreate()在ESP32 (Arduino IDE)上导致内存泄漏

实现mbedtls和xTaskCreate()在ESP32 (Arduino IDE)上导致内存泄漏
EN

Stack Overflow用户
提问于 2021-01-08 11:44:57
回答 1查看 434关注 0票数 0

我有下面的代码。如果我在signKey()中直接调用loopTask函数,那么空闲堆是稳定的。但是,如果我使用该函数使用xTaskCreate()创建任务,那么空闲堆总是在减少。我是不是遗漏了什么?

下面是使用直接调用的串行监视器上的输出:

代码语言:javascript
运行
复制
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

下面是使用任务的串行监视器上的输出:

代码语言:javascript
运行
复制
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

这是密码:

代码语言:javascript
运行
复制
#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, NULL, 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);
}

更新:我尝试在setup()上创建任务,并使任务不断循环,没有出现减少的空闲堆!因此,这个问题只存在于我动态创建和删除任务时。为什么会发生这种事?

EN

回答 1

Stack Overflow用户

发布于 2021-01-08 16:35:31

ESP32有两种类型的内存-数据和指令。Arduino包装器返回空闲堆的相当宽松的解释 --被查询的内部可能包括这两种类型。因此,它可能只是被来自单个使用线程的垃圾填充的代码缓存。

不然你就漏水了。无论如何,单用线程并不是微系统上常用的实践--它们使一切变得更加困难,包括这样的分析。标准方法是在启动时创建一个永久的FreeRTOS任务,并在需要做什么时将其工作项传递给消息队列。我可以推荐FreeRTOS教程作为一个优秀的资源。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65628352

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档