內(nèi)存映射

轉(zhuǎn)自認(rèn)真分析mmap:是什么 為什么 怎么用

閱讀目錄
mmap基礎(chǔ)概念
mmap內(nèi)存映射原理
mmap和常規(guī)文件操作的區(qū)別
mmap優(yōu)點(diǎn)總結(jié)
mmap相關(guān)函數(shù)
mmap使用細(xì)節(jié)

回到頂部
mmap基礎(chǔ)概念
mmap是一種內(nèi)存映射文件的方法筋量,即將一個(gè)文件或者其它對(duì)象映射到進(jìn)程的地址空間,實(shí)現(xiàn)文件磁盤(pán)地址和進(jìn)程虛擬地址空間中一段虛擬地址的一一對(duì)映關(guān)系讶舰。實(shí)現(xiàn)這樣的映射關(guān)系后师妙,進(jìn)程就可以采用指針的方式讀寫(xiě)操作這一段內(nèi)存都许,而系統(tǒng)會(huì)自動(dòng)回寫(xiě)臟頁(yè)面到對(duì)應(yīng)的文件磁盤(pán)上,即完成了對(duì)文件的操作而不必再調(diào)用read,write等系統(tǒng)調(diào)用函數(shù)嗽桩。相反传透,內(nèi)核空間對(duì)這段區(qū)域的修改也直接反映用戶(hù)空間,從而可以實(shí)現(xiàn)不同進(jìn)程間的文件共享韧衣。如下圖所示:


由上圖可以看出,進(jìn)程的虛擬地址空間购桑,由多個(gè)虛擬內(nèi)存區(qū)域構(gòu)成畅铭。虛擬內(nèi)存區(qū)域是進(jìn)程的虛擬地址空間中的一個(gè)同質(zhì)區(qū)間,即具有同樣特性的連續(xù)地址范圍勃蜘。上圖中所示的text數(shù)據(jù)段(代碼段)硕噩、初始數(shù)據(jù)段、BSS數(shù)據(jù)段缭贡、堆炉擅、棧和內(nèi)存映射,都是一個(gè)獨(dú)立的虛擬內(nèi)存區(qū)域阳惹。而為內(nèi)存映射服務(wù)的地址空間處在堆棧之間的空余部分谍失。
linux內(nèi)核使用vm_area_struct結(jié)構(gòu)來(lái)表示一個(gè)獨(dú)立的虛擬內(nèi)存區(qū)域,由于每個(gè)不同質(zhì)的虛擬內(nèi)存區(qū)域功能和內(nèi)部機(jī)制都不同莹汤,因此一個(gè)進(jìn)程使用多個(gè)vm_area_struct結(jié)構(gòu)來(lái)分別表示不同類(lèi)型的虛擬內(nèi)存區(qū)域快鱼。各個(gè)vm_area_struct結(jié)構(gòu)使用鏈表或者樹(shù)形結(jié)構(gòu)鏈接,方便進(jìn)程快速訪問(wèn)纲岭,如下圖所示:

vm_area_struct結(jié)構(gòu)中包含區(qū)域起始和終止地址以及其他相關(guān)信息抹竹,同時(shí)也包含一個(gè)vm_ops指針,其內(nèi)部可引出所有針對(duì)這個(gè)區(qū)域可以使用的系統(tǒng)調(diào)用函數(shù)止潮。這樣窃判,進(jìn)程對(duì)某一虛擬內(nèi)存區(qū)域的任何操作需要用要的信息,都可以從vm_area_struct中獲得喇闸。mmap函數(shù)就是要?jiǎng)?chuàng)建一個(gè)新的vm_area_struct結(jié)構(gòu)袄琳,并將其與文件的物理磁盤(pán)地址相連询件。具體步驟請(qǐng)看下一節(jié)。

