細(xì)話mmap

mmap基礎(chǔ)概念

mmap是一種內(nèi)存映射文件的方法,即將一個文件或者其它對象映射到進(jìn)程的地址空間,實(shí)現(xiàn)文件磁盤地址和進(jìn)程虛擬地址空間中一段虛擬地址的一一對映關(guān)系。實(shí)現(xiàn)這樣的映射關(guān)系后,進(jìn)程就可以采用指針的方式讀寫操作這一段內(nèi)存宣赔,而系統(tǒng)會自動回寫臟頁面到對應(yīng)的文件磁盤上媳溺,即完成了對文件的操作而不必再調(diào)用read,write等系統(tǒng)調(diào)用函數(shù)戏阅。相反橙凳,內(nèi)核空間對這段區(qū)域的修改也直接反映用戶空間罪针,從而可以實(shí)現(xiàn)不同進(jìn)程間的文件共享彭羹。如下圖所示:


mmap

由上圖可以看出,進(jìn)程的虛擬地址空間泪酱,由多個虛擬內(nèi)存區(qū)域構(gòu)成派殷。虛擬內(nèi)存區(qū)域是進(jìn)程的虛擬地址空間中的一個同質(zhì)區(qū)間,即具有同樣特性的連續(xù)地址范圍墓阀。上圖中所示的text數(shù)據(jù)段(代碼段)毡惜、初始數(shù)據(jù)段、BSS數(shù)據(jù)段斯撮、堆经伙、棧和內(nèi)存映射,都是一個獨(dú)立的虛擬內(nèi)存區(qū)域勿锅。而為內(nèi)存映射服務(wù)的地址空間處在堆棧之間的空余部分帕膜。

linux內(nèi)核使用vm_area_struct結(jié)構(gòu)來表示一個獨(dú)立的虛擬內(nèi)存區(qū)域,由于每個不同質(zhì)的虛擬內(nèi)存區(qū)域功能和內(nèi)部機(jī)制都不同粱甫,因此一個進(jìn)程使用多個vm_area_struct結(jié)構(gòu)來分別表示不同類型的虛擬內(nèi)存區(qū)域泳叠。各個vm_area_struct結(jié)構(gòu)使用鏈表或者樹形結(jié)構(gòu)鏈接,方便進(jìn)程快速訪問茶宵,如下圖所示:


共享存儲映射

vm_area_struct結(jié)構(gòu)中包含區(qū)域起始和終止地址以及其他相關(guān)信息危纫,同時也包含一個vm_ops指針,其內(nèi)部可引出所有針對這個區(qū)域可以使用的系統(tǒng)調(diào)用函數(shù)。這樣种蝶,進(jìn)程對某一虛擬內(nèi)存區(qū)域的任何操作需要用要的信息契耿,都可以從vm_area_struct中獲得。mmap函數(shù)就是要創(chuàng)建一個新的vm_area_struct結(jié)構(gòu)螃征,并將其與文件的物理磁盤地址相連搪桂。

mmap內(nèi)存映射原理

mmap內(nèi)存映射的實(shí)現(xiàn)過程,總的來說可以分為三個階段:

(一)進(jìn)程啟動映射過程盯滚,并在虛擬地址空間中為映射創(chuàng)建虛擬映射區(qū)域

1踢械、進(jìn)程在用戶空間調(diào)用庫函數(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ū)分配一個vm_area_struct結(jié)構(gòu)背率,接著對這個結(jié)構(gòu)的各個域進(jìn)行了初始化
4话瞧、將新建的虛擬區(qū)結(jié)構(gòu)(vm_area_struct)插入進(jìn)程的虛擬地址區(qū)域鏈表或樹中

