linux - 为什么 EAGAIN 在 pthread_key_create 发生?

标签 linux pthreads

有时,当我尝试使用 pthread_key_create 创建 key 时,我会收到 EAGAIN 错误代码。是否有可能确切地知道为什么?

文档说:

The system lacked the necessary resources to create another thread-specific data key, or the system-imposed limit on the total number of keys per process [PTHREAD_KEYS_MAX] would be exceeded.

如何检查它是否是键的限制?也许一些监视工具之王可以检查系统中已经打开了多少键,还有多少可以使用?

关于我们的代码的一件重要事情:我们使用 fork() 并且有多个进程在运行。每个进程可以有多个线程。

我发现我们在使用fork()时,对thread key没有独立的限制。这是一个小例子。

#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>

size_t create_keys(pthread_key_t *keys, size_t number_of_keys)
{
    size_t counter = 0;
    for (size_t i = 0; i < number_of_keys; i++)
    {
        int e = pthread_key_create(keys + i, NULL);
        if (e)
        {
            printf("ERROR (%d): index: %ld, pthread_key_create (%d)\n", getpid(), i, e);
            break;
        }
        counter++;
    }

    return counter;
}

int main(int argc, char const *argv[])
{
    printf("maximim number of thread keys: %ld\n", sysconf(_SC_THREAD_KEYS_MAX));

    printf("process id: %d\n", getpid());

    const size_t number_of_keys = 1024;

    pthread_key_t keys_1[number_of_keys];
    memset(keys_1, 0, number_of_keys * sizeof(pthread_key_t));

    printf("INFO (%d): number of active keys: %ld\n", getpid(), create_keys(keys_1, number_of_keys));

    pid_t p = fork();
    if (p == 0)
    {
        printf("process id: %d\n", getpid());

        pthread_key_t keys_2[number_of_keys];
        memset(keys_2, 0, number_of_keys * sizeof(pthread_key_t));

        printf("INFO (%d): number of active keys: %ld\n", getpid(), create_keys(keys_2, number_of_keys));
    }

    return 0;
}

当我在 Ubuntu 16.04 上运行此示例时,我发现如果我使用与限制 (1024) 相同数量的键,则子进程无法创建任何新线程键。但是,如果我为父进程和子进程使用 512 键,我可以无错误地运行它。

最佳答案

如您所知,fork() 的传统工作方式是将进程复制到内存中,然后从每个副本中作为父进程和子进程的同一点继续执行。这就是 fork() 的返回码所指示的。

为了执行 fork(),必须复制进程的内部结构。内存、堆栈、打开的文件,可能还有线程本地存储键。每个系统在 fork() 的实现上都是不同的。某些系统允许您自定义要复制的进程区域(请参阅 Linux clone(2) 界面)。但是,概念保持不变。

因此,转到您的示例代码:如果您在父进程中分配 1024 个键,每个子进程都会继承一个完整的键表并且没有备用键可以使用,从而导致错误。如果在父级中只分配了 512 个键,那么每个子级继承了一个半空的键表,并且有 512 个备用键可以使用,因此不会出现错误。

关于linux - 为什么 EAGAIN 在 pthread_key_create 发生?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55904512/

相关文章:

linux - httpd-2.4.10 从 "Regex could not be compiled"开始失败

python - 处理文件名中的文字空间

c - 如何使用 pthreads 并行化 pi 的蒙特卡洛估计?

c++ - C++ 所需的具有 C 链接的回调函数

linux - 如何从用户空间访问thread_info

c - 为什么添加线程会使这个简单的套接字服务器更快?

c++ - 如何在具有 OpenMP 功能的 QThread 中强制使用多核

linux - 防止 ssh 命令中参数的扩展/评估

linux - 如何在 bash for 循环中使用变量

php - 文件夹权限 777 不工作