Linux虛擬地址和物理地址的映射(轉(zhuǎn)自博客園)

代碼格式不清漠魏,查看原文章見以下鏈接

https://www.cnblogs.com/big-devil/p/8590228.html

?背景

一般情況下焕襟,Linux系統(tǒng)中碾局,進(jìn)程的4GB內(nèi)存空間被劃分成為兩個部分------用戶空間和內(nèi)核空間桥滨,大小分別為0~3G芽唇,3~4G。用戶進(jìn)程通常情況下脓豪,只能訪問用戶空間的虛擬地址巷帝,不能訪問到內(nèi)核空間。每個進(jìn)程的用戶空間都是完全獨(dú)立扫夜、互不相干的楞泼,用戶進(jìn)程各自有不同的頁表驰徊。而內(nèi)核空間是由內(nèi)核負(fù)責(zé)映射,它并不會跟著進(jìn)程改變堕阔,是固定的棍厂。內(nèi)核空間地址有自己對應(yīng)的頁表,內(nèi)核的虛擬空間獨(dú)立于其他程序超陆。3~4G之間的內(nèi)核空間中牺弹,從低地址到高地址依次為:系統(tǒng)物理內(nèi)存映射區(qū)—隔離帶—vmalloc虛擬內(nèi)存分配區(qū)—隔離帶—高端內(nèi)存映射區(qū)—專用頁面映射區(qū)—保留區(qū)。



?內(nèi)核空間內(nèi)存動態(tài)申請

主要包括三個函數(shù):kmalloc(), __get_free_pages, vmalloc时呀。

?kmalloc(), __get_free_pages申請的內(nèi)存位于物理地址映射區(qū)张漂,而且在物理上也是連續(xù)的,返回的虛擬地址真實(shí)的物理地址(物理地址是連續(xù)的谨娜,虛擬地址也是連續(xù)的)只有一個固定的偏移航攒,因此存在較簡單的轉(zhuǎn)換關(guān)系。

?而vmalloc申請的內(nèi)存位于vmalloc虛擬內(nèi)存分配區(qū)(這些區(qū)都是以線性地址為度量)瞧预,它在虛擬內(nèi)存空間給出一塊連續(xù)的內(nèi)存區(qū)屎债,實(shí)質(zhì)上,這片連續(xù)的虛擬內(nèi)存在物理內(nèi)存中并不一定連續(xù)垢油,而vmalloc申請的虛擬內(nèi)存和物理內(nèi)存之間沒有簡單的換算關(guān)系盆驹。因?yàn)関malloc申請的在虛擬內(nèi)存空間連續(xù)的內(nèi)存區(qū)在物理內(nèi)存中并不一定連續(xù),可以想象為了完成vmalloc滩愁,新的頁表需要被建立躯喇,因此,調(diào)用vmalloc來分配少量內(nèi)存是不妥的硝枉。一般來講廉丽,kmalloc用來分配小于128K的內(nèi)存,而更大的內(nèi)存塊需要用vmalloc來實(shí)現(xiàn)妻味。


?虛擬地址與物理地址關(guān)系

對于內(nèi)核物理內(nèi)存映射區(qū)的虛擬內(nèi)存(用kmalloc(), __get_free_pages申請的)正压,使用virt_to_phys()和phys_to_virt()來實(shí)現(xiàn)物理地址和內(nèi)核虛擬地址之間的互相轉(zhuǎn)換。它實(shí)際上责球,僅僅做了3G的地址移位焦履。上述方法適用于常規(guī)內(nèi)存(內(nèi)核物理內(nèi)存映射區(qū)),高端內(nèi)存的虛擬地址與物理地址之間不存在如此簡單的換算關(guān)系雏逾。因?yàn)樗婕暗搅朔蛛x物理頁的頁表控制機(jī)制嘉裤。


?ioremap

在ARM中,設(shè)備的寄存器或者存儲塊的這部分空間屬于內(nèi)存空間的一部分栖博,我們稱之為IO內(nèi)存屑宠。在內(nèi)核中訪問IO內(nèi)存之前,我們只有IO內(nèi)存的物理地址仇让,這樣是無法通過軟件直接訪問的典奉,需要首先用ioremap()函數(shù)將設(shè)備所處的物理地址映射到內(nèi)核虛擬地址空間(3GB~4GB)躺翻。然后,才能根據(jù)映射所得到的內(nèi)核虛擬地址范圍秋柄,通過訪問指令訪問這些IO內(nèi)存資源获枝。在將I/O內(nèi)存資源的物理地址映射成核心虛地址后,理論上講我們就可以象讀寫RAM那樣直接讀寫I/O內(nèi)存資源了骇笔。為了保證驅(qū)動程序的跨平臺的可移植性,我們應(yīng)該使用Linux中特定的函數(shù)來訪問I/O內(nèi)存資源嚣崭,而不應(yīng)該通過指向核心虛地址的指針來訪問笨触。


