OS X memset 和系统跟踪
Posted
技术标签:
【中文标题】OS X memset 和系统跟踪【英文标题】:OS X memset and system trace 【发布时间】:2015-04-27 19:23:07 【问题描述】:这是一个简化的程序:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
void *worker(void *data)
size_t size = 1000000;
void *area = malloc(size);
if (area != NULL)
memset(area, 0, size);
sleep(1);
free(area);
return NULL;
int main()
int number_of_threads = 4;
pthread_t threads[number_of_threads];
for (int i = 0; i < number_of_threads; i++)
if (pthread_create(&(threads[i]), NULL, worker, NULL))
return 0;
for (int i = 0; i < number_of_threads; i++)
pthread_join(threads[i], NULL);
return 0;
我使用命令iprofiler -systemtrace OSXMalloc
得到以下系统跟踪:
为什么memset
会产生所有这些零填充事件?它们是什么意思,为什么这么多?我知道我尝试用零填充 1 MB,但为什么它不在每个线程的一次调用中执行此操作?
【问题讨论】:
【参考方案1】:您在这里看到的不是memset
,而是将页面映射到内存以供以后使用的行为。操作系统用零填充页面,以防止数据从一个应用程序泄漏到另一个应用程序。
您看到的每个零填充事件都会为每个内存页面生成一次。单个内存页面只有 4K 长(4096 字节),因此 100 万字节的连续块跨越 245 个,可能是 246 个单个页面。
可能并非所有内存页面都需要此零填充事件。其中一些可能在空闲 CPU 时间被清零(并且操作系统保留“准备就绪”内存页面的列表),而其他页面可能已分配但从未被使用。但是,在这种情况下,memset
本身会尝试访问每个字节,因此操作系统别无选择,只能在 memset 到达之前清除页面。
【讨论】:
你的回答也很有帮助,因为它有一些细节,你也帮助编辑了问题。谢谢你,很抱歉造成误解。【参考方案2】:出于安全和隐私的目的,内核需要保证新分配给进程的页面用零填充。否则,您可能会从其他一些流程中获取数据,例如密码或财务信息。
页面在首次访问时归零,有点类似于写时复制。由于memset()
将遍历将它们归零的页面,因此内核将一次将页面归零。 memset()
然后做了一堆多余的工作,在已经归零的页面上写零。
使用calloc()
而不是malloc()
后跟memset(..., 0, ...)
会更好。由于 malloc 库知道内核将零填充新分配的页面,因此它知道不需要执行显式的memset()
来满足calloc()
的零填充合同。第一次访问时仍然会出现零填充错误,但它们会在内存第一次真正被使用时发生。对于不需要的memset()
,它们不会“急切地”完成。
顺便说一句,并非所有通过malloc()
完成的分配都从内核获取新页面。有些会重用之前在您的进程中分配和释放的页面。但是,对于像您这样的大型分配,页面通常在 malloc()
期间分配并在 free()
期间释放。
【讨论】:
我想知道零填充的保证是否会导致读者假设“哦,那我真的不必再清除内存了,永远!”所以,提到进程内内存重新分配的好处! (为此,亲爱的读者,它不会填零。)我来这里是为了投票和咀嚼泡泡糖,但今天我已经没有投票了。很快就会回电。 (等等!我还有一个!)【参考方案3】:将有 4 个线程,每个线程都将调用 malloc 和 memset,因此这 4 个实例已全部占用。
但是,代码中有一个错误。
将pthread_t
数组预设为全零。
如果对pthread_create
的任何调用失败,请将关联的pthread_t
条目重新设置为0
如果调用 pthread_create 失败,请不要退出程序
在调用pthread_join
的循环中,
如果关联的pthread_t
条目是0
那么,不要为该条目调用pthread_join
。
否则,当可能存在活动的 pthread 时,程序将退出。
【讨论】:
首先,这是一个演示程序,仅用于演示系统跟踪输出,您对代码的建议超出了范围。第二件事是我的问题是关于零填充事件的数量。我知道我的代码分配内存并用零填充,谢谢。以上是关于OS X memset 和系统跟踪的主要内容,如果未能解决你的问题,请参考以下文章
#define _clr(x) memset(x,0xff,sizeof(int)*n) 是啥意思?
c++这个memset()函数有啥用? memset(啥意思,啥意思,啥意思);