回到頂部
mmap內(nèi)存映射原理
mmap內(nèi)存映射的實(shí)現(xiàn)過(guò)程跨蟹,總的來(lái)說(shuō)可以分為三個(gè)階段:
(一)進(jìn)程啟動(dòng)映射過(guò)程雳殊,并在虛擬地址空間中為映射創(chuàng)建虛擬映射區(qū)域
1、進(jìn)程在用戶(hù)空間調(diào)用庫(kù)函數(shù)mmap窗轩,原型:void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
2夯秃、在當(dāng)前進(jìn)程的虛擬地址空間中,尋找一段空閑的滿足要求的連續(xù)的虛擬地址
3痢艺、為此虛擬區(qū)分配一個(gè)vm_area_struct結(jié)構(gòu)仓洼,接著對(duì)這個(gè)結(jié)構(gòu)的各個(gè)域進(jìn)行了初始化
4、將新建的虛擬區(qū)結(jié)構(gòu)(vm_area_struct)插入進(jìn)程的虛擬地址區(qū)域鏈表或樹(shù)中

(二)調(diào)用內(nèi)核空間的系統(tǒng)調(diào)用函數(shù)mmap(不同于用戶(hù)空間函數(shù))堤舒,實(shí)現(xiàn)文件物理地址和進(jìn)程虛擬地址的一一映射關(guān)系
5色建、為映射分配了新的虛擬地址區(qū)域后,通過(guò)待映射的文件指針舌缤,在文件描述符表中找到對(duì)應(yīng)的文件描述符箕戳,通過(guò)文件描述符,鏈接到內(nèi)核“已打開(kāi)文件集”中該文件的文件結(jié)構(gòu)體(struct file)国撵,每個(gè)文件結(jié)構(gòu)體維護(hù)著和這個(gè)已打開(kāi)文件相關(guān)各項(xiàng)信息陵吸。
6、通過(guò)該文件的文件結(jié)構(gòu)體介牙,鏈接到file_operations模塊壮虫,調(diào)用內(nèi)核函數(shù)mmap,其原型為:int mmap(struct file *filp, struct vm_area_struct *vma)环础,不同于用戶(hù)空間庫(kù)函數(shù)囚似。
7、內(nèi)核mmap函數(shù)通過(guò)虛擬文件系統(tǒng)inode模塊定位到文件磁盤(pán)物理地址线得。
8饶唤、通過(guò)remap_pfn_range函數(shù)建立頁(yè)表,即實(shí)現(xiàn)了文件地址和虛擬地址區(qū)域的映射關(guān)系框都。此時(shí)搬素,這片虛擬地址并沒(méi)有任何數(shù)據(jù)關(guān)聯(lián)到主存中。

(三)進(jìn)程發(fā)起對(duì)這片映射空間的訪問(wèn)魏保,引發(fā)缺頁(yè)異常熬尺,實(shí)現(xiàn)文件內(nèi)容到物理內(nèi)存(主存)的拷貝
注:前兩個(gè)階段僅在于創(chuàng)建虛擬區(qū)間并完成地址映射,但是并沒(méi)有將任何文件數(shù)據(jù)的拷貝至主存谓罗。真正的文件讀取是當(dāng)進(jìn)程發(fā)起讀或?qū)懖僮鲿r(shí)粱哼。
9、進(jìn)程的讀或?qū)懖僮髟L問(wèn)虛擬地址空間這一段映射地址檩咱,通過(guò)查詢(xún)頁(yè)表揭措,發(fā)現(xiàn)這一段地址并不在物理頁(yè)面上胯舷。因?yàn)槟壳爸唤⒘说刂酚成洌嬲挠脖P(pán)數(shù)據(jù)還沒(méi)有拷貝到內(nèi)存中绊含,因此引發(fā)缺頁(yè)異常桑嘶。
10、缺頁(yè)異常進(jìn)行一系列判斷躬充,確定無(wú)非法操作后逃顶,內(nèi)核發(fā)起請(qǐng)求調(diào)頁(yè)過(guò)程。
11充甚、調(diào)頁(yè)過(guò)程先在交換緩存空間(swap cache)中尋找需要訪問(wèn)的內(nèi)存頁(yè)以政,如果沒(méi)有則調(diào)用nopage函數(shù)把所缺的頁(yè)從磁盤(pán)裝入到主存中。
12伴找、之后進(jìn)程即可對(duì)這片主存進(jìn)行讀或者寫(xiě)的操作盈蛮,如果寫(xiě)操作改變了其內(nèi)容,一定時(shí)間后系統(tǒng)會(huì)自動(dòng)回寫(xiě)臟頁(yè)面到對(duì)應(yīng)磁盤(pán)地址技矮,也即完成了寫(xiě)入到文件的過(guò)程抖誉。
注:修改過(guò)的臟頁(yè)面并不會(huì)立即更新回文件中,而是有一段時(shí)間的延遲衰倦,可以調(diào)用msync()來(lái)強(qiáng)制同步, 這樣所寫(xiě)的內(nèi)容就能立即保存到文件里了寸五。