?mmap

用mmap映射一個設(shè)備,意味著使用戶空間的一段地址關(guān)聯(lián)到設(shè)備內(nèi)存上雹舀,這使得只要程序在分配的地址范圍內(nèi)進(jìn)行讀取或者寫入芦劣,實(shí)際上就是對設(shè)備的訪問。這種數(shù)據(jù)傳輸是直接的说榆,不需要用到內(nèi)核空間作為數(shù)據(jù)轉(zhuǎn)移的中間站虚吟。remap_page_range()函數(shù)的功能是構(gòu)造用于映射一段物理地址的新頁表,實(shí)現(xiàn)了內(nèi)核空間與用戶空間的映射签财。在內(nèi)核驅(qū)動程序的初始化階段串慰,通過ioremap()將物理地址映射到內(nèi)核虛擬空間;在驅(qū)動程序的mmap系統(tǒng)調(diào)用中唱蒸,使用remap_page_range()將該塊ROM映射到用戶虛擬空間邦鲫。這樣內(nèi)核空間和用戶空間都能訪問這段被映射后的虛擬地址。

?進(jìn)程空間/內(nèi)核空間/IO內(nèi)存

? ??其中神汹,后面兩個指的是同一段物理內(nèi)存區(qū)域庆捺,只是一個為虛擬地址(內(nèi)核空間),一個為物理地址(IO內(nèi)存)屁魏。進(jìn)程空間和內(nèi)核空間對應(yīng)著不同的物理地址滔以,它們之間的數(shù)據(jù)傳遞,是實(shí)際的數(shù)據(jù)的拷貝氓拼。


?進(jìn)程空間/IO內(nèi)存

其中你画,進(jìn)程空間mmap得到的那段虛擬地址跟IO內(nèi)存對應(yīng)著同一段物理地址。這個過程沒有額外的數(shù)據(jù)中轉(zhuǎn)披诗,讀寫都直接針對硬件的物理地址進(jìn)行撬即。

一般來講,小數(shù)據(jù)量的傳輸用ioremap()就足夠了呈队,


?IO內(nèi)存的一般訪問方法

?首先是調(diào)用request_mem_region()申請資源剥槐,即告訴內(nèi)核,本驅(qū)動正在使用這段物理內(nèi)存宪摧,其他驅(qū)動不得訪問它們粒竖。在設(shè)備驅(qū)動模塊加載或open()函數(shù)中進(jìn)行颅崩。

?接著講寄存器地址通過ioremap()映射到內(nèi)核空間虛擬地址,之后就可以通過Linux設(shè)備訪問編程接口訪問這些設(shè)備的寄存器了蕊苗。在設(shè)備驅(qū)動初始化刷后、write(),read(),ioctl()函數(shù)中進(jìn)行。

??訪問完成之后寸莫,應(yīng)對ioremap()申請的虛擬地址進(jìn)行釋放并思,并釋放release_mem_region()申請的IO內(nèi)存資源。在設(shè)備驅(qū)動模塊卸載或release()函數(shù)中進(jìn)行瞧柔。

?linux中的物理地址和虛擬地址?:

? ??在支持MMU的32位處理器平臺上漆弄,Linux系統(tǒng)中的物理存儲空間和虛擬存儲空間的地址范圍分別都是從0x00000000到0xFFFFFFFF,共4GB造锅,但物理存儲空間與虛擬存儲空間布局完全不同撼唾。Linux運(yùn)行在虛擬存儲空間,并負(fù)責(zé)把系統(tǒng)中實(shí)際存在的遠(yuǎn)小于4GB的物理內(nèi)存根據(jù)不同需求映射到整個4GB的虛擬存儲空間中哥蔚。

?物理存儲空間布局

? ??Linux的物理存儲空間布局與處理器相關(guān)倒谷,詳細(xì)情況可以從處理器用戶手冊的存儲空間分布表(memory map)相關(guān)章節(jié)中查到,我們這里只列出嵌入式處理器平臺Linux物理內(nèi)存空間的一般布局糙箍。