(二)調(diào)用內(nèi)核空間的系統(tǒng)調(diào)用函數(shù)mmap(不同于用戶空間函數(shù)),實(shí)現(xiàn)文件物理地址和進(jìn)程虛擬地址的一一映射關(guān)系
1寝姿、為映射分配了新的虛擬地址區(qū)域后交排,通過待映射的文件指針,在文件描述符表中找到對應(yīng)的文件描述符饵筑,通過文件描述符埃篓,鏈接到內(nèi)核“已打開文件集”中該文件的文件結(jié)構(gòu)體(struct file),每個文件結(jié)構(gòu)體維護(hù)著和這個已打開文件相關(guān)各項(xiàng)信息根资。
2都许、通過該文件的文件結(jié)構(gòu)體,鏈接到file_operations模塊嫂冻,調(diào)用內(nèi)核函數(shù)mmap,其原型為:int mmap(struct file *filp, struct vm_area_struct *vma)塞椎,不同于用戶空間庫函數(shù)桨仿。
3、內(nèi)核mmap函數(shù)通過虛擬文件系統(tǒng)inode模塊定位到文件磁盤物理地址案狠。
4服傍、通過remap_pfn_range函數(shù)建立頁表,即實(shí)現(xiàn)了文件地址和虛擬地址區(qū)域的映射關(guān)系骂铁。此時吹零,這片虛擬地址并沒有任何數(shù)據(jù)關(guān)聯(lián)到主存中。

(三)進(jìn)程發(fā)起對這片映射空間的訪問拉庵,引發(fā)缺頁異常灿椅,實(shí)現(xiàn)文件內(nèi)容到物理內(nèi)存(主存)的拷貝

注:前兩個階段僅在于創(chuàng)建虛擬區(qū)間并完成地址映射,但是并沒有將任何文件數(shù)據(jù)的拷貝至主存。真正的文件讀取是當(dāng)進(jìn)程發(fā)起讀或?qū)懖僮鲿r茫蛹。
1操刀、進(jìn)程的讀或?qū)懖僮髟L問虛擬地址空間這一段映射地址,通過查詢頁表婴洼,發(fā)現(xiàn)這一段地址并不在物理頁面上骨坑。因?yàn)槟壳爸唤⒘说刂酚成洌嬲挠脖P數(shù)據(jù)還沒有拷貝到內(nèi)存中柬采,因此引發(fā)缺頁異常欢唾。
2、缺頁異常進(jìn)行一系列判斷粉捻,確定無非法操作后礁遣,內(nèi)核發(fā)起請求調(diào)頁過程。
3杀迹、調(diào)頁過程先在交換緩存空間(swap cache)中尋找需要訪問的內(nèi)存頁亡脸,如果沒有則調(diào)用nopage函數(shù)把所缺的頁從磁盤裝入到主存中。
4树酪、之后進(jìn)程即可對這片主存進(jìn)行讀或者寫的操作浅碾,如果寫操作改變了其內(nèi)容,一定時間后系統(tǒng)會自動回寫臟頁面到對應(yīng)磁盤地址续语,也即完成了寫入到文件的過程垂谢。

注:修改過的臟頁面并不會立即更新回文件中,而是有一段時間的延遲疮茄,可以調(diào)用msync()來強(qiáng)制同步, 這樣所寫的內(nèi)容就能立即保存到文件里了滥朱。

mmap和常規(guī)文件操作的區(qū)別

常規(guī)文件系統(tǒng)操作(調(diào)用read/fread等類函數(shù))中,函數(shù)的調(diào)用過程:
1力试、進(jìn)程發(fā)起讀文件請求徙邻。
2、內(nèi)核通過查找進(jìn)程文件符表畸裳,定位到內(nèi)核已打開文件集上的文件信息缰犁,從而找到此文件的inode。
3怖糊、inode在address_space上查找要請求的文件頁是否已經(jīng)緩存在頁緩存中帅容。如果存在,則直接返回這片文件頁的內(nèi)容伍伤。
4并徘、如果不存在,則通過inode定位到文件磁盤地址扰魂,將數(shù)據(jù)從磁盤復(fù)制到頁緩存麦乞。之后再次發(fā)起讀頁面過程蕴茴,進(jìn)而將頁緩存中的數(shù)據(jù)發(fā)給用戶進(jìn)程。

