Linux可執(zhí)行文件如何裝載進(jìn)虛擬內(nèi)存

開篇先拋出幾個(gè)問題坞生,之后逐個(gè)擊破:

  1. 什么是進(jìn)程的虛擬地址空間?為什么進(jìn)程要有自己的虛擬地址空間喜每,這樣做有什么好處务唐?
  2. 我們都聽說過頁映射,什么是頁映射带兜,操作系統(tǒng)為什么要以頁映射方式將程序映射到進(jìn)程地址空間枫笛,這樣做有什么好處?程序運(yùn)行過程中發(fā)生頁錯(cuò)誤如何處理刚照?
  3. 什么是進(jìn)程刑巧?從操作系統(tǒng)的角度來看,進(jìn)程是如何被建立的无畔?
  4. 進(jìn)程虛擬地址空間的分布是什么樣的海诲?
  5. Linux是如何裝載并運(yùn)行ELF程序的?

虛擬地址空間

what:虛擬地址空間就是我們常說的虛擬內(nèi)存檩互,虛擬內(nèi)存是計(jì)算機(jī)系統(tǒng)內(nèi)存管理的一種技術(shù)特幔。它使得應(yīng)用程序認(rèn)為它擁有連續(xù)可用的內(nèi)存(一個(gè)連續(xù)完整的地址空間),而實(shí)際上闸昨,它通常是被分隔成多個(gè)物理內(nèi)存碎片蚯斯,還有部分暫時(shí)存儲(chǔ)在外部磁盤存儲(chǔ)器上,在需要時(shí)進(jìn)行數(shù)據(jù)交換饵较。與沒有使用虛擬內(nèi)存技術(shù)的系統(tǒng)相比拍嵌,使用這種技術(shù)的系統(tǒng)使得大型程序的編寫變得更容易,對(duì)真正的物理內(nèi)存的使用也更有效率循诉。當(dāng)處理器讀取或?qū)懭雰?nèi)存位置時(shí)横辆,都會(huì)使用虛擬地址。在讀取或?qū)懭氩僮鬟^程中茄猫,處理器會(huì)將虛擬地址轉(zhuǎn)換為物理地址狈蚤。

why:使用虛擬內(nèi)存有如下好處:

  • 程序員無需操心如何存儲(chǔ)數(shù)據(jù)或者程序等內(nèi)容

  • 程序可以使用一系列連續(xù)的虛擬地址來訪問物理內(nèi)存中不連續(xù)的大內(nèi)存區(qū)域茫孔,用戶看到的是連續(xù)地址癣籽,而無需關(guān)心更底層物理地址的排布捞挥。

  • 通過使用虛擬內(nèi)存懂诗,程序可以使用大于實(shí)際可用物理內(nèi)存的空間毅整,當(dāng)物理內(nèi)存不夠用時(shí)功咒,操作系統(tǒng)會(huì)將物理內(nèi)存頁保存在磁盤文件跋理,數(shù)據(jù)頁或者代碼頁會(huì)根據(jù)需要在物理內(nèi)存和磁盤之間移動(dòng)震放。

  • 不同進(jìn)程使用的虛擬地址彼此隔離,用戶無需擔(dān)心會(huì)影響到其它程序內(nèi)存地址中的數(shù)據(jù)幻捏,操作系統(tǒng)的內(nèi)存管理模塊會(huì)將虛擬地址映射到物理地址盆犁。

更多詳解虛擬內(nèi)存的內(nèi)容可以看我之前的文章:1, 2篡九, 3

頁映射

background:程序運(yùn)行時(shí)所需要的指令和數(shù)據(jù)必須放在內(nèi)存中才可以正常執(zhí)行蚣抗,最簡單的辦法就是將運(yùn)行所需要的指令和數(shù)據(jù)全部裝進(jìn)內(nèi)存,但是很多時(shí)候程序需要的內(nèi)存可能大于實(shí)際可用的物理內(nèi)存瓮下,為了解決這種不夠用的問題引入了動(dòng)態(tài)裝入的概念翰铡,可以將程序最常用的部分駐留在內(nèi)存中,而將一些不常用的數(shù)據(jù)存在磁盤中讽坏。

