pthread_create 使用 85MB VIRT 而不是 8MB VIRT
Posted
技术标签:
【中文标题】pthread_create 使用 85MB VIRT 而不是 8MB VIRT【英文标题】:pthread_create using 85MB VIRT instead of 8MB VIRT 【发布时间】:2021-11-13 10:51:29 【问题描述】:好的,我理解 VIRT != 物理 RAM,通常建议不要担心它等。
但我很困惑为什么我的每个 pthread_create 都会导致 VIRT 增加 85MB,而不是根据我的 ulimit 堆栈设置 8192 kbytes 通常增加 8MB。
我怀疑它与堆有关,但我是 C 新手,不确定这方面。
我的代码片段是:
if (tcount == gset_vars->global_threads_max)
for (j = 0; j< tcount; j++)
pthread_join(tid[j], NULL); // close threads
tcount=0;
pthread_create(&tid[tcount],NULL,HTTP_Multi_Thread,(void *)&args[i]);
tcount++;
代码注释:
它在一个for循环中,有15次迭代,得到的VIRT是1275MB(即15*85)
内部 for 循环仅在 gset_vars->global_threads_max 变量设置为小于 15 时运行(这不会影响生成的 VIRT 大小)。
函数调用 (HTTP_Multi_Thread) 只是运行一些基本的 libcurl 来下载单个文件并将其写入磁盘。 args 只是 url 和本地文件名。
注意:为了保持代码 sn-p 简短,它没有显示在主循环之后我确实在所有线程上运行 pthread_join (tcount)。
编辑:正如@johnbollinger 所建议的,这里是一个基本的、可重现的示例:
#include <stdio.h>
#include <pthread.h>
#include <curl/curl.h>
#include <string.h>
#include <unistd.h>
#define NUMT 8
char *urls[NUMT] =
"http://example.com",
"http://example.com",
"http://example.com",
"http://example.com",
"http://example.com",
"http://example.com",
"http://example.com",
"http://example.com";
char *filenames[NUMT] =
"ex1.txt",
"ex2.txt",
"ex3.txt",
"ex4.txt",
"ex5.txt",
"ex6.txt",
"ex7.txt",
"ex8.txt";
struct arg_struct
char url[128];
char filename[128];
;
size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream)
size_t written = fwrite(ptr, size, nmemb, stream);
return written;
static void *pull_one_url(void *arguments)
struct arg_struct *myargs = arguments;
char url[128];
char filename[128];
strcpy(url, myargs->url);
strcpy(filename, myargs->filename);
FILE *fp;
fp = fopen(filename, "wb");
CURL *curl;
curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, url);
//curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
curl_easy_perform(curl);
curl_easy_cleanup(curl);
fclose(fp);
return NULL;
int main(int argc, char **argv)
pthread_t tid[NUMT];
int i;
struct arg_struct args[NUMT];
curl_global_init(CURL_GLOBAL_ALL);
for (i = 0; i < NUMT; i++)
strcpy(args[i].filename, filenames[i]);
strcpy(args[i].url, urls[i]);
pthread_create(&tid[i],
NULL,
pull_one_url,
(void *)&args[i]);
for (i = 0; i < NUMT; i++)
pthread_join(tid[i], NULL);
fprintf(stderr, "Thread %d terminated\n", i);
curl_global_cleanup();
sleep(60);
sleep(60) 的唯一目的是在运行时允许一些分析时间。可能需要为 Windows 用户启用 WRITEFUNCTION 选项。
【问题讨论】:
如果您希望我们考虑您的代码细节与问题相关的可能性,那么我们肯定需要一个 minimal reproducible example 来重现行为。 感谢@JohnBollinger 我在我的主帖中添加了一个基本示例。有趣的是,这个例子为每个线程分配了大约 135MB 的 VIRT,至少根据我的 64 位 raspbian 操作系统上的 htop。 我没有要求一个基本的例子,我要求的是一个最小的。那是你提供的吗?例如,您能否在不消除大量虚拟内存占用的情况下删除对 libcurl 函数的任何调用?如果有的话,哪些对于观察您所询问的行为至关重要? 如果将curl_easy_init()
和curl_easy_cleanup()
调用移至主线程,并在其间向每个线程传递一个(不同的)句柄会怎样?
@Grish 由于虚拟内存不是稀缺资源,因此分配大量虚拟内存绝对没有什么可笑的。有些应用程序分配 2GB 或更多的虚拟内存只是为了使文件访问更简单一些。在 64 位操作系统上,没有理由尝试将其最小化,因为它实际上是免费的。
【参考方案1】:
您的ulimit
堆栈设置仅影响进程的起始堆栈。它对新创建线程的堆栈大小没有任何影响。为此,您需要使用pthread_attr_setstacksize
。
【讨论】:
我试过这个,出于某种原因,无论我将堆栈大小设置为多小或大,它对 htop 中报告的 VIRT 分配大小的影响为零。 @Grish 发布您的代码。以上是关于pthread_create 使用 85MB VIRT 而不是 8MB VIRT的主要内容,如果未能解决你的问题,请参考以下文章
使用 pthread_create 时出现 valgrind 内存泄漏错误
C++:使用 pthread_create 创建新线程,以运行类成员函数