回到頂部
mmap和常規(guī)文件操作的區(qū)別
對(duì)linux文件系統(tǒng)不了解的朋友,請(qǐng)參閱我之前寫(xiě)的博文《從內(nèi)核文件系統(tǒng)看文件讀寫(xiě)過(guò)程》耿币,我們首先簡(jiǎn)單的回顧一下常規(guī)文件系統(tǒng)操作(調(diào)用read/fread等類(lèi)函數(shù))中,函數(shù)的調(diào)用過(guò)程:
1韧拒、進(jìn)程發(fā)起讀文件請(qǐng)求淹接。
2、內(nèi)核通過(guò)查找進(jìn)程文件符表叛溢,定位到內(nèi)核已打開(kāi)文件集上的文件信息塑悼,從而找到此文件的inode。
3楷掉、inode在address_space上查找要請(qǐng)求的文件頁(yè)是否已經(jīng)緩存在頁(yè)緩存中厢蒜。如果存在,則直接返回這片文件頁(yè)的內(nèi)容烹植。
4斑鸦、如果不存在,則通過(guò)inode定位到文件磁盤(pán)地址草雕,將數(shù)據(jù)從磁盤(pán)復(fù)制到頁(yè)緩存巷屿。之后再次發(fā)起讀頁(yè)面過(guò)程,進(jìn)而將頁(yè)緩存中的數(shù)據(jù)發(fā)給用戶(hù)進(jìn)程墩虹。
總結(jié)來(lái)說(shuō)嘱巾,常規(guī)文件操作為了提高讀寫(xiě)效率和保護(hù)磁盤(pán)憨琳,使用了頁(yè)緩存機(jī)制。這樣造成讀文件時(shí)需要先將文件頁(yè)從磁盤(pán)拷貝到頁(yè)緩存中旬昭,由于頁(yè)緩存處在內(nèi)核空間篙螟,不能被用戶(hù)進(jìn)程直接尋址,所以還需要將頁(yè)緩存中數(shù)據(jù)頁(yè)再次拷貝到內(nèi)存對(duì)應(yīng)的用戶(hù)空間中问拘。這樣遍略,通過(guò)了兩次數(shù)據(jù)拷貝過(guò)程,才能完成進(jìn)程對(duì)文件內(nèi)容的獲取任務(wù)场梆。寫(xiě)操作也是一樣墅冷,待寫(xiě)入的buffer在內(nèi)核空間不能直接訪問(wèn),必須要先拷貝至內(nèi)核空間對(duì)應(yīng)的主存或油,再寫(xiě)回磁盤(pán)中(延遲寫(xiě)回)寞忿,也是需要兩次數(shù)據(jù)拷貝。
而使用mmap操作文件中顶岸,創(chuàng)建新的虛擬內(nèi)存區(qū)域和建立文件磁盤(pán)地址和虛擬內(nèi)存區(qū)域映射這兩步腔彰,沒(méi)有任何文件拷貝操作。而之后訪問(wèn)數(shù)據(jù)時(shí)發(fā)現(xiàn)內(nèi)存中并無(wú)數(shù)據(jù)而發(fā)起的缺頁(yè)異常過(guò)程辖佣,可以通過(guò)已經(jīng)建立好的映射關(guān)系霹抛,只使用一次數(shù)據(jù)拷貝,就從磁盤(pán)中將數(shù)據(jù)傳入內(nèi)存的用戶(hù)空間中卷谈,供進(jìn)程使用杯拐。
總而言之,常規(guī)文件操作需要從磁盤(pán)到頁(yè)緩存再到用戶(hù)主存的兩次數(shù)據(jù)拷貝世蔗。而mmap操控文件端逼,只需要從磁盤(pán)到用戶(hù)主存的一次數(shù)據(jù)拷貝過(guò)程。說(shuō)白了污淋,mmap的關(guān)鍵點(diǎn)是實(shí)現(xiàn)了用戶(hù)空間和內(nèi)核空間的數(shù)據(jù)直接交互而省去了空間不同數(shù)據(jù)不通的繁瑣過(guò)程顶滩。因此mmap效率更高。