說明:

?最大node號n不能大于MAX_NUMNODES-1渤愁。

?MAX_NUMNODES表示系統(tǒng)支持的最多node數(shù)。在ARM系統(tǒng)中倍靡,Sharp芯片最多支持16個nodes猴伶,其他芯片最多支持4個nodes。

?numnodes是當(dāng)前系統(tǒng)中實(shí)際的內(nèi)存node數(shù)塌西。

?在不支持CONFIG_DISCONTIGMEM選項(xiàng)的系統(tǒng)中他挎,只有一個內(nèi)存node。

?最大bank號m不能大于NR_BANKS-1捡需。

?NR_BANKS表示系統(tǒng)中支持的最大內(nèi)存bank數(shù)办桨,一般等于處理器的RAM片選數(shù)。在ARM系統(tǒng)中站辉,Sharp芯片最多支持16個banks呢撞,其他芯片最多支持8個banks。

?mem_init()函數(shù)會將所有節(jié)點(diǎn)的頁幀位碼表所占空間饰剥、孔洞頁描述符空間及空閑內(nèi)存頁都釋放掉殊霞。

?虛擬存儲空間布局

? ??在支持MMU的系統(tǒng)中,當(dāng)系統(tǒng)做完硬件初始化后就使能MMU功能汰蓉,這樣整個系統(tǒng)就運(yùn)行在虛擬存儲空間中绷蹲,實(shí)現(xiàn)虛擬存儲空間到物理存儲空間映射功能的是處理器的MMU,而虛擬存儲空間與5路存儲空間的映射關(guān)系則是由Linux內(nèi)核來管理的。32位系統(tǒng)中物理存儲空間占4GB空間祝钢,虛擬存儲空間同樣占4GB空間比规,Linux把物理空間中實(shí)際存在的遠(yuǎn)遠(yuǎn)小于4GB的內(nèi)存空間映射到整個4GB虛擬存儲空間中除映射I/O空間之外的全部空間,所以虛擬內(nèi)存空間遠(yuǎn)遠(yuǎn)大于物理內(nèi)存空間拦英,這就說同一塊物理內(nèi)存可能映射到多處虛擬內(nèi)存地址空間上蜒什,這正是Linux內(nèi)存管理職責(zé)所在。

說明:

?線性地址空間:是指Linux系統(tǒng)中從0x00000000到0xFFFFFFFF整個4GB虛擬存儲空間疤估。


?內(nèi)核空間:內(nèi)核空間表示運(yùn)行在處理器最高級別的超級用戶模式(supervisor mode)下的代碼或數(shù)據(jù)灾常,內(nèi)核空間占用從0xC000000到0xFFFFFFFF的1GB線性地址空間,內(nèi)核線性地址空間由所有進(jìn)程共享做裙,但只有運(yùn)行在內(nèi)核態(tài)的進(jìn)程才能訪問岗憋,用戶進(jìn)程可以通過系統(tǒng)調(diào)用切換到內(nèi)核態(tài)訪問內(nèi)核空間,進(jìn)程運(yùn)行在內(nèi)核態(tài)時所產(chǎn)生的地址都屬于內(nèi)核空間锚贱。


?用戶空間:用戶空間占用從0x00000000到0xBFFFFFFF共3GB的線性地址空間,每個進(jìn)程都有一個獨(dú)立的3GB用戶空間关串,所以用戶空間由每個進(jìn)程獨(dú)有拧廊,但是內(nèi)核線程沒有用戶空間,因?yàn)樗划a(chǎn)生用戶空間地址晋修。另外子進(jìn)程共享(繼承)父進(jìn)程的用戶空間只是使用與父進(jìn)程相同的用戶線性地址到物理內(nèi)存地址的映射關(guān)系吧碾,而不是共享父進(jìn)程用戶空間。運(yùn)行在用戶態(tài)和內(nèi)核態(tài)的進(jìn)程都可以訪問用戶空間墓卦。


