【C】自己写的shell命令打印函数 rkcmd 运行崩溃

发布于:2025-07-06 ⋅ 阅读:(20) ⋅ 点赞:(0)
API void rkcmd(s8* pchCmd, ...)
{
	if (NULL == pchCmd)
	{
		return;
	}

	//////////////////////////////////////////////////////////////////////////
	std::string strCmd = pchCmd;
	s8* pchParam = NULL;

	va_list pArgList;
	va_start(pArgList, pchCmd);

	for (u32 dwIdx = 0; dwIdx < 0xf; dwIdx++)
	{
		pchParam = va_arg(pArgList, s8*);
		if (NULL == pchParam)
		{
			break;
		}
		strCmd += " ";
		strCmd += pchParam;
	}
	va_end(pArgList);
	//////////////////////////////////////////////////////////////////////////
	MPrintf(">> %s", strCmd.c_str());

	// 执行命令并读取其输出
	FILE* pipe = popen(strCmd.c_str(), "r");
	if (!pipe)
	{
		MPrintf("popen() err! Failed to run command");
		return;
	}
	// 读取命令的输出
	s8 buffer[1024] = { 0 };
	while (fgets(buffer, sizeof(buffer), pipe) != NULL)
	{
		// 去除行尾换行符(兼容 \n 和 \r\n)
		size_t len = strlen(buffer);
		if (len > 0 && buffer[len - 1] == '\n') {
			buffer[len - 1] = '\0';  // 去掉 \n
			if (len > 1 && buffer[len - 2] == '\r') {
				buffer[len - 2] = '\0';  // 去掉 \r(Windows换行)
			}
		}

		MPrintf("%s", buffer);
	}

	// 关闭管道并等待命令执行完毕
	pclose(pipe);
}

这个 rkcmd 函数在执行 rkcmd("dumpmpi vdec"); 时崩溃,可能有以下几个原因和对应的解决方案:


1. 命令字符串问题

  • 可能原因

    • "dumpmpi vdec" 命令可能包含特殊字符(如空格、引号、换行符等),导致 popen() 解析失败。
    • 命令本身可能不存在,或者路径未正确设置。
  • 解决方案

    • 检查 dumpmpi 是否是可执行程序(在终端运行 which dumpmpi)。
    • 尝试用绝对路径调用,例如:
      rkcmd("/usr/bin/dumpmpi", "vdec", NULL);
      
    • 如果命令包含特殊字符,需要转义或使用引号包裹。

2. 可变参数(va_list)处理问题

  • 可能原因

    • 调用 rkcmd("dumpmpi vdec") 时,函数内部仍然会尝试读取后续的 va_arg 参数,但由于没有传递 NULL 终止,可能导致内存越界访问。
  • 解决方案

    • 确保可变参数以 NULL 结尾,例如:
      rkcmd("dumpmpi", "vdec", NULL);  // 正确方式
      
    • 或者在函数内部增加更严格的参数检查:
      for (u32 dwIdx = 0; dwIdx < 0xf; dwIdx++) {
          pchParam = va_arg(pArgList, s8*);
          if (NULL == pchParam || pchParam[0] == '\0') {  // 检查空指针或空字符串
              break;
          }
          strCmd += " ";
          strCmd += pchParam;
      }
      

3. popen() 执行失败

  • 可能原因

    • popen() 可能因为权限不足、命令不存在或系统资源限制而失败。
    • 未检查 popen() 的返回值直接使用 pipe,导致崩溃。
  • 解决方案

    • 增加错误处理逻辑:
      FILE* pipe = popen(strCmd.c_str(), "r");
      if (!pipe) {
          MPrintf("Error: popen() failed! Command: %s", strCmd.c_str());
          perror("Reason");  // 打印系统错误信息
          return;
      }
      

4. 缓冲区溢出或内存泄漏

  • 可能原因

    • fgets(buffer, sizeof(buffer), pipe) 如果读取超长行,可能导致截断或异常。
    • pclose(pipe) 未检查返回值,可能隐藏了子进程的错误。
  • 解决方案

    • 增加缓冲区检查和进程状态检查:
      int status = pclose(pipe);
      if (status != 0) {
          MPrintf("Command failed with exit status %d", status);
      }
      

5. 平台或环境问题

  • 可能原因

    • 代码被编译为其他平台(非 _RK3588__RK3568_),导致函数实际未执行。
    • 动态库或依赖缺失(如 dumpmpi 是某个 SDK 提供的工具,但未正确安装)。
  • 解决方案

    • 确认宏 _RK3588__RK3568_ 已正确定义。
    • 检查 dumpmpi 是否存在于设备中(通过 adb shell which dumpmpi 或直接在设备终端测试)。

调试建议

  1. 简化测试
    先尝试执行一个简单命令,确认函数基础功能是否正常:

    rkcmd("ls", "/", NULL);  // 列出根目录
    
  2. 打印完整命令
    在调用 popen() 前打印 strCmd,确认命令拼接正确:

    MPrintf("Executing: %s", strCmd.c_str());
    
  3. 检查权限
    如果 dumpmpi 需要 root 权限,尝试以超级用户身份运行程序。

  4. 查看系统日志
    通过 dmesglogcat 查看内核或系统日志,可能会有更详细的错误信息。


如果仍有崩溃,请提供以下信息以便进一步分析:

  1. 崩溃时的 调用栈(backtrace)
  2. dumpmpi 是否能在终端直接运行?
  3. 设备的具体系统和版本(如 Android 版本、Linux 发行版等)。

网站公告

今日签到

点亮在社区的每一天
去签到