偷拍美女厕所撒尿视频0x1002

  • 首页
  • 免费观 看成人网站
  • 将粗大挺进邻居人妻
  • 亚洲国产成人AV线
  • 伊人狼人大蕉香AV
  • 行房时间短怎么治
  • 偷拍美女厕所撒尿视频0x1002
    发布日期:2022-09-23 06:55    点击次数:101
    英语A级过了能干嘛偷拍美女厕所撒尿视频

     

    本文转载自微信公众号「脑子进煎鱼了」,作家陈煎鱼。转载本文请连系脑子进煎鱼了公众号。 

    前段工夫,某同学说某就业的容器因为超出内存截至,不休地重启,问咱们是不是有内存露馅,马上排查,然后责罚掉,省的出问题。

    咱们大为畏俱,马上稽察监控+报警系统和性能分析,发现应用主义根底就不高,不像有露馅的时势。

    问题到底是出在那儿了呢,咱们插足某个容器里稽察了 top 的系统主义:

    PID       VSZ    RSS   ... COMMAND 67459     2007m  136m  ... ./eddycjy-server 

    看上去也没什么大支出的东西,就一个 Go 程度?就这?

    再定眼一看,某同学就说 VSZ 那么高,而某云上的容器内存主义尽然适值和 VSZ 的值相接近,因此就怀疑是不是 VSZ 所导致的,认为存在一定的关联干系。

    这个测度的成果到底是否正确呢?

    基础常识

    本篇著作将主要围绕 Go 程度的 VSZ 来进行剖释,望望到底它为什么那么 "高"。

    第一节为前置的补充常识,大家可按端正阅读。

    什么是 VSZ

    VSZ 是该程度所能使用的臆造内存总大小,它包括程度不错拜访的总共内存,其中包括了被换出的内存(Swap)、已分派但未使用的内存以及来自分享库的内存。

    为什么要臆造内存

    在前边咱们有了解到 VSZ 其实即是该程度的臆造内存总大小,那如果咱们想了解 VSZ 的话,那咱们得先了解 “为什么要臆造内存?”。

    本体上来讲,在一个系统中的程度是与其他程度分享 CPU 和主存资源的。

    因此在当代的操作系统中,多程度的使用相配的常见,如果太多的程度需要太多的内存,在莫得臆造内存的情况下,物理内存很可能会不够用,就会导致其中有些任务无法运行,更以至会出现一些很奇怪的阵势。

    举例 “某一个程度不小心写了另一个程度使用的内存”,就会酿成内存挫折,因此臆造内存是相配遑急的一个绪言。

    臆造内存包含了什么

    臆造内存,又分为:

    内核臆造内存。 程度臆造内存。

    每一个程度的臆造内存都是孤苦的, 里面结构如下图所示。

    在内核臆造内存中,包含了内核中的代码和数据结构。

    内核臆造内存中的某些区域会被映射到总共程度分享的物理页面中去,因此你会看到 ”内核臆造内存“ 中履行上是包含了 ”物理内存“ 的,它们两者存在映射干系。

    而从应用场景上来讲,每个程度也会去分享内核的代码和全局数据结构,因此就会被映射到总共程度的物理页面中去。

    臆造内存的遑急才气

    为了更有用地料理内存况且减少出错,当代系统提供了一种对主存的空洞见解,也即是今天的主角,叫做臆造内存(VM)。

    臆造内存是硬件荒谬、硬件地址翻译、主存、磁盘文献和内核软件交互的场合,它为每个程度提供了一个大的、一致的和特有的地址空间,臆造内存提供了三个遑急的才气:

    它将主存动作是一个存储在磁盘上的地址空间的高速缓存,在主存中只保存步履区域,并凭据需要在磁盘和主存之间往复传送数据,通过这种方式,它高效地使用了主存。

    它为每个程度提供了一致的地址空间,从而简化了内存料理。

    它保护了每个程度的地址空间不被其他程度挫折。

    小结

    上头发散的可能比拟多,苟简来讲,关于本文咱们重心关怀这些常识点,如下:

    臆造内存它是有多样种种内存交互的场合,它包含的不单是是 "我方",而在本文中,咱们只需要关怀 VSZ,也即是程度臆造内存,它包含了你的代码、数据、堆、栈段和分享库。 臆造内存作为内存保护的器具,粗略保证程度之间的内存空间孤苦,不受其他程度的影响,因此每一个程度的 VSZ 大小都不相同,互不影响。 臆造内存的存在,系统给各程度分派的内存之和是不错大于履行可用的物理内存的,因此你也会发现你程度的物理内存老是比臆造内存低的多的多。

    排查问题

    在了解了基础常识后,咱们贯注出手排查问题,第一步咱们先编写一个测试轨范,望望莫得什么业务逻辑的 Go 轨范,它运转的 VSZ 是如何样的。

    测试

    应用代码:

    func main() {  r := gin.Default()  r.GET("/ping", func(c *gin.Context) {   c.JSON(200, gin.H{    "message": "pong",   })  })  r.Run(":8001") } 

    稽察程度情况:

    $ ps aux 67459 USER      PID  %CPU %MEM      VSZ    RSS   ... eddycjy 67459   0.0  0.0  4297048    960   ... 

    从成果上来看,VSZ 为 4297048K,也即是 4G 傍边,咋一眼看当年照旧挺吓人的,明明莫得什么业务逻辑,然而为什么那么高呢,果真令人感到好奇。

    阐明有莫得露馅

    在未知的情况下,咱们不错最初看下 runtime.MemStats 和 pprof,细目应用到底有莫得露馅。不外咱们这块是演示轨范,什么业务逻辑都莫得,因此不错细目和应用莫得平直干系。

    # runtime.MemStats # Alloc = 1298568 # TotalAlloc = 1298568 # Sys = 71893240 # Lookups = 0 # Mallocs = 10013 # Frees = 834 # HeapAlloc = 1298568 # HeapSys = 66551808 # HeapIdle = 64012288 # HeapInuse = 2539520 # HeapReleased = 64012288 # HeapObjects = 9179 ... 

    Go FAQ

    接着我第一反映是去翻了 Go FAQ(因为看到过,有印象),其问题为 "Why does my Go process use so much virtual memory?",回话如下:

    The Go memory allocator reserves a large region of virtual memory as an arena for allocations. This virtual memory is local to the specific Go process; the reservation does not deprive other processes of memory.

    To find the amount of actual memory allocated to a Go process, use the Unix top command and consult the RES (Linux) or RSIZE (macOS) columns.

    这个 FAQ 是在 2012 年 10 月 提交 的,这样多年了也莫得更进一步的证明,再翻了 issues 和 forum,一些关闭掉的 issue 都指向了 FAQ,这昭彰无法繁华我的肄业欲,因此我连续往下探索,望望里面到底都摆了些什么。

    稽察内存映射

    在上图中,咱们有提到程度臆造内存,主要包含了你的代码、数据、堆、栈段和分享库,那初步怀疑是不是程度做了什么内存映射,导致了多数的内存空间被保留呢,为了细目这少许,咱们通过如下大叫去排查:

    $ vmmap --wide 67459 ... ==== Non-writable regions for process 67459 REGION TYPE                      START - END             [ VSIZE  RSDNT  DIRTY   SWAP] PRT/MAX SHRMOD PURGE    REGION DETAIL __TEXT                 00000001065ff000-000000010667b000 [  496K   492K     0K     0K] r-x/rwx SM=COW          /bin/zsh __LINKEDIT             0000000106687000-0000000106699000 [   72K    44K     0K     0K] r--/rwx SM=COW          /bin/zsh MALLOC metadata        000000010669b000-000000010669c000 [    4K     4K     4K     0K] r--/rwx SM=COW          DefaultMallocZone_0x10669b000 zone structure ... __TEXT                 00007fff76c31000-00007fff76c5f000 [  184K   168K     0K     0K] r-x/r-x SM=COW          /usr/lib/system/libxpc.dylib __LINKEDIT             00007fffe7232000-00007ffff32cb000 [192.6M  17.4M     0K     0K] r--/r-- SM=COW          dyld shared cache combined __LINKEDIT ...          ==== Writable regions for process 67459 REGION TYPE                      START - END             [ VSIZE  RSDNT  DIRTY   SWAP] PRT/MAX SHRMOD PURGE    REGION DETAIL __DATA                 000000010667b000-0000000106682000 [   28K    28K    28K     0K] rw-/rwx SM=COW          /bin/zsh ...    __DATA                 0000000106716000-000000010671e000 [   32K    28K    28K     4K] rw-/rwx SM=COW          /usr/lib/zsh/5.3/zsh/zle.so __DATA                 000000010671e000-000000010671f000 [    4K     4K     4K     0K] rw-/rwx SM=COW          /usr/lib/zsh/5.3/zsh/zle.so __DATA                 0000000106745000-0000000106747000 [    8K     8K     8K     0K] rw-/rwx SM=COW          /usr/lib/zsh/5.3/zsh/complete.so __DATA                 000000010675a000-000000010675b000 [    4K     4K     4K     0K] rw- ... 

    这块主要是诈欺 macOS 的 vmmap 大叫去稽察内存映射情况,这样就不错澄清这个程度的内存映射情况,从输出分析来看,这些关联分享库占用的空间并不大,导致 VSZ 过高的根本原因不在分享库和二进制文献上,然而并莫得发现多数保留内存空间的步履,这是一个问题点。

    注:如若 Linux 系统,可使用 cat /proc/PID/maps 或 cat /proc/PID/smaps 稽察。

    稽察系统调用

    既然在内存映掷中,咱们莫得明确的看到保留内存空间的步履,那咱们接下来望望该程度的系统调用,细目一下它是否存在内存操作的步履,如下:

    $ sudo dtruss -a ./awesomeProject ...  4374/0x206a2:     15620       6      3 mprotect(0x1BC4000,
    熟妇 0x1000, 0x0)   = 0 0 ...  4374/0x206a2:     15781       9      4 sysctl([CTL_HW, 3, 0, 0, 0, 0] (2), 0x7FFEEFBFFA64, 0x7FFEEFBFFA68, 0x0, 0x0)   = 0 0  4374/0x206a2:     15783       3      1 sysctl([CTL_HW, 7, 0, 0, 0, 0] (2), 0x7FFEEFBFFA64, 0x7FFEEFBFFA68, 0x0, 0x0)   = 0 0  4374/0x206a2:     15899       7      2 mmap(0x0, 0x40000, 0x3, 0x1002, 0xFFFFFFFFFFFFFFFF, 0x0)   = 0x4000000 0  4374/0x206a2:     15930       3      1 mmap(0xC000000000, 0x4000000, 0x0, 0x1002, 0xFFFFFFFFFFFFFFFF, 0x0)   = 0xC000000000 0  4374/0x206a2:     15934       4      2 mmap(0xC000000000, 0x4000000, 0x3, 0x1012, 0xFFFFFFFFFFFFFFFF, 0x0)   = 0xC000000000 0  4374/0x206a2:     15936       2      0 mmap(0x0, 0x2000000, 0x3, 0x1002, 0xFFFFFFFFFFFFFFFF, 0x0)   = 0x59B7000 0  4374/0x206a2:     15942       2      0 mmap(0x0, 0x210800, 0x3, 0x1002, 0xFFFFFFFFFFFFFFFF, 0x0)   = 0x4040000 0  4374/0x206a2:     15947       2      0 mmap(0x0, 0x10000, 0x3, 0x1002, 0xFFFFFFFFFFFFFFFF, 0x0)   = 0x1BD0000 0  4374/0x206a2:     15993       3      0 madvise(0xC000000000, 0x2000, 0x8)   = 0 0  4374/0x206a2:     16004       2      0 mmap(0x0, 0x10000,任你爽 精品视频 0x3, 0x1002, 0xFFFFFFFFFFFFFFFF, 0x0)   = 0x1BE0000 0 ... 

    在这末节中,咱们通过 macOS 的 dtruss 大叫监听并稽察了运行这个轨范所进行的总共系统调用,发现了与内存料理有一定干系的方法如下:

    mmap:创建一个新的臆造内存区域,但这里需要防备,即是当系统调用 mmap 时,它只是从臆造内存中肯求了一段空间出来,并不会去分派和映射委果的物理内存,而当你拜访这段空间的时候,才会在刻下工夫委果的去分派物理内存。那么对应到咱们履行应用的程度中,那即是 VSZ 的增长后,而该内存空间又未贯注使用的话,物理内存是不会有增长的。 madvise:提供关联使用内存的提议,举例:MADV_NORMAL、MADV_RANDOM、MADV_SEQUENTIAL、MADV_WILLNEED、MADV_DONTNEED 等等。 mprotect:成立内存区域的保护情况,举例:PROT_NONE、PROT_READ、PROT_WRITE、PROT_EXEC、PROT_SEM、PROT_SAO、PROT_GROWSUP、PROT_GROWSDOWN 等等。 sysctl:在内核运行时动态地修改内核的运行参数。

    在此比拟可疑的是 mmap 方法,它在 dtruss 的最终统计中一共调用了 10 余次,咱们不错信赖它在 Go Runtime 的时候进行了多数的臆造内存肯求。

    咱们再接着往下看,望望到底是在什么阶段进行了臆造内存空间的肯求。

    注:如若 Linux 系统,可使用 strace 大叫。

    稽察 Go Runtime

    启动历程

    通过上述的分析,咱们不错澄清在 Go 轨范启动的时候 VSZ 就照旧不低了,况且细目不是分享库等的原因,且轨范在启动时系统调用如实存在 mmap 等方法的调用。

    那么咱们不错充分怀疑 Go 在运迂回阶段就保留了该内存空间。那咱们第一步要做的即是稽察一下 Go 的交流启动历程,望望是在那儿肯求的。

    交流过程如下:

    graph TD A(rt0_darwin_amd64.s:8<br/>_rt0_amd64_darwin) -->|JMP| B(asm_amd64.s:15<br/>_rt0_amd64) B --> |JMP|C(asm_amd64.s:87<br/>runtime-rt0_go) C --> D(runtime1.go:60<br/>runtime-args) D --> E(os_darwin.go:50<br/>runtime-osinit) E --> F(proc.go:472<br/>runtime-schedinit) F --> G(proc.go:3236<br/>runtime-newproc) G --> H(proc.go:1170<br/>runtime-mstart) H --> I(在新创建的 p 和 m 上运行 runtime-main) 
    runtime-osinit:赢得 CPU 中枢数。 runtime-schedinit:运迂回轨范运行环境(包括栈、内存分派器、垃圾回收、P等)。 runtime-newproc:创建一个新的 G 和 绑定 runtime.main。 runtime-mstart:启动线程 M。

    注:来自@曹大的 《Go 轨范的启动历程》和@全成的 《Go 轨范是若何跑起来的》,推选大家阅读。

    运迂回运行环境

    昭彰,咱们要商讨的是 runtime 里的 schedinit 方法,如下:

    func schedinit() {  ...  stackinit()  mallocinit()  mcommoninit(_g_.m)  cpuinit()       // must run before alginit  alginit()       // maps must not be used before this call  modulesinit()   // provides activeModules  typelinksinit() // uses maps, activeModules  itabsinit()     // uses activeModules   msigsave(_g_.m)  initSigmask = _g_.m.sigmask   goargs()  goenvs()  parsedebugvars()  gcinit()   ... } 

    从用途来看,相配昭彰, mallocinit 方法会进行内存分派器的运迂回,咱们连续往下看。

    运迂回内存分派器

    mallocinit

    接下来咱们贯注的分析一下 mallocinit 方法,在交流历程中, mallocinit 主要承担 Go 轨范的内存分派器的运迂回动作,而今上帝要是针对臆造内存地址这块进行拆解,如下:

    func mallocinit() {  ...  if sys.PtrSize == 8 {   for i := 0x7f; i >= 0; i-- {    var p uintptr    switch {    case GOARCH == "arm64" && GOOS == "darwin":     p = uintptr(i)<<40 | uintptrMask&(0x0013<<28)    case GOARCH == "arm64":     p = uintptr(i)<<40 | uintptrMask&(0x0040<<32)    case GOOS == "aix":     if i == 0 {      continue     }     p = uintptr(i)<<40 | uintptrMask&(0xa0<<52)    case raceenabled:     ...    default:     p = uintptr(i)<<40 | uintptrMask&(0x00c0<<32)    }    hint := (*arenaHint)(mheap_.arenaHintAlloc.alloc())    hint.addr = p    hint.next, mheap_.arenaHints = mheap_.arenaHints, hint   }  } else {       ...  } } 
    判断刻下是 64 位照旧 32 位的系统。 从 0x7fc000000000~0x1c000000000 出手成立保留地址。 判断刻下 GOARCH、GOOS 或是否开启了竞态检查,凭据不同的情况肯求不同大小的连气儿内存地址,而这里的 p 是行将要要肯求的连气儿内存地址的出手地址。 保存刚刚计较的 arena 的信息到 arenaHint 中。

    可能会有小伙伴问,为什么要判断是 32 位照旧 64 位的系统,这是因为不同位数的臆造内存的寻址限度是不同的,因此要进行分歧,不然会出现高位的臆造内存映射问题。而在肯求保留空间时,咱们会往往提到 arenaHint 结构体,它是 arenaHints链内外的一个节点,结构如下:

    type arenaHint struct {  addr uintptr  down bool  next *arenaHint } 
    addr:arena 的肇端地址 down:是否终末一个 arena next:下一个 arenaHint 的指针地址

    那么这里猖獗提到的 arena 又是什么东西呢,这其实是 Go 的内存料理中的见解,Go Runtime 会把肯求的臆造内存分为三个大块,如下:

    image

    spans:纪录 arena 区域页号和 mspan 的映射干系。 bitmap:象征 arena 的使用情况,在功能上来讲,会用于象征 arena 的哪些空间地址照旧保存了对象。 arean:arean 其实即是 Go 的堆区,是由 mheap 进行料理的,它的 MaxMem 是 512GB-1。而在功能上来讲,Go 会在运迂回的时候肯求一段连气儿的臆造内存空间地址到 arean 保留住来,在委果需要肯求堆上的空间时再从 arean 中取出来处理,这时候就会蜕变为物理内存了。

    在这里的话,你需要接续 arean 区域在 Go 内存里的作用就不错了。

    mmap

    咱们刚刚通过上述的分析,照旧澄清 mallocinit 的用途了,然而你可能照旧会有猜疑,即是咱们之前所看到的 mmap 系统调用,和它又有什么干系呢,如何就关联到一齐了,接下来咱们先一齐来望望更基层的代码,如下:

    func sysAlloc(n uintptr, sysStat *uint64) unsafe.Pointer {  p, err := mmap(nil, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_PRIVATE, -1, 0)  ...  mSysStatInc(sysStat, n)  return p }  func sysReserve(v unsafe.Pointer, n uintptr) unsafe.Pointer {  p, err := mmap(v, n, _PROT_NONE, _MAP_ANON|_MAP_PRIVATE, -1, 0)  ... }  func sysMap(v unsafe.Pointer, n uintptr, sysStat *uint64) {  ...  munmap(v, n)  p, err := mmap(v, n, _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_FIXED|_MAP_PRIVATE, -1, 0)   ... } 

    在 Go Runtime 中存在着一系列的系统级内存调用方法,本文波及的主要如下:

    sysAlloc:从 OS 系统上肯求清零后的内存空间,调用参数是 _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_PRIVATE,得到的成果需进行内存对齐。 sysReserve:从 OS 系统中保留内存的地址空间,这时候还莫得分派物理内存,调用参数是 _PROT_NONE, _MAP_ANON|_MAP_PRIVATE,得到的成果需进行内存对齐。 sysMap:示知 OS 系统咱们要使用照旧保留了的内存空间,调用参数是 _PROT_READ|_PROT_WRITE, _MAP_ANON|_MAP_FIXED|_MAP_PRIVATE。

    看上去好像很有钦慕的时势,然而 mallocinit 方法在运转眼息,到底是在那儿波及了 mmap 方法呢,名义看不出来,如下:

    for i := 0x7f; i >= 0; i-- {  ...  hint := (*arenaHint)(mheap_.arenaHintAlloc.alloc())  hint.addr = p  hint.next, mheap_.arenaHints = mheap_.arenaHints, hint } 

    履行上在调用 mheap_.arenaHintAlloc.alloc() 时,调用的是 mheap 下的 sysAlloc 方法,而 sysAlloc 又会与 mmap 方法产生调用干系,况且这个方法与旧例的 sysAlloc 还不大相同,如下:

    var mheap_ mheap ... func (h *mheap) sysAlloc(n uintptr) (v unsafe.Pointer, size uintptr) {  ...  for h.arenaHints != nil {   hint := h.arenaHints   p := hint.addr   if hint.down {    p -= n   }   if p+n < p {    v = nil   } else if arenaIndex(p+n-1) >= 1<<arenaBits {    v = nil   } else {    v = sysReserve(unsafe.Pointer(p), n)   }   ... } 

    你不错惊喜的发现 mheap.sysAlloc 里其实有调用 sysReserve 方法,而 sysReserve 方法又正恰是从 OS 系统中保留内存的地址空间的特定方法,是不是很惊喜,一切似乎都串起来了。

    小结

    在本节中,咱们先写了一个测试轨范,然后凭据相配规的排查思绪进行了一步步的追踪怀疑,举座历程如下:

    通过 top 或 ps 等大叫,稽察程度运行情况,分析基础主义。 通过 pprof 或 runtime.MemStats 等器具链稽察应用运行情况,分析应用层面是否有露馅或者哪儿高。 通过 vmmap 大叫,稽察程度的内存映射情况,分析是不是程度臆造空间内的某个区域比拟高,举例:分享库等。 通过 dtruss 大叫,稽察轨范的系统调用情况,分析可能出现的一些特地步履,举例:在分析中咱们发现 mmap 方法调用的比例是比拟高的,那咱们有充分的情理怀疑 Go 在启动时就进行了多数的内存空间保留。 通过上述的分析,细目可能是在哪个方法肯求了那么多的内存空间后,再到 Go Runtime 中去做进一步的源码分析,因为源码眼前,了无玄妙,没必要靠猜。

    从论断上而言,VSZ(程度臆造内存大小)与分享库等莫得太大的干系,主要与 Go Runtime 存在平直关联,也即是在前图中默示的运行时堆(malloc)。搭救到 Go Runtime 里,即是在 mallocinit 这个内存分派器的运迂回阶段里进行了一定量的臆造空间的保留。

    而保留臆造内存空间时,受什么影响,又是一个形而上学问题。从源码上来看,主要如下:

    受不同的 OS 系统架构(GOARCH/GOOS)和位数(32/64 位)的影响。 受内存对齐的影响,计较归来的内存空间大小是需要经过对齐才会进行保留。

    总结

    咱们通过一步阵势分析,证明注解了 Go 会在那儿,又会受什么身分,去调用了什么方法保留了那么多的臆造内存空间,然而咱们深信会忧心程度臆造内存(VSZ)高,会不会存在问题呢,我分析如下:

    VSZ 并不虞味着你委果使用了那些物理内存,因此是不需要追溯的。 VSZ 并不会给 GC 带来压力,GC 料理的是程度履行使用的物理内存,而 VSZ 在你履行使用它之前,它并莫得过多的代价。 VSZ 基本都是不成拜访的内存映射,也即是它并莫得内存的拜访权限(不允许读、写和实施)。

    思考

    看到这里舒一语气,因为 Go VSZ 的高,并不会对咱们产生什么相配实质性的问题,然而又仔细一想,为什么 Go 要肯求那么多的臆造内存呢?

    总体磋议如下:

    Go 的缱绻是磋议到 arena 和 bitmap 的后续使用,先提早保留了总共这个词内存地址空间。 Go Runtime 和应用的渐渐使用,深信也会出手履行的肯求和使用内存,这时候 arena 和 bitmap 的内存分派器就只需要将预先肯求好的内存地址空间保留蜕变为履行可用的物理内存就好了,这时势不错极大的升迁着力。

    参考

    High virtual memory allocation by golang

    GO MEMORY MANAGEMENT

    GoBigVirtualSize

    GoProgramMemoryUse

    曹大的 Go 轨范的启动历程

    全成大佬的 Go 轨范是若何跑起来的

    欧神的 go-under-the-hood