?內(nèi)核邏輯地址空間:是指從PAGE_OFFSET到high_memory之間的線性地址空間倦春,是系統(tǒng)物理內(nèi)存映射區(qū),它映射了全部或部分(如果系統(tǒng)包含高端內(nèi)存)物理內(nèi)存落剪。內(nèi)核邏輯地址空間與圖18-4中的系統(tǒng)RAM內(nèi)存物理地址空間是一一對應(yīng)的(包括內(nèi)存孔洞也是一一對應(yīng)的)睁本,內(nèi)核邏輯地址空間中的地址與RAM內(nèi)存物理地址空間中對應(yīng)的地址只差一個固定偏移量,如果RAM內(nèi)存物理地址空間從0x00000000地址編址忠怖,那么這個偏移量就是PAGE_OFFSET呢堰。


?低端內(nèi)存:內(nèi)核邏輯地址空間所映射物理內(nèi)存就是低端內(nèi)存,低端內(nèi)存在Linux線性地址空間中始終有永久的一一對應(yīng)的內(nèi)核邏輯地址凡泣,系統(tǒng)初始化過程中將低端內(nèi)存永久映射到了內(nèi)核邏輯地址空間枉疼,為低端內(nèi)存建立了虛擬映射頁表。低端內(nèi)存內(nèi)物理內(nèi)存的物理地址與線性地址之間的轉(zhuǎn)換可以通過__pa(x)和__va(x)兩個宏來進(jìn)行鞋拟,__pa(x)將內(nèi)核邏輯地址空間的地址x轉(zhuǎn)換成對應(yīng)的物理地址骂维,相當(dāng)于__virt_to_phys((unsigned long)(x)),__va(x)則相反贺纲,把低端物理內(nèi)存空間的地址轉(zhuǎn)換成對應(yīng)的內(nèi)核邏輯地址航闺,相當(dāng)于((void *)__phys_to_virt((unsigned long)(x)))。


?高端內(nèi)存:低端內(nèi)存地址之上的物理內(nèi)存是高端內(nèi)存哮笆,高端內(nèi)存在Linux線性地址空間中沒有沒有固定的一一對應(yīng)的內(nèi)核邏輯地址来颤,系統(tǒng)初始化過程中不會為這些內(nèi)存建立映射頁表將其固定映射到Linux線性地址空間汰扭,而是需要使用高端內(nèi)存的時候才為分配的高端物理內(nèi)存建立映射頁表,使其能夠被內(nèi)核使用福铅,否則不能被使用萝毛。高端內(nèi)存的物理地址于現(xiàn)行地址之間的轉(zhuǎn)換不能使用上面的__pa(x)和__va(x)宏。


?高端內(nèi)存概念的由來:如上所述滑黔,Linux將4GB的線性地址空間劃分成兩部分笆包,從0x00000000到0xBFFFFFFF共3GB空間作為用戶空間由用戶進(jìn)程獨(dú)占,這部分線性地址空間并沒有固定映射到物理內(nèi)存空間上略荡;從0xC0000000到0xFFFFFFFF的第4GB線性地址空間作為內(nèi)核空間庵佣,在嵌入式系統(tǒng)中,這部分線性地址空間除了映射物理內(nèi)存空間之外還要映射處理器內(nèi)部外設(shè)寄存器空間等I/O空間汛兜。0xC0000000~high_memory之間的內(nèi)核邏輯地址空間專用來固定映射系統(tǒng)中的物理內(nèi)存巴粪,也就是說0xC0000000~high_memory之間空間大小與系統(tǒng)的物理內(nèi)存空間大小是相同的(當(dāng)然在配置了CONFIG_DISCONTIGMEMD選項(xiàng)的非連續(xù)內(nèi)存系統(tǒng)中,內(nèi)核邏輯地址空間和物理內(nèi)存空間一樣可能存在內(nèi)存孔洞)粥谬,如果系統(tǒng)中的物理內(nèi)存容量遠(yuǎn)小于1GB肛根,那么內(nèi)核現(xiàn)行地址空間中內(nèi)核邏輯地址空間之上的high_memory~0xFFFFFFFF之間還有足夠的空間來固定映射一些I/O空間÷┎撸可是派哲,如果系統(tǒng)中的物理內(nèi)存容量(包括內(nèi)存孔洞)小于1GB,那么就沒有足夠的內(nèi)核線性地址空間來固定映射系統(tǒng)全部物理內(nèi)存以及一些I/O空間了掺喻,為了解決這個問題芭届,在x86處理器平臺設(shè)置了一個經(jīng)驗(yàn)值:896MB,就是說感耙,如果系統(tǒng)中的物理內(nèi)存(包括內(nèi)存孔洞)大于896MB褂乍,那么將前896MB物理內(nèi)存固定映射到內(nèi)核邏輯地址空間0xC0000000~0xC0000000+896MB(=high_memory)上,而896MB之后的物理內(nèi)存則不建立到內(nèi)核線性地址空間的固定映射抑月,這部分內(nèi)存就叫高端物理內(nèi)存树叽。此時內(nèi)核線性地址空間high_memory~0xFFFFFFFF之間的128MB空間就稱為高端內(nèi)存線性地址空間,用來映射高端物理內(nèi)存和I/O空間谦絮。896MB是x86處理器平臺的經(jīng)驗(yàn)值题诵,留了128MB線性地址空間來映射高端內(nèi)存以及I/O地址空間,我們在嵌入式系統(tǒng)中可以根據(jù)具體情況修改這個閾值层皱,比如性锭,MIPS中將這個值設(shè)置為0x20000000B(512MB),那么只有當(dāng)系統(tǒng)中的物理內(nèi)存空間容量大于0x20000000B時叫胖,內(nèi)核才需要配置CONFIG_HIGHMEM選項(xiàng)草冈,使能內(nèi)核對高端內(nèi)存的分配和映射功能。什么情況需要劃分出高端物理內(nèi)存以及高端物理內(nèi)存閾值的設(shè)置原則見上面的內(nèi)存頁區(qū)(zone)概念說明。