回到頂部
mmap優(yōu)點(diǎn)總結(jié)
由上文討論可知寸爆,mmap優(yōu)點(diǎn)共有一下幾點(diǎn):
1礁鲁、對(duì)文件的讀取操作跨過(guò)了頁(yè)緩存,減少了數(shù)據(jù)的拷貝次數(shù)赁豆,用內(nèi)存讀寫(xiě)取代I/O讀寫(xiě)仅醇,提高了文件讀取效率。
2歌憨、實(shí)現(xiàn)了用戶(hù)空間和內(nèi)核空間的高效交互方式着憨。兩空間的各自修改操作可以直接反映在映射的區(qū)域內(nèi),從而被對(duì)方空間及時(shí)捕捉务嫡。
3甲抖、提供進(jìn)程間共享內(nèi)存及相互通信的方式漆改。不管是父子進(jìn)程還是無(wú)親緣關(guān)系的進(jìn)程,都可以將自身用戶(hù)空間映射到同一個(gè)文件或匿名映射到同一片區(qū)域准谚。從而通過(guò)各自對(duì)映射區(qū)域的改動(dòng)挫剑,達(dá)到進(jìn)程間通信和進(jìn)程間共享的目的。
同時(shí)柱衔,如果進(jìn)程A和進(jìn)程B都映射了區(qū)域C樊破,當(dāng)A第一次讀取C時(shí)通過(guò)缺頁(yè)從磁盤(pán)復(fù)制文件頁(yè)到內(nèi)存中;但當(dāng)B再讀C的相同頁(yè)面時(shí)唆铐,雖然也會(huì)產(chǎn)生缺頁(yè)異常哲戚,但是不再需要從磁盤(pán)中復(fù)制文件過(guò)來(lái),而可直接使用已經(jīng)保存在內(nèi)存中的文件數(shù)據(jù)艾岂。
4顺少、可用于實(shí)現(xiàn)高效的大規(guī)模數(shù)據(jù)傳輸。內(nèi)存空間不足王浴,是制約大數(shù)據(jù)操作的一個(gè)方面脆炎,解決方案往往是借助硬盤(pán)空間協(xié)助操作,補(bǔ)充內(nèi)存的不足氓辣。但是進(jìn)一步會(huì)造成大量的文件I/O操作秒裕,極大影響效率。這個(gè)問(wèn)題可以通過(guò)mmap映射很好的解決钞啸。換句話說(shuō)几蜻,但凡是需要用磁盤(pán)空間代替內(nèi)存的時(shí)候,mmap都可以發(fā)揮其功效体斩。

回到頂部
mmap相關(guān)函數(shù)
函數(shù)原型
void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
返回說(shuō)明
成功執(zhí)行時(shí)入蛆,mmap()返回被映射區(qū)的指針。失敗時(shí)硕勿,mmap()返回MAP_FAILED[其值為(void *)-1],error被設(shè)為以下的某個(gè)值:

返回錯(cuò)誤類(lèi)型
參數(shù)
start:映射區(qū)的開(kāi)始地址
length:映射區(qū)的長(zhǎng)度
prot:期望的內(nèi)存保護(hù)標(biāo)志枫甲,不能與文件的打開(kāi)模式?jīng)_突源武。是以下的某個(gè)值,可以通過(guò)or運(yùn)算合理地組合在一起
prot
flags:指定映射對(duì)象的類(lèi)型想幻,映射選項(xiàng)和映射頁(yè)是否可以共享粱栖。它的值可以是一個(gè)或者多個(gè)以下位的組合體
flag
fd:有效的文件描述詞。如果MAP_ANONYMOUS被設(shè)定脏毯,為了兼容問(wèn)題闹究,其值應(yīng)為-1
offset:被映射對(duì)象內(nèi)容的起點(diǎn)
相關(guān)函數(shù)
int munmap( void * addr, size_t len )
成功執(zhí)行時(shí),munmap()返回0食店。失敗時(shí)渣淤,munmap返回-1赏寇,error返回標(biāo)志和mmap一致;
該調(diào)用在進(jìn)程地址空間中解除一個(gè)映射關(guān)系价认,addr是調(diào)用mmap()時(shí)返回的地址嗅定,len是映射區(qū)的大小用踩;
當(dāng)映射關(guān)系解除后渠退,對(duì)原來(lái)映射地址的訪問(wèn)將導(dǎo)致段錯(cuò)誤發(fā)生。