總結(jié)來說路幸,常規(guī)文件操作為了提高讀寫效率和保護(hù)磁盤荐开,使用了頁緩存機(jī)制。這樣造成讀文件時需要先將文件頁從磁盤拷貝到頁緩存中简肴,由于頁緩存處在內(nèi)核空間晃听,不能被用戶進(jìn)程直接尋址,所以還需要將頁緩存中數(shù)據(jù)頁再次拷貝到內(nèi)存對應(yīng)的用戶空間中砰识。這樣能扒,通過了兩次數(shù)據(jù)拷貝過程,才能完成進(jìn)程對文件內(nèi)容的獲取任務(wù)辫狼。寫操作也是一樣初斑,待寫入的buffer在內(nèi)核空間不能直接訪問,必須要先拷貝至內(nèi)核空間對應(yīng)的主存膨处,再寫回磁盤中(延遲寫回)见秤,也是需要兩次數(shù)據(jù)拷貝。

而使用mmap操作文件中真椿,創(chuàng)建新的虛擬內(nèi)存區(qū)域和建立文件磁盤地址和虛擬內(nèi)存區(qū)域映射這兩步鹃答,沒有任何文件拷貝操作。而之后訪問數(shù)據(jù)時發(fā)現(xiàn)內(nèi)存中并無數(shù)據(jù)而發(fā)起的缺頁異常過程突硝,可以通過已經(jīng)建立好的映射關(guān)系测摔,只使用一次數(shù)據(jù)拷貝,就從磁盤中將數(shù)據(jù)傳入內(nèi)存的用戶空間中解恰,供進(jìn)程使用锋八。

總而言之,常規(guī)文件操作需要從磁盤到頁緩存再到用戶主存的兩次數(shù)據(jù)拷貝护盈。而mmap操控文件挟纱,只需要從磁盤到用戶主存的一次數(shù)據(jù)拷貝過程。說白了腐宋,mmap的關(guān)鍵點(diǎn)是實(shí)現(xiàn)了用戶空間和內(nèi)核空間的數(shù)據(jù)直接交互而省去了空間不同數(shù)據(jù)不通的繁瑣過程樊销。因此mmap效率更高。

mmap優(yōu)點(diǎn)總結(jié)

由上文討論可知脏款,mmap優(yōu)點(diǎn)共有一下幾點(diǎn):
1、對文件的讀取操作跨過了頁緩存裤园,減少了數(shù)據(jù)的拷貝次數(shù)撤师,用內(nèi)存讀寫取代I/O讀寫,提高了文件讀取效率拧揽。
2剃盾、實(shí)現(xiàn)了用戶空間和內(nèi)核空間的高效交互方式腺占。兩空間的各自修改操作可以直接反映在映射的區(qū)域內(nèi),從而被對方空間及時捕捉痒谴。
3衰伯、提供進(jìn)程間共享內(nèi)存及相互通信的方式。不管是父子進(jìn)程還是無親緣關(guān)系的進(jìn)程积蔚,都可以將自身用戶空間映射到同一個文件或匿名映射到同一片區(qū)域意鲸。從而通過各自對映射區(qū)域的改動,達(dá)到進(jìn)程間通信和進(jìn)程間共享的目的尽爆。
同時怎顾,如果進(jìn)程A和進(jìn)程B都映射了區(qū)域C,當(dāng)A第一次讀取C時通過缺頁從磁盤復(fù)制文件頁到內(nèi)存中漱贱;但當(dāng)B再讀C的相同頁面時槐雾,雖然也會產(chǎn)生缺頁異常,但是不再需要從磁盤中復(fù)制文件過來幅狮,而可直接使用已經(jīng)保存在內(nèi)存中的文件數(shù)據(jù)募强。
4、可用于實(shí)現(xiàn)高效的大規(guī)模數(shù)據(jù)傳輸崇摄。內(nèi)存空間不足擎值,是制約大數(shù)據(jù)操作的一個方面,解決方案往往是借助硬盤空間協(xié)助操作配猫,補(bǔ)充內(nèi)存的不足幅恋。但是進(jìn)一步會造成大量的文件I/O操作,極大影響效率泵肄。這個問題可以通過mmap映射很好的解決捆交。換句話說,但凡是需要用磁盤空間代替內(nèi)存的時候腐巢,mmap都可以發(fā)揮其功效品追。

mmap相關(guān)函數(shù)

函數(shù)原型
void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);