what:頁映射不是一次性將所有的程序和數(shù)據(jù)裝入內(nèi)存锭魔,而是將內(nèi)存和磁盤中的數(shù)據(jù)和指令按頁為單位分成若干份,以后所有的裝載和操作的單位就是頁路呜。頁的大小不固定迷捧,但是一般都是4096字節(jié)。

how:如下圖胀葱,舉個(gè)例子漠秋,可執(zhí)行程序所需要的指令和數(shù)據(jù)總和占8個(gè)頁,編號(hào)為VP0-VP7抵屿,而實(shí)際的物理內(nèi)存只有4個(gè)頁庆锦,編號(hào)為PP0-PP3,4個(gè)頁的物理內(nèi)存無法同時(shí)將8個(gè)頁的程序都裝載進(jìn)去轧葛,所以需要?jiǎng)討B(tài)裝入搂抒,假設(shè)程序入口地址在VP0,這時(shí)內(nèi)核發(fā)現(xiàn)VP0不在內(nèi)存中尿扯,所以將VP0分配給了PP0求晶,將VP0的內(nèi)容裝入了PP0,運(yùn)行一段后程序需要用到VP2衷笋,內(nèi)核又將VP2分配給了PP1芳杏,之后又用到VP4和VP6,內(nèi)核又分別分配給了PP2和PP3辟宗。這時(shí)候程序只需要VP0爵赵、VP2、VP4和VP6這四個(gè)頁就可以一直運(yùn)行下去慢蜓,如果程序又需要VP5亚再,那內(nèi)核就必須會(huì)放棄正在使用的四個(gè)內(nèi)存頁中的一個(gè)才可以把VP5裝載進(jìn)去繼續(xù)執(zhí)行郭膛,至于選擇哪個(gè)晨抡,操作系統(tǒng)內(nèi)核會(huì)有多種換出算法來處理這種問題。

image.png

why:其實(shí)上面已經(jīng)介紹了原因,如果一次性把所有指令和數(shù)據(jù)都加載到內(nèi)存中耘柱,物理內(nèi)存可能不夠用如捅,所以需要使用動(dòng)態(tài)裝入,所以引入了頁映射的方法调煎。

進(jìn)程如何被建立

這里首先需要弄清楚程序和進(jìn)程的區(qū)別镜遣?程序(可執(zhí)行文件)是一個(gè)靜態(tài)的概念,它就是預(yù)先編譯好的指令和數(shù)據(jù)集合的一個(gè)文件士袄,進(jìn)程則是一個(gè)動(dòng)態(tài)的概念悲关,它是程序運(yùn)行的一個(gè)過程。

從操作系統(tǒng)角度看娄柳,一個(gè)進(jìn)程最關(guān)鍵的特征是它擁有獨(dú)立的虛擬地址空間寓辱,很多時(shí)候一個(gè)程序被執(zhí)行都伴隨著一個(gè)新的進(jìn)程被創(chuàng)建,之后裝載相應(yīng)的可執(zhí)行文件并運(yùn)行赤拒。上述經(jīng)歷了什么步驟秫筏?

  1. 創(chuàng)建一個(gè)獨(dú)立的虛擬地址空間:這里的創(chuàng)建空間并不是真正的創(chuàng)建空間,而是創(chuàng)建映射函數(shù)所需要的數(shù)據(jù)結(jié)構(gòu)挎挖,方便后面映射需要这敬。
  2. 讀取可執(zhí)行文件頭,建立虛擬空間和可執(zhí)行文件的映射關(guān)系:上面的映射數(shù)據(jù)結(jié)構(gòu)是為了建立虛擬空間到物理內(nèi)存的映射關(guān)系蕉朵,這一步是虛擬空間與可執(zhí)行文件的映射關(guān)系崔涂。
  3. 將CPU的指令寄存器設(shè)置成可執(zhí)行文件入口,啟動(dòng)運(yùn)行:這里可以簡單的理解為操作系統(tǒng)執(zhí)行了一條跳轉(zhuǎn)指令始衅,跳轉(zhuǎn)到可執(zhí)行文件的入口地址堪伍。

