有时,当我尝试使用pthread_key_create
创建密钥时,出现了EAGAIN错误代码。有可能确切地知道为什么吗?
文档说:
系统缺少创建另一个特定于线程的数据密钥的必要资源,否则将超出系统对每个进程的密钥总数[PTHREAD_KEYS_MAX]施加的限制。
如何检查是否是密钥限制?也许是监控工具之王,可以检查系统中已经打开了多少键以及仍然可以使用多少键?
关于我们的代码的一件重要事情:我们使用fork()
并运行多个进程。每个进程可以有多个线程。
我发现使用fork()
时对线程键没有独立的限制。这是个小例子。
#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个键用于父级和子级进程,则可以正常运行它。
答案 0 :(得分:1)
如您所知,fork()传统上是通过复制内存中的进程,然后从每个副本中与父级和子级相同的位置继续执行来工作的。这就是fork()的返回代码所指示的。
为了执行fork(),必须复制进程的内部。内存,堆栈,打开的文件,可能还有线程本地存储密钥。每个系统的fork()实现不同。某些系统允许您自定义要复制的过程区域(请参阅Linux clone(2)接口)。但是,概念保持不变。
因此,在您的示例代码上:如果您在父级中分配了1024个键,则每个子进程都将继承一个完整的键表,并且没有备用键可以使用,从而导致错误。如果您在父级中仅分配了512个密钥,那么每个子级都将继承一个半空密钥表,并具有512个备用密钥可以使用,因此不会出现错误。
答案 1 :(得分:0)
最大值:
#include <unistd.h>
#include <stdio.h>
int main ()
{
printf ("%ld\n", sysconf(_SC_THREAD_KEYS_MAX));
return 0;
}
考虑使用pthread_key_delete
。