You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Popen报错No file descriptors available问题排查(MIPS平台)

问题分析与解决:文件描述符耗尽报错

核心原因

问题本质是文件描述符泄漏,结合你提到的线程创建后存在fork操作,主要触发点有两个:

  1. popen会创建管道并打开一对文件描述符(读端、写端),若pclose未被正确执行(比如代码分支跳转、信号中断跳过关闭逻辑),会导致fd无法回收。
  2. 当线程处于popen到pclose的执行区间时发生fork,子进程会复制父进程当前所有打开的fd(包括管道fd)。如果子进程未主动关闭这些无关fd,且子进程长期运行,就会持续占用资源,最终耗尽系统可用文件描述符。

具体解决方案

1. 确保pclose始终执行

即使fgets过程中出现异常(如信号中断),也要保证管道被关闭。可以用包裹块强制执行关闭逻辑:

static char data[1024];

static void * my_thread(void * arg)
{
    while (true)
    {
        FILE * fp = NULL;
        fp = popen("ls /", "r");
        if (fp == NULL)
        {
            printf("Error: %s", strerror(errno));
            exit(1);
        }

        // 用do-while块确保无论如何都会走到pclose
        do {
            while (fgets(data, sizeof(data) - 1, fp) != NULL)
            {
                printf("%s", data);
            }
        } while(0);

        pclose(fp);
        sleep(1);
    }

    return NULL;
}

2. Fork后立即关闭无关文件描述符

子进程继承的大部分fd都是无用的,需主动关闭以释放资源。可以遍历关闭标准IO(0、1、2)之外的所有fd:

// 在fork后的子进程代码中执行
int max_fd = sysconf(_SC_OPEN_MAX);
for (int i = 3; i < max_fd; i++) {
    close(i); // 忽略关闭失败的情况,如fd已被关闭
}

如果需要精准保留特定fd,可以在父进程中记录需要保留的fd列表,子进程只保留这些fd,其余全部关闭。

3. 调整文件描述符上限(治标手段)

用ulimit -n查看当前进程的fd上限,若上限过低,可临时调整:

ulimit -n 1024

永久调整需修改/etc/security/limits.conf配置,但这只是缓解措施,核心仍需解决泄漏问题。

4. 避免IO操作期间Fork

尽量将fork操作安排在无额外fd打开的时机,或在fork前让线程暂停IO流程,确保所有临时fd已被pclose回收。

内容的提问来源于stack exchange,提问作者blinkbetter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 13:20:31