頁錯(cuò)誤:當(dāng)程序執(zhí)行一個(gè)地址的指令時(shí),發(fā)現(xiàn)是個(gè)空頁面觅闽,所以就認(rèn)為是個(gè)頁錯(cuò)誤帝雇,這時(shí)候控制權(quán)交由操作系統(tǒng),操作系統(tǒng)有專門的錯(cuò)誤處理程序處理這種情況蛉拙,查詢第二步驟建立的映射數(shù)據(jù)結(jié)構(gòu)尸闸,找到空頁面所在的虛擬內(nèi)存區(qū)域,計(jì)算出相應(yīng)的頁面在可執(zhí)行文件中的偏移孕锄,然后在物理內(nèi)存中分配一個(gè)物理頁面吮廉,將進(jìn)程中的該虛擬頁與物理頁建立映射關(guān)系,控制權(quán)返還給進(jìn)程畸肆,進(jìn)程從頁錯(cuò)誤的位置繼續(xù)執(zhí)行宦芦。

進(jìn)程虛擬空間分布

如果您讀過我之前的文章應(yīng)該就知道,一個(gè)正常的進(jìn)程轴脐,可執(zhí)行文件中不只包含數(shù)據(jù)段和代碼段调卑,還有好多個(gè)段抡砂,這里通過readelf可以查看:

$ readelf -S test
There are 9 section headers, starting at offset 0x1208:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .text             PROGBITS         00000000004000e8  000000e8
       0000000000000056  0000000000000000  AX       0     0     1
  [ 2] .rodata           PROGBITS         000000000040013e  0000013e
       0000000000000006  0000000000000000   A       0     0     1
  [ 3] .eh_frame         PROGBITS         0000000000400148  00000148
       0000000000000078  0000000000000000   A       0     0     8
  [ 4] .data             PROGBITS         0000000000601000  00001000
       0000000000000008  0000000000000000  WA       0     0     8
  [ 5] .comment          PROGBITS         0000000000000000  00001008
       0000000000000029  0000000000000001  MS       0     0     1
  [ 6] .symtab           SYMTAB           0000000000000000  00001038
       0000000000000150  0000000000000018           7     7     8
  [ 7] .strtab           STRTAB           0000000000000000  00001188
       000000000000003a  0000000000000000           0     0     1
  [ 8] .shstrtab         STRTAB           0000000000000000  000011c2
       0000000000000042  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  l (large), p (processor specific

通過上面的結(jié)果可以看出這里的段叫Section,拿這個(gè)舉例恬涧,ELF文件映射是以系統(tǒng)頁為單位注益,每個(gè)段在映射時(shí)的長度都是系統(tǒng)頁的整數(shù)倍,假設(shè)程序有8個(gè)段溯捆,每個(gè)段都占512字節(jié)丑搔,占用了8個(gè)頁,但是一個(gè)頁卻有4K的大小提揍,空間利用率只有1/8啤月,造成極大的空間浪費(fèi)。實(shí)際上劳跃,從操作系統(tǒng)裝載可執(zhí)行文件的角度看顽冶,可以發(fā)現(xiàn)它實(shí)際上并不關(guān)心可執(zhí)行文件各個(gè)段所包含的實(shí)際內(nèi)容,它主要就是關(guān)心段的權(quán)限(可讀售碳、可寫强重、可執(zhí)行),ELF文件中段的權(quán)限主要就有幾種組合:

  1. 以代碼段為代表的權(quán)限為可讀可執(zhí)行的段

  2. 以數(shù)據(jù)段和BSS段位代表的權(quán)限為可讀可寫的段

  3. 以只讀數(shù)據(jù)段位代表的權(quán)限為只讀的段

對(duì)于相同權(quán)限的段贸人,可以把它們(section)合并到一起當(dāng)作一個(gè)段(segment)進(jìn)行映射间景。拿前面的例子,之前8個(gè)section需要8個(gè)頁艺智,而這種方式8個(gè)section可能會(huì)被合并成2個(gè)segment倘要,占用2個(gè)頁。

segment的概念實(shí)際上是從裝載的角度重新劃分了ELF的各個(gè)段十拣,在將目標(biāo)文件鏈接成可執(zhí)行文件的時(shí)候封拧,鏈接器盡量把相同權(quán)限屬性的段分配在同一空間,多個(gè)section變成一個(gè)segment夭问,而系統(tǒng)就是按這種segment來映射可執(zhí)行文件的泽西。

segment和section是從不同的角度劃分一個(gè)ELF文件,稱為不同的視圖缰趋,從section的角度來看ELF文件就是鏈接視圖捧杉,從segment的角度來看ELF文件就是執(zhí)行視圖,當(dāng)我們?cè)谡劦紼LF裝載時(shí)秘血,段專門指segment味抖,其它情況下,段指的是section灰粮。

