Linux线程创建是否触发页错误?与soft-dirty PTEs有何关联?
Linux Soft-Dirty 位异常:首次创建线程触发全页置脏的原因
问题回顾
- 主线程调用
malloc(100MB)并填充所有内存页,确保物理页已完成分配与映射 - 执行
echo 4 > /proc/self/clear_refs清除所有页的soft-dirty位 - 创建仅执行
sleep()的新线程,检查发现100MB内存区域的所有页soft-dirty位被置1 - 后续重复创建相同的休眠线程,soft-dirty位不再发生变化
核心原因:首次线程创建触发页表项修改,而非页错误
线程创建本身不会触发全内存页的页错误,但首次将进程从单线程转为多线程时,内核的地址空间共享处理会间接触发soft-dirty位的置位,具体逻辑如下:
单线程到多线程的页表属性变更
当进程处于单线程状态时,内核会将其私有内存页的页表项标记为“独占”模式。首次创建线程时,为了支持多线程共享地址空间,内核需要遍历进程的所有私有页页表项,将其修改为“共享”属性(设置PG_share标志)。soft-dirty位的触发条件
根据Linux内核设计,soft-dirty位的置位不仅包括页面被写入的情况,还包括页表项属性被修改的场景——比如改变页的共享状态、调整访问权限等操作。因此,首次线程创建时的页表项批量修改,会导致所有涉及的内存页soft-dirty位被置1。后续线程创建无变更的原因
当进程已经是多线程状态后,所有私有页的页表项已经处于共享模式,后续创建线程时,内核无需再修改页表属性,自然不会触发soft-dirty位的更新。
关键澄清
- 该现象不是页错误:页错误是进程访问未映射/无权限页面时触发的异常,这里没有发生内存访问,仅内核修改了页表项。
- 线程创建并非“仅标记共享状态”:首次创建时内核需要主动修改页表属性,这才是soft-dirty位被置位的直接原因。
内容的提问来源于stack exchange,提问作者TOM ZHANG
相关产品推荐
相关产品推荐