返回說明
成功執(zhí)行時,mmap()返回被映射區(qū)的指針冯丙。失敗時肉瓦,mmap()返回MAP_FAILED[其值為(void *)-1], error被設(shè)為以下的某個值:
返回錯誤類型
1 EACCES:訪問出錯
2 EAGAIN:文件已被鎖定胃惜,或者太多的內(nèi)存已被鎖定
3 EBADF:fd不是有效的文件描述詞
4 EINVAL:一個或者多個參數(shù)無效
5 ENFILE:已達(dá)到系統(tǒng)對打開文件的限制
6 ENODEV:指定文件所在的文件系統(tǒng)不支持內(nèi)存映射
7 ENOMEM:內(nèi)存不足泞莉,或者進(jìn)程已超出最大內(nèi)存映射數(shù)量
8 EPERM:權(quán)能不足,操作不允許
9 ETXTBSY:已寫的方式打開文件船殉,同時指定MAP_DENYWRITE標(biāo)志
10 SIGSEGV:試著向只讀區(qū)寫入
11 SIGBUS:試著訪問不屬于進(jìn)程的內(nèi)存區(qū)

參數(shù)
start:映射區(qū)的開始地址
length:映射區(qū)的長度
prot:期望的內(nèi)存保護(hù)標(biāo)志鲫趁,不能與文件的打開模式?jīng)_突。是以下的某個值利虫,可以通過or運(yùn)算合理地組合在一起挨厚,可能取值:
1堡僻、 PROT_EXEC :頁內(nèi)容可以被執(zhí)行
2、 PROT_READ :頁內(nèi)容可以被讀取
3疫剃、 PROT_WRITE :頁可以被寫入
4钉疫、 PROT_NONE :頁不可訪問

flags:指定映射對象的類型,映射選項(xiàng)和映射頁是否可以共享巢价。它的值可以是一個或者多個以下位的組合體:
1牲阁、 MAP_FIXED //使用指定的映射起始地址,如果由start和len參數(shù)指定的內(nèi)存區(qū)重疊于現(xiàn)存的映射空間蹄溉,重疊部分將會被丟棄咨油。如果指定的起始地址不可用,操作將會失敗柒爵。并且起始地址必須落在頁的邊界上役电。
2、 MAP_SHARED //與其它所有映射這個對象的進(jìn)程共享映射空間棉胀。對共享區(qū)的寫入法瑟,相當(dāng)于輸出到文件。直到msync()或者munmap()被調(diào)用唁奢,文件實(shí)際上不會被更新霎挟。
3、 MAP_PRIVATE //建立一個寫入時拷貝的私有映射麻掸。內(nèi)存區(qū)域的寫入不會影響到原文件酥夭。這個標(biāo)志和以上標(biāo)志是互斥的,只能使用其中一個脊奋。
4熬北、 MAP_DENYWRITE //這個標(biāo)志被忽略。
5诚隙、 MAP_EXECUTABLE //同上
6讶隐、 MAP_NORESERVE //不要為這個映射保留交換空間。當(dāng)交換空間被保留久又,對映射區(qū)修改的可能會得到保證巫延。當(dāng)交換空間不被保留,同時內(nèi)存不足地消,對映射區(qū)的修改會引起段違例信號炉峰。
7、 MAP_LOCKED //鎖定映射區(qū)的頁面脉执,從而防止頁面被交換出內(nèi)存疼阔。
8、 MAP_GROWSDOWN //用于堆棧适瓦,告訴內(nèi)核VM系統(tǒng)竿开,映射區(qū)可以向下擴(kuò)展。
9玻熙、 MAP_ANONYMOUS //匿名映射否彩,映射區(qū)不與任何文件關(guān)聯(lián)。
10嗦随、 MAP_ANON //MAP_ANONYMOUS的別稱列荔,不再被使用。
11枚尼、 MAP_FILE //兼容標(biāo)志贴浙,被忽略。
12署恍、 MAP_32BIT //將映射區(qū)放在進(jìn)程地址空間的低2GB崎溃,MAP_FIXED指定時會被忽略。當(dāng)前這個標(biāo)志只在x86-64平臺上得到支持盯质。
13袁串、 MAP_POPULATE //為文件映射通過預(yù)讀的方式準(zhǔn)備好頁表。隨后對映射區(qū)的訪問不會被頁違例阻塞呼巷。
14囱修、 MAP_NONBLOCK //僅和MAP_POPULATE一起使用時才有意義。不執(zhí)行預(yù)讀王悍,只為已存在于內(nèi)存中的頁面建立頁表入口破镰。