通過readelf命令可以查看可執(zhí)行文件的segment仔涩。

$ readelf -l test

Elf file type is EXEC (Executable file)
Entry point 0x400123
There are 3 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x00000000000001c0 0x00000000000001c0  R E    0x200000
  LOAD           0x0000000000001000 0x0000000000601000 0x0000000000601000
                 0x0000000000000008 0x0000000000000008  RW     0x200000
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x10

 Section to Segment mapping:
  Segment Sections...
   00     .text .rodata .eh_frame
   01     .data
   02

這里有很少的segment,描述segment屬性的結(jié)構(gòu)叫程序頭粘舟,這里只需要知道ELF可執(zhí)行文件中有一個(gè)專門的數(shù)據(jù)結(jié)構(gòu)叫程序頭表熔脂,它用來保存segment的信息佩研,因?yàn)槟繕?biāo)文件不需要被裝載,所以沒有程序頭表锤悄,而可執(zhí)行文件和共享庫文件都有頭表韧骗,他們會(huì)被用于裝載嘉抒,這里的各個(gè)segment都是通過匿名虛擬內(nèi)存區(qū)域(VMA)來映射零聚。

可以通過cat來查看VMA:

cat /proc/72/maps
7f445f4b0000-7f445f4c7000 r-xp 00000000 00:00 516559             /lib/x86_64-linux-gnu/libgcc_s.so.1
7f445f4c7000-7f445f4c8000 ---p 00017000 00:00 516559             /lib/x86_64-linux-gnu/libgcc_s.so.1
7f445f4c8000-7f445f6c6000 ---p 00000018 00:00 516559             /lib/x86_64-linux-gnu/libgcc_s.so.1
7f445f6c6000-7f445f6c7000 r--p 00016000 00:00 516559             /lib/x86_64-linux-gnu/libgcc_s.so.1
7f445f6c7000-7f445f6c8000 rw-p 00017000 00:00 516559             /lib/x86_64-linux-gnu/libgcc_s.so.1
7f445f6d0000-7f445f86d000 r-xp 00000000 00:00 516611             /lib/x86_64-linux-gnu/libm-2.27.so
7f445f86d000-7f445f870000 ---p 0019d000 00:00 516611             /lib/x86_64-linux-gnu/libm-2.27.so
7f445f870000-7f445fa6c000 ---p 000001a0 00:00 516611             /lib/x86_64-linux-gnu/libm-2.27.so
7f445fa6c000-7f445fa6d000 r--p 0019c000 00:00 516611             /lib/x86_64-linux-gnu/libm-2.27.so
7f445fa6d000-7f445fa6e000 rw-p 0019d000 00:00 516611             /lib/x86_64-linux-gnu/libm-2.27.so
7f445fa70000-7f445fc57000 r-xp 00000000 00:00 516391             /lib/x86_64-linux-gnu/libc-2.27.so
7f445fc57000-7f445fc60000 ---p 001e7000 00:00 516391             /lib/x86_64-linux-gnu/libc-2.27.so
7f445fc60000-7f445fe57000 ---p 000001f0 00:00 516391             /lib/x86_64-linux-gnu/libc-2.27.so
7f445fe57000-7f445fe5b000 r--p 001e7000 00:00 516391             /lib/x86_64-linux-gnu/libc-2.27.so
7f445fe5b000-7f445fe5d000 rw-p 001eb000 00:00 516391             /lib/x86_64-linux-gnu/libc-2.27.so
7f445fe5d000-7f445fe61000 rw-p 00000000 00:00 0
7f445fe70000-7f445ffe9000 r-xp 00000000 00:00 540399             /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25
7f445ffe9000-7f445fff6000 ---p 00179000 00:00 540399             /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25
7f445fff6000-7f44601e9000 ---p 00000186 00:00 540399             /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25
7f44601e9000-7f44601f3000 r--p 00179000 00:00 540399             /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25
7f44601f3000-7f44601f5000 rw-p 00183000 00:00 540399             /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.25
7f44601f5000-7f44601f9000 rw-p 00000000 00:00 0
7f4460200000-7f4460226000 r-xp 00000000 00:00 516353             /lib/x86_64-linux-gnu/ld-2.27.so
7f4460226000-7f4460227000 r-xp 00026000 00:00 516353             /lib/x86_64-linux-gnu/ld-2.27.so
7f4460427000-7f4460428000 r--p 00027000 00:00 516353             /lib/x86_64-linux-gnu/ld-2.27.so
7f4460428000-7f4460429000 rw-p 00028000 00:00 516353             /lib/x86_64-linux-gnu/ld-2.27.so
7f4460429000-7f446042a000 rw-p 00000000 00:00 0
7f4460440000-7f4460442000 rw-p 00000000 00:00 0
7f4460450000-7f4460452000 rw-p 00000000 00:00 0
7f4460460000-7f4460462000 rw-p 00000000 00:00 0
7f4460600000-7f4460601000 r-xp 00000000 00:00 205513             /mnt/d/wzq/wzq/util/test/a.out
7f4460800000-7f4460801000 r--p 00000000 00:00 205513             /mnt/d/wzq/wzq/util/test/a.out
7f4460801000-7f4460802000 rw-p 00001000 00:00 205513             /mnt/d/wzq/wzq/util/test/a.out
7fffc7576000-7fffc7597000 rw-p 00000000 00:00 0                  [heap]
7fffcf186000-7fffcf986000 rw-p 00000000 00:00 0                  [stack]
7fffcfe84000-7fffcfe85000 r-xp 00000000 00:00 0                  [vdso]