?高端線性地址空間:從high_memory到0xFFFFFFFF之間的線性地址空間屬于高端線性地址空間怎棱,其中VMALLOC_START~VMALLOC_END之間線性地址被vmalloc()函數(shù)用來分配物理上不連續(xù)但線性地址空間連續(xù)的高端物理內(nèi)存哩俭,或者被vmap()函數(shù)用來映射高端或低端物理內(nèi)存,或者由ioremap()函數(shù)來重新映射I/O物理空間拳恋。PKMAP_BASE開始的LAST_PKMAP(一般等于1024)頁線性地址空間被kmap()函數(shù)用來永久映射高端物理內(nèi)存凡资。FIXADDR_START開始的KM_TYPE_NR*NR_CPUS頁線性地址空間被kmap_atomic()函數(shù)用來臨時映射高端物理內(nèi)存,其他未用高端線性地址空間可以用來在系統(tǒng)初始化期間永久映射I/O地址空間谬运。




?嵌入式系統(tǒng)中如何訪問I/O資源

? ??幾乎每一種外設(shè)都是通過讀寫設(shè)備上的寄存器來進(jìn)行的隙赁,通常包括控制寄存器、狀態(tài)寄存器和數(shù)據(jù)寄存器三大類梆暖,外設(shè)的寄存器通常被連續(xù)地編址伞访。根據(jù)CPU體系結(jié)構(gòu)的不同,CPU對IO端口的編址方式有兩種:

?I/O映射方式(I/O-mapped)

  典型地轰驳,如X86處理器為外設(shè)專門實(shí)現(xiàn)了一個單獨(dú)的地址空間厚掷,稱為"I/O地址空間"或者"I/O端口空間",CPU通過專門的I/O指令(如X86的IN和OUT指令)來訪問這一空間中的地址單元级解。

?內(nèi)存映射方式(Memory-mapped)

  RISC指令系統(tǒng)的CPU(如ARM蝗肪、PowerPC等)通常只實(shí)現(xiàn)一個物理地址空間,外設(shè)I/O端口成為內(nèi)存的一部分蠕趁。此時,CPU可以象訪問一個內(nèi)存單元那樣訪問外設(shè)I/O端口辛馆,而不需要設(shè)立專門的外設(shè)I/O指令俺陋。

  但是,這兩者在硬件實(shí)現(xiàn)上的差異對于軟件來說是完全透明的昙篙,驅(qū)動程序開發(fā)人員可以將內(nèi)存映射方式的I/O端口和外設(shè)內(nèi)存統(tǒng)一看作是"I/O內(nèi)存"資源腊状。

  一般來說,在系統(tǒng)運(yùn)行時苔可,外設(shè)的I/O內(nèi)存資源的物理地址是已知的缴挖,由硬件的設(shè)計決定。但是CPU通常并沒有為這些已知的外設(shè)I/O內(nèi)存資源的物理地址預(yù)定義虛擬地址范圍焚辅,驅(qū)動程序并不能直接通過物理地址訪問I/O內(nèi)存資源映屋,而必須將它們映射到核心虛地址空間內(nèi)(通過頁表),然后才能根據(jù)映射所內(nèi)指令訪問這些I/O得到的核心虛地址范圍同蜻,通過訪內(nèi)存資源棚点。Linux在io.h頭文件中聲明了函數(shù)ioremap(),用來將I/O內(nèi)存資源的物理地址映射到核心虛地址空間(3GB-4GB)中湾蔓,原型如下:



void* ioremap(unsignedlongphys_addr, unsignedlongsize, unsignedlongflags);


iounmap函數(shù)用于取消ioremap()所做的映射瘫析,原型如下:

voidiounmap(void* addr);

這兩個函數(shù)都是實(shí)現(xiàn)在mm/ioremap.c文件中。

  在將I/O內(nèi)存資源的物理地址映射成核心虛地址后,理論上講我們就可以象讀寫RAM那樣直接讀寫I/O內(nèi)存資源了贬循。為了保證驅(qū)動程序的跨平臺的可移植性咸包,我們應(yīng)該使用Linux中特定的函數(shù)來訪問I/O內(nèi)存資源,而不應(yīng)該通過指向核心虛地址的指針來訪問杖虾。如在x86平臺上烂瘫,讀寫I/O的函數(shù)如下所示:

#definereadb(addr) (*(volatile unsigned char *) __io_virt(addr))#definereadw(addr) (*(volatile unsigned short *) __io_virt(addr))#definereadl(addr) (*(volatile unsigned int *) __io_virt(addr))#definewriteb(b,addr) (*(volatile unsigned char *) __io_virt(addr) = (b))#definewritew(b,addr) (*(volatile unsigned short *) __io_virt(addr) = (b))#definewritel(b,addr) (*(volatile unsigned int *) __io_virt(addr) = (b))#definememset_io(a,b,c) memset(__io_virt(a),(b),(c))#definememcpy_fromio(a,b,c) memcpy((a),__io_virt(b),(c))#definememcpy_toio(a,b,c) memcpy(__io_virt(a),(b),(c))

  最后,我們要特別強(qiáng)調(diào)驅(qū)動程序中mmap函數(shù)的實(shí)現(xiàn)方法亏掀。用mmap映射一個設(shè)備忱反,意味著使用戶空間的一段地址關(guān)聯(lián)到設(shè)備內(nèi)存上,這使得只要程序在分配的地址范圍內(nèi)進(jìn)行讀取或者寫入滤愕,實(shí)際上就是對設(shè)備的訪問温算。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市间影,隨后出現(xiàn)的幾起案子注竿,更是在濱河造成了極大的恐慌,老刑警劉巖魂贬,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件巩割,死亡現(xiàn)場離奇詭異,居然都是意外死亡付燥,警方通過查閱死者的電腦和手機(jī)宣谈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來键科,“玉大人闻丑,你說我怎么就攤上這事⊙保” “怎么了嗦嗡?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長饭玲。 經(jīng)常有香客問我侥祭,道長,這世上最難降的妖魔是什么茄厘? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任矮冬,我火速辦了婚禮,結(jié)果婚禮上蚕断,老公的妹妹穿的比我還像新娘欢伏。我一直安慰自己,他們只是感情好亿乳,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布硝拧。 她就那樣靜靜地躺著径筏,像睡著了一般。 火紅的嫁衣襯著肌膚如雪障陶。 梳的紋絲不亂的頭發(fā)上滋恬,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機(jī)與錄音抱究,去河邊找鬼恢氯。 笑死,一個胖子當(dāng)著我的面吹牛鼓寺,可吹牛的內(nèi)容都是我干的勋拟。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼妈候,長吁一口氣:“原來是場噩夢啊……” “哼敢靡!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起苦银,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤啸胧,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后幔虏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體纺念,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年想括,在試婚紗的時候發(fā)現(xiàn)自己被綠了陷谱。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡瑟蜈,死狀恐怖叭首,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情踪栋,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布图毕,位于F島的核電站夷都,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏予颤。R本人自食惡果不足惜囤官,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蛤虐。 院中可真熱鬧党饮,春花似錦、人聲如沸驳庭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蹲堂,卻和暖如春狼讨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背柒竞。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工政供, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人朽基。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓布隔,卻偏偏與公主長得像,于是被迫代替她去往敵國和親稼虎。 傳聞我的和親對象是個殘疾皇子衅檀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評論 2 355

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