→ tjjh89017: 你沒有假設ASLR disable的情況 08/29 16:53
→ tjjh89017: 不能說「stack 起始位址都是一模一樣的」 08/29 16:53
→ tinlans: 確實現在的系統 ASLR 預設都打開了,但會把他的問題更 08/29 21:14
→ tinlans: 複雜化。不過還是感謝補充 XD 08/29 21:14
推 wtchen: 請問個問題,32bit一個process就4GB,64bit應該就unlimit 08/29 23:15
→ wtchen: 那系統要怎麼判斷有無out-of-memory? 08/29 23:16
我知道的部分是有點老了,而且是 BSD malloc 的實作,因為我是 FreeBSD 派的。
不過還是能大概回一下你的問題,因為概念基本上都通。
這 4GB 空間不是你 pointer 隨便玩都行,還是有它的規矩在。
OS 課本上寫的記憶體保護原理實際上也有作用,所以你沒跟 OS 申請依然是非法存取。
BSD libc 會知道目前 heap size,如果 process 呼叫 malloc() 時,
如果 heap 必須長大才能滿足需求,必須呼叫 sbrk() 這個 system call。
這個 system call 如果 return -1 表示失敗,因此 OS 可以在這裡拒絕配置記憶體。
sbrk() 做的事情是移動 data segment 的 break 位址,break 的意義手冊上查得到:
The brk() and sbrk() functions are used to change the amount of memory
allocated in a process's data segment. They do this by moving the loca-
tion of the "break". The break is the first address after the end of the
process's uninitialized data segment (also known as the "BSS").
簡單來說,把 break 往高位址移動就是給這 process 更多 memory 的意思。
OS 沒有 heap 的概念,它把 data + heap 當成一個 data segment 整體。
如果你隨便把 sbrk 這關鍵字丟 Google 圖片搜尋,應該會看到這種圖:
http://flylib.com/books/2/830/1/html/2/images/09fig9_3.jpg

推 suhorng: 4GB 是 memory address space, 要用記憶體要配置才有 08/29 23:40
→ suhorng: 作業系統管理記憶體的分配跟 mapping, 會知道有沒有 OOM 08/29 23:42
→ ah7675: address space跟使用多少是兩回事啊啊啊 08/29 23:43
推 lsc36: 指標有32/64bit這麼長可是還是要跟OS拿page來用啊 08/29 23:45
推 kyuudonut: 謝謝前輩回答,所以kernel在切換process的時候,會再 08/30 00:21
→ kyuudonut: 依另外依各自的page table做映射的意思嗎? 08/30 00:22
以前常見的一種實作就是把 page table 起始位址存在 PTBR 這個暫存器,
所以會隨著 context switch 一起被儲存和恢復,因此自然會選到正確的那張。
這個技巧應該已經老到寫進課本蠻久了,你應該會有印象才對。
※ 編輯: tinlans (220.132.55.117), 08/30/2016 01:37:45
推 wtchen: 那請問一個process裡的不同thread的stack要怎麼劃? 08/30 01:09
→ wtchen: 據我所知Linux預設的stack size limit是8MiB 08/30 01:11
→ wtchen: 遠小於user space的3GB... 08/30 01:11
推 wtchen: 其實我很不懂heap是往下延伸stack往上直到兩者相撞的話 08/30 01:16
→ wtchen: 為啥heap還是可以無限增加(看OS支援大小)而stack不行 08/30 01:17
如果你有把原 po 說的那本書看完,你應該會知道 stack 和 heap 中間還有夾其它東西。
簡單 Google 一下的話可以發現像這樣的圖:
http://static.duartes.org/img/blogPosts/linuxFlexibleAddressSpaceLayout.png

→ PkmX: linux的話thread的stack是userspace自己allocate然後pass給 08/30 02:03
→ PkmX: clone(2) 08/30 02:03
→ PkmX: 8MB是預設的softlimit 你爽的話也可以ulimit -s去加大它 08/30 02:06
※ 編輯: tinlans (220.132.55.117), 08/30/2016 02:12:46
→ PkmX: 其實我很討厭往上/下長的說法 說往0或無限大長不是很好嗎XD 08/30 02:09
→ kdjf: stack也可以無限加,只是OS申請 08/30 02:10
runtime 增加的方法我就真的沒聽過了,時代真進步。是哪個 system call?
→ kdjf: 要先跟OS申請 08/30 02:11
→ kdjf: heap要用brk跟系統要空間一樣 08/30 02:12
推 wtchen: 感謝說明,受教了 08/30 02:13
→ kdjf: 只是習慣上把已知一定連續又可預測生命的資料放在自然連續的 08/30 02:13
→ kdjf: stack裡方便又快 08/30 02:14
※ 編輯: tinlans (220.132.55.117), 08/30/2016 02:15:54
推 kdjf: 剛剛google到setrlimit,可能是他吧 08/30 02:17
→ kdjf: 不過stack叫做stack&他的用法可能是古老的hardware stack 08/30 02:19
→ kdjf: 時留下來的? 08/30 02:19
確實是它,雖然我一直都知道這個 system call 的存在,
不過一直以為只有在 execve() 被呼叫的當下會去看而已。
剛才查了一下,至少確定它在 BSD 家族可以在 runtime 調整 stack size。
因為長期在做 compiler 這塊,記憶漸漸被竄改成在 linker 指定是最後的機會 XD
→ tjjh89017: 是說,64bit還有實體定址的問題,不是真的一定有2^64 08/30 02:24
※ 編輯: tinlans (220.132.55.117), 08/30/2016 03:06:31
→ kyuudonut: 謝謝前輩指點! 難怪每次看到memory的記憶體分配圖 08/30 15:21
→ kyuudonut: 有些都會稱為 process memory 08/30 15:21
推 CaptainH: 推 08/30 22:38
推 askacis: linux下setrlimit()也是可以用來調Stack size 08/31 18:19
→ askacis: pthread_attr_setstacksize()可以拿來調整thread 08/31 18:20