int msync( void *addr, size_t len, int flags )
一般說(shuō)來(lái)脐彩,進(jìn)程在映射空間的對(duì)共享內(nèi)容的改變并不直接寫(xiě)回到磁盤(pán)文件中碎乃,往往在調(diào)用munmap()后才執(zhí)行該操作。
可以通過(guò)調(diào)用msync()實(shí)現(xiàn)磁盤(pán)上文件內(nèi)容與共享內(nèi)存區(qū)的內(nèi)容一致惠奸。

回到頂部
mmap使用細(xì)節(jié)
1梅誓、使用mmap需要注意的一個(gè)關(guān)鍵點(diǎn)是,mmap映射區(qū)域大小必須是物理頁(yè)大小(page_size)的整倍數(shù)(32位系統(tǒng)中通常是4k字節(jié))晨川。原因是证九,內(nèi)存的最小粒度是頁(yè),而進(jìn)程虛擬地址空間和內(nèi)存的映射也是以頁(yè)為單位共虑。為了匹配內(nèi)存的操作愧怜,mmap從磁盤(pán)到虛擬地址空間的映射也必須是頁(yè)。
2妈拌、內(nèi)核可以跟蹤被內(nèi)存映射的底層對(duì)象(文件)的大小拥坛,進(jìn)程可以合法的訪問(wèn)在當(dāng)前文件大小以?xún)?nèi)又在內(nèi)存映射區(qū)以?xún)?nèi)的那些字節(jié)。也就是說(shuō)尘分,如果文件的大小一直在擴(kuò)張猜惋,只要在映射區(qū)域范圍內(nèi)的數(shù)據(jù),進(jìn)程都可以合法得到培愁,這和映射建立時(shí)文件的大小無(wú)關(guān)著摔。具體情形參見(jiàn)“情形三”。
3定续、映射建立之后谍咆,即使文件關(guān)閉,映射依然存在私股。因?yàn)橛成涞氖谴疟P(pán)的地址摹察,不是文件本身,和文件句柄無(wú)關(guān)倡鲸。同時(shí)可用于進(jìn)程間通信的有效地址空間不完全受限于被映射文件的大小供嚎,因?yàn)槭前错?yè)映射。

在上面的知識(shí)前提下,我們下面看看如果大小不是頁(yè)的整倍數(shù)的具體情況:
情形一:一個(gè)文件的大小是5000字節(jié)克滴,mmap函數(shù)從一個(gè)文件的起始位置開(kāi)始逼争,映射5000字節(jié)到虛擬內(nèi)存中。
分析:因?yàn)閱挝晃锢眄?yè)面的大小是4096字節(jié)偿曙,雖然被映射的文件只有5000字節(jié)氮凝,但是對(duì)應(yīng)到進(jìn)程虛擬地址區(qū)域的大小需要滿足整頁(yè)大小,因此mmap函數(shù)執(zhí)行后望忆,實(shí)際映射到虛擬內(nèi)存區(qū)域8192個(gè) 字節(jié)罩阵,5000~8191的字節(jié)部分用零填充。映射后的對(duì)應(yīng)關(guān)系如下圖所示:


此時(shí):
(1)讀/寫(xiě)前5000個(gè)字節(jié)(0~4999)启摄,會(huì)返回操作文件內(nèi)容稿壁。
(2)讀字節(jié)50008191時(shí),結(jié)果全為0歉备。寫(xiě)50008191時(shí)傅是,進(jìn)程不會(huì)報(bào)錯(cuò),但是所寫(xiě)的內(nèi)容不會(huì)寫(xiě)入原文件中 蕾羊。
(3)讀/寫(xiě)8192以外的磁盤(pán)部分喧笔,會(huì)返回一個(gè)SIGSECV錯(cuò)誤。

