【问题标题】:Running pipe of subprocess in ESP32 using ANSI C使用 ANSI C 在 ESP32 中运行子进程的管道
【发布时间】:2021-03-18 19:27:22
【问题描述】:

我正在使用esp-idf 进入ESP32,我想让一个程序能够在使用C 时运行子进程。

通常,我尝试调用如下函数:

...
  #include <stdio.h>

  char *cmd = "ls -l";    
  char buf[BUFSIZE];
  FILE *fp;
  if ((fp = popen(cmd, "r")) == NULL) {
      printf("############## Error opening pipe!\n");
      return -1;
  }
  while (fgets(buf, BUFSIZE, fp) != NULL) {
      printf("############## OUTPUT: %s", buf);
  }
  if(pclose(fp))  {
      printf("############## Command not found or exited with error status\n");
      return -1;
  }
  return 0;
...

但应用程序返回

c:\esp\../main/app_main.c:139: undefined reference to `popen`

有人有这方面的经验吗?

【问题讨论】:

  • 您使用的工具链最有可能用于“裸机”,因此并未实现所有标准库。

标签: c subprocess pipe esp32


【解决方案1】:

popen() 是在 POSIX 兼容系统和类似系统(UNIX、Linux、FreeBSD)上可用的系统调用。 ESP32 运行的软件远程不兼容 POSIX。

管道和子流程在 ESP32 上毫无意义 - 不受支持。没有popen() 电话。

ESP32 运行名为FreeRTOS 的轻量级操作系统。 FreeRTOS 提供轻量级任务和非常简单的内存管理,仅此而已。

FreeRTOS 任务共享一个地址空间;它们通常是非抢占式的,自愿让出处理器以允许其他任务运行,并执行子例程(C 函数)。每个 POSIX 进程都有自己的地址空间,是抢占式的并运行 POSIX 二进制应用程序。它们是完全不同的、不相容的东西。 ESP32 没有资源或内存管理硬件来正确支持 POSIX 进程。

ESP-IDF(“物联网开发框架”)是在 FreeRTOS 之上构建的一个层,它提供了一个瘦 API,可用于访问 ESP32 的硬件(I2C、SPI、wifi、蓝牙、定时器等)。

Arduino CorePythonLUA 等其他编程环境都建立在 ESP-IDF 之上。

与 POSIX 风格的系统不同,ESP-IDF 一次运行一个程序。该程序是您编译、链接并存储在其闪存中的程序。 POSIX 风格的系统一次运行成百上千个程序。 ESP32 和 ESP-IDF 没有这个能力。

当您开始为 ESP32 构建应用程序时,您不仅不能使用与 POSIX 兼容的系统调用,还需要学习在资源非常有限的环境中编程。在 Linux 和类似系统上,程序员通常编写代码,就好像对内存、文件系统大小和持久性没有限制一样。这些事情在 ESP32 上都不是真的——编写一个意外需要比其可用的 520KB 更多内存的程序是微不足道的;编写一个期望比其闪存中可用的更多持久存储的程序是微不足道的;编写一个如此频繁地写入闪存以致于破坏它的程序是微不足道的。您需要学习如何在 ESP32 的约束下进行编程,而不仅仅是如何编写调用 ESP-IDF 而不是 POSIX 系统的代码。

阅读您链接到的 ESP-IDF 文档。这就是你工作的环境。你可能会发现从 Arduino Core 开始会更容易——它是一个 C/C++ 环境,有大量的教程,它是一个更简单的构建环境,你可以如果需要,仍然可以轻松地从中调用 ESP-IDF 函数。

【讨论】:

  • 好,详细的回答!只有一件事:在 IDF 上,调度仍然是抢占式的。至少这是我从为 ESP32 编写 FreeRTOS 端口的人那里得到的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-01
  • 1970-01-01
  • 2010-10-09
  • 1970-01-01
相关资源
最近更新 更多