fd:有效的文件描述詞。如果MAP_ANONYMOUS被設(shè)定压储,為了兼容問題鲜漩,其值應(yīng)為-1
offset:被映射對象內(nèi)容的起點(diǎn)

相關(guān)函數(shù)
int munmap( void * addr, size_t len )
成功執(zhí)行時,munmap()返回0渠脉。失敗時宇整,munmap返回-1,error返回標(biāo)志和mmap一致芋膘;
該調(diào)用在進(jìn)程地址空間中解除一個映射關(guān)系鳞青,addr是調(diào)用mmap()時返回的地址,len是映射區(qū)的大形蟆臂拓;
當(dāng)映射關(guān)系解除后,對原來映射地址的訪問將導(dǎo)致段錯誤發(fā)生习寸。

int msync( void *addr, size_t len, int flags )
一般說來胶惰,進(jìn)程在映射空間的對共享內(nèi)容的改變并不直接寫回到磁盤文件中,往往在調(diào)用munmap()后才執(zhí)行該操作霞溪。
可以通過調(diào)用msync()實(shí)現(xiàn)磁盤上文件內(nèi)容與共享內(nèi)存區(qū)的內(nèi)容一致孵滞。

mmap使用細(xì)節(jié)

1中捆、使用mmap需要注意的一個關(guān)鍵點(diǎn)是,mmap映射區(qū)域大小必須是物理頁大小(page_size)的整倍數(shù)(32位系統(tǒng)中通常是4k字節(jié))坊饶。原因是泄伪,內(nèi)存的最小粒度是頁,而進(jìn)程虛擬地址空間和內(nèi)存的映射也是以頁為單位匿级。為了匹配內(nèi)存的操作蟋滴,mmap從磁盤到虛擬地址空間的映射也必須是頁。

2痘绎、內(nèi)核可以跟蹤被內(nèi)存映射的底層對象(文件)的大小津函,進(jìn)程可以合法的訪問在當(dāng)前文件大小以內(nèi)又在內(nèi)存映射區(qū)以內(nèi)的那些字節(jié)。也就是說孤页,如果文件的大小一直在擴(kuò)張尔苦,只要在映射區(qū)域范圍內(nèi)的數(shù)據(jù),進(jìn)程都可以合法得到散庶,這和映射建立時文件的大小無關(guān)蕉堰。具體情形參見“情形三”。

3悲龟、映射建立之后屋讶,即使文件關(guān)閉,映射依然存在须教。因?yàn)橛成涞氖谴疟P的地址皿渗,不是文件本身,和文件句柄無關(guān)轻腺。同時可用于進(jìn)程間通信的有效地址空間不完全受限于被映射文件的大小乐疆,因?yàn)槭前错撚成洹?/p>

在上面的知識前提下,我們下面看看如果大小不是頁的整倍數(shù)的具體情況:

情形一:一個文件的大小是5000字節(jié)贬养,mmap函數(shù)從一個文件的起始位置開始挤土,映射5000字節(jié)到虛擬內(nèi)存中。
分析:因?yàn)閱挝晃锢眄撁娴拇笮∈?096字節(jié)误算,雖然被映射的文件只有5000字節(jié)仰美,但是對應(yīng)到進(jìn)程虛擬地址區(qū)域的大小需要滿足整頁大小,因此mmap函數(shù)執(zhí)行后儿礼,實(shí)際映射到虛擬內(nèi)存區(qū)域8192個 字節(jié)咖杂,5000~8191的字節(jié)部分用零填充。映射后的對應(yīng)關(guān)系如下圖所示:

情形一

此時:
(1)讀/寫前5000個字節(jié)(0~4999)蚊夫,會返回操作文件內(nèi)容诉字。
(2)讀字節(jié)50008191時,結(jié)果全為0。寫50008191時壤圃,進(jìn)程不會報(bào)錯陵霉,但是所寫的內(nèi)容不會寫入原文件中 。
(3)讀/寫8192以外的磁盤部分伍绳,會返回一個SIGSECV錯誤撩匕。