上面的我們可以先忽略,看最下面些侍,主要有堆和棧隶症,這兩個(gè)VMA幾乎在所有的進(jìn)程中都存在,而[vdso]是一個(gè)內(nèi)核模塊岗宣,程序通過這個(gè)模塊和內(nèi)核進(jìn)行通信蚂会。

小總結(jié):如圖【圖片來自網(wǎng)絡(luò),侵權(quán)刪】:

image.png

操作系統(tǒng)通過給進(jìn)程空間劃分出一個(gè)個(gè)VMA來管理進(jìn)程的虛擬空間耗式,基本原則是將相同權(quán)限屬性的胁住、有相同映射文件的映射成一個(gè)VMA,一個(gè)進(jìn)程主要可以分成以下幾種VMA區(qū)域:

  1. 代碼VMA:權(quán)限只讀可執(zhí)行刊咳,有映射文件

  2. 數(shù)據(jù)VMA:權(quán)限可讀寫可執(zhí)行彪见,有映射文件

  3. 堆VMA:權(quán)限可讀寫可執(zhí)行,無映射文件娱挨,匿名余指,向上擴(kuò)展

  4. 棧VMA:權(quán)限可讀寫不可執(zhí)行,無映射文件跷坝,匿名酵镜,向下擴(kuò)展

Linux如何裝載并運(yùn)行ELF程序