情形二:一個(gè)文件的大小是5000字節(jié)龟再,mmap函數(shù)從一個(gè)文件的起始位置開(kāi)始书闸,映射15000字節(jié)到虛擬內(nèi)存中,即映射大小超過(guò)了原始文件的大小利凑。
分析:由于文件的大小是5000字節(jié)浆劲,和情形一一樣,其對(duì)應(yīng)的兩個(gè)物理頁(yè)哀澈。那么這兩個(gè)物理頁(yè)都是合法可以讀寫(xiě)的牌借,只是超出5000的部分不會(huì)體現(xiàn)在原文件中。由于程序要求映射15000字節(jié)割按,而文件只占兩個(gè)物理頁(yè)膨报,因此8192字節(jié)~15000字節(jié)都不能讀寫(xiě),操作時(shí)會(huì)返回異常适荣。如下圖所示:


此時(shí):
(1)進(jìn)程可以正常讀/寫(xiě)被映射的前5000字節(jié)(0~4999)丙躏,寫(xiě)操作的改動(dòng)會(huì)在一定時(shí)間后反映在原文件中。
(2)對(duì)于5000~8191字節(jié)束凑,進(jìn)程可以進(jìn)行讀寫(xiě)過(guò)程,不會(huì)報(bào)錯(cuò)栅盲。但是內(nèi)容在寫(xiě)入前均為0汪诉,另外,寫(xiě)入后不會(huì)反映在文件中。
(3)對(duì)于8192~14999字節(jié)扒寄,進(jìn)程不能對(duì)其進(jìn)行讀寫(xiě)鱼鼓,會(huì)報(bào)SIGBUS錯(cuò)誤。
(4)對(duì)于15000以外的字節(jié)该编,進(jìn)程不能對(duì)其讀寫(xiě)迄本,會(huì)引發(fā)SIGSEGV錯(cuò)誤。

情形三:一個(gè)文件初始大小為0课竣,使用mmap操作映射了10004K的大小嘉赎,即1000個(gè)物理頁(yè)大約4M字節(jié)空間,mmap返回指針ptr于樟。*
分析:如果在映射建立之初公条,就對(duì)文件進(jìn)行讀寫(xiě)操作,由于文件大小為0迂曲,并沒(méi)有合法的物理頁(yè)對(duì)應(yīng)靶橱,如同情形二一樣,會(huì)返回SIGBUS錯(cuò)誤路捧。
但是如果关霸,每次操作ptr讀寫(xiě)前,先增加文件的大小杰扫,那么ptr在文件大小內(nèi)部的操作就是合法的队寇。例如,文件擴(kuò)充4096字節(jié)涉波,ptr就能操作ptr ~ [ (char)ptr + 4095]的空間英上。只要文件擴(kuò)充的范圍在1000個(gè)物理頁(yè)(映射范圍)內(nèi),ptr都可以對(duì)應(yīng)操作相同的大小啤覆。
這樣苍日,方便隨時(shí)擴(kuò)充文件空間,隨時(shí)寫(xiě)入文件窗声,不造成空間浪費(fèi)相恃。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市笨觅,隨后出現(xiàn)的幾起案子拦耐,更是在濱河造成了極大的恐慌,老刑警劉巖见剩,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件杀糯,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡苍苞,警方通過(guò)查閱死者的電腦和手機(jī)固翰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén)狼纬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人骂际,你說(shuō)我怎么就攤上這事疗琉。” “怎么了歉铝?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵盈简,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我太示,道長(zhǎng)柠贤,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任先匪,我火速辦了婚禮种吸,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘呀非。我一直安慰自己坚俗,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布岸裙。 她就那樣靜靜地躺著猖败,像睡著了一般。 火紅的嫁衣襯著肌膚如雪降允。 梳的紋絲不亂的頭發(fā)上恩闻,一...
    開(kāi)封第一講書(shū)人閱讀 49,166評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音剧董,去河邊找鬼幢尚。 笑死,一個(gè)胖子當(dāng)著我的面吹牛翅楼,可吹牛的內(nèi)容都是我干的尉剩。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼毅臊,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼理茎!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起管嬉,我...
    開(kāi)封第一講書(shū)人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤皂林,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后蚯撩,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體础倍,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年胎挎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了沟启。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扰楼。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖美浦,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情项栏,我是刑警寧澤浦辨,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站沼沈,受9級(jí)特大地震影響流酬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜列另,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一芽腾、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧页衙,春花似錦摊滔、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至眨八,卻和暖如春腺兴,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背廉侧。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工页响, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人段誊。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓闰蚕,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親枕扫。 傳聞我的和親對(duì)象是個(gè)殘疾皇子陪腌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

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