情形二:一個文件的大小是5000字節(jié),mmap函數(shù)從一個文件的起始位置開始墨叛,映射15000字節(jié)到虛擬內(nèi)存中,即映射大小超過了原始文件的大小模蜡。

分析:由于文件的大小是5000字節(jié)漠趁,和情形一一樣,其對應(yīng)的兩個物理頁忍疾。那么這兩個物理頁都是合法可以讀寫的闯传,只是超出5000的部分不會體現(xiàn)在原文件中。由于程序要求映射15000字節(jié)卤妒,而文件只占兩個物理頁甥绿,因此8192字節(jié)~15000字節(jié)都不能讀寫,操作時會返回異常则披。如下圖所示:


情形二

此時:
(1)進(jìn)程可以正常讀/寫被映射的前5000字節(jié)(0~4999)共缕,寫操作的改動會在一定時間后反映在原文件中。
(2)對于5000~8191字節(jié)士复,進(jìn)程可以進(jìn)行讀寫過程图谷,不會報(bào)錯。但是內(nèi)容在寫入前均為0阱洪,另外便贵,寫入后不會反映在文件中。
(3)對于8192~14999字節(jié)冗荸,進(jìn)程不能對其進(jìn)行讀寫承璃,會報(bào)SIGBUS錯誤。
(4)對于15000以外的字節(jié)蚌本,進(jìn)程不能對其讀寫盔粹,會引發(fā)SIGSEGV錯誤。

**情形三:一個文件初始大小為0魂毁,使用mmap操作映射了1000*4K的大小玻佩,即1000個物理頁大約4M字節(jié)空間,mmap返回指針ptr席楚。

分析:如果在映射建立之初咬崔,就對文件進(jìn)行讀寫操作,由于文件大小為0,并沒有合法的物理頁對應(yīng)垮斯,如同情形二一樣郎仆,會返回SIGBUS錯誤。

但是如果兜蠕,每次操作ptr讀寫前扰肌,先增加文件的大小,那么ptr在文件大小內(nèi)部的操作就是合法的熊杨。例如曙旭,文件擴(kuò)充4096字節(jié),ptr就能操作ptr ~ [ (char)ptr + 4095]的空間晶府。只要文件擴(kuò)充的范圍在1000個物理頁(映射范圍)內(nèi)桂躏,ptr都可以對應(yīng)操作相同的大小。

這樣川陆,方便隨時擴(kuò)充文件空間剂习,隨時寫入文件,不造成空間浪費(fèi)较沪。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鳞绕,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子尸曼,更是在濱河造成了極大的恐慌们何,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件控轿,死亡現(xiàn)場離奇詭異垂蜗,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)解幽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進(jìn)店門贴见,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人躲株,你說我怎么就攤上這事片部。” “怎么了霜定?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵档悠,是天一觀的道長。 經(jīng)常有香客問我望浩,道長辖所,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任磨德,我火速辦了婚禮缘回,結(jié)果婚禮上吆视,老公的妹妹穿的比我還像新娘。我一直安慰自己酥宴,他們只是感情好啦吧,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著拙寡,像睡著了一般授滓。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上肆糕,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天般堆,我揣著相機(jī)與錄音,去河邊找鬼诚啃。 笑死郁妈,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的绍申。 我是一名探鬼主播,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼顾彰,長吁一口氣:“原來是場噩夢啊……” “哼极阅!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起涨享,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤筋搏,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后厕隧,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體奔脐,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年吁讨,在試婚紗的時候發(fā)現(xiàn)自己被綠了髓迎。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡建丧,死狀恐怖排龄,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情翎朱,我是刑警寧澤橄维,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站拴曲,受9級特大地震影響争舞,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜澈灼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一竞川、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦流译、人聲如沸逞怨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽叠赦。三九已至,卻和暖如春革砸,著一層夾襖步出監(jiān)牢的瞬間除秀,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工算利, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留册踩,地道東北人。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓效拭,卻偏偏與公主長得像暂吉,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子缎患,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評論 2 351

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