Linux內(nèi)核裝載ELF文件主要有兩步:

  1. 通過fork系統(tǒng)調(diào)用創(chuàng)建一個(gè)新的進(jìn)程
  2. 通過execve系統(tǒng)調(diào)用執(zhí)行指定的ELF文件,附帶環(huán)境變量和參數(shù)
    1. 檢查ELF可執(zhí)行文件的有效性柴钻,比如魔數(shù)(通過魔數(shù)可以確定文件格式)淮韭、Segment的數(shù)量等
    2. 尋找動(dòng)態(tài)鏈接的段,設(shè)置動(dòng)態(tài)鏈接器路徑
    3. 根據(jù)ELF可執(zhí)行文件的程序頭表描述贴届,對(duì)ELF文件進(jìn)行映射缸濒,比如代碼、數(shù)據(jù)粱腻、只讀數(shù)據(jù)
    4. 初始化ELF進(jìn)程環(huán)境
    5. 將系統(tǒng)調(diào)用的返回地址修改為ELF可執(zhí)行文件的入口地址庇配。

參考資料

《程序員的自我修養(yǎng):鏈接裝載與庫》

https://docs.microsoft.com/zh-cn/windows-hardware/drivers/gettingstarted/virtual-address-spaces

https://blog.csdn.net/chenlycly/article/details/53367336

https://www.zhihu.com/question/290504400

https://zh.wikipedia.org/wiki/%E8%99%9A%E6%8B%9F%E5%86%85%E5%AD%98

https://www.cnblogs.com/Tan-sir/p/7488796.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市绍些,隨后出現(xiàn)的幾起案子捞慌,更是在濱河造成了極大的恐慌,老刑警劉巖柬批,帶你破解...
    沈念sama閱讀 221,695評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件啸澡,死亡現(xiàn)場離奇詭異袖订,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)嗅虏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門洛姑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人皮服,你說我怎么就攤上這事楞艾。” “怎么了龄广?”我有些...
    開封第一講書人閱讀 168,130評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵硫眯,是天一觀的道長。 經(jīng)常有香客問我择同,道長两入,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評(píng)論 1 297
  • 正文 為了忘掉前任敲才,我火速辦了婚禮裹纳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘紧武。我一直安慰自己剃氧,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,655評(píng)論 6 397
  • 文/花漫 我一把揭開白布脏里。 她就那樣靜靜地躺著她我,像睡著了一般。 火紅的嫁衣襯著肌膚如雪迫横。 梳的紋絲不亂的頭發(fā)上番舆,一...
    開封第一講書人閱讀 52,268評(píng)論 1 309
  • 那天,我揣著相機(jī)與錄音矾踱,去河邊找鬼恨狈。 笑死,一個(gè)胖子當(dāng)著我的面吹牛呛讲,可吹牛的內(nèi)容都是我干的禾怠。 我是一名探鬼主播,決...
    沈念sama閱讀 40,835評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼贝搁,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼吗氏!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起雷逆,我...
    開封第一講書人閱讀 39,740評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤弦讽,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體往产,經(jīng)...
    沈念sama閱讀 46,286評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡被碗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,375評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了仿村。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锐朴。...
    茶點(diǎn)故事閱讀 40,505評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蔼囊,靈堂內(nèi)的尸體忽然破棺而出焚志,到底是詐尸還是另有隱情,我是刑警寧澤压真,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布娩嚼,位于F島的核電站蘑险,受9級(jí)特大地震影響滴肿,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜佃迄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,873評(píng)論 3 333
  • 文/蒙蒙 一泼差、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧呵俏,春花似錦堆缘、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至麻车,卻和暖如春缀皱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背动猬。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評(píng)論 1 272
  • 我被黑心中介騙來泰國打工啤斗, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人赁咙。 一個(gè)月前我還...
    沈念sama閱讀 48,921評(píng)論 3 376
  • 正文 我出身青樓钮莲,卻偏偏與公主長得像,于是被迫代替她去往敵國和親彼水。 傳聞我的和親對(duì)象是個(gè)殘疾皇子崔拥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,515評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容