IPC之Binder

基本上參考Android跨進(jìn)程通信:圖文詳解 Binder機(jī)制 原理再結(jié)合自己的理解記錄本次學(xué)習(xí)

Binder總結(jié)

Binder驅(qū)動(dòng)

全部流程表

接下來(lái)就來(lái)理解并扒一下其中的細(xì)節(jié)

什么是進(jìn)程間通訊,為什么要搞一個(gè)Binder機(jī)制

一個(gè)進(jìn)程空間分為 用戶空間和內(nèi)核空間(kernel)

用戶空間:數(shù)據(jù)不可共享=不可共享空間

內(nèi)核空間:數(shù)據(jù)可共享=可共享空間

所有進(jìn)程共用1各內(nèi)核空間

內(nèi)核空間咽瓷、用戶空間、內(nèi)核態(tài)寒矿、用戶態(tài)

對(duì)于32位操作系統(tǒng)而言国裳,它的尋址空間(虛擬地址空間)為4G。操作系統(tǒng)將虛擬地址空間劃分為兩部分、一部分內(nèi)核空間(最高1G字節(jié))弃甥,一部分用戶空間(3G字節(jié))

內(nèi)核態(tài):當(dāng)進(jìn)程運(yùn)行在內(nèi)核空間,CPU執(zhí)行任何指令汁讼,可以自由的訪問(wèn)任何有效地址

用戶態(tài):當(dāng)進(jìn)程運(yùn)行在用戶空間淆攻,只能范文映射其地址空間的頁(yè)表項(xiàng)中規(guī)定的用戶態(tài)下可訪問(wèn)頁(yè)面的虛擬地址

為什么要區(qū)分內(nèi)核空間與用戶空間

CPU指令分為特權(quán)指令和非特權(quán)指令,對(duì)于危險(xiǎn)的指令嘿架,比如清內(nèi)存等瓶珊,這種指令只允許操作系統(tǒng)及其相關(guān)模塊使用,普通應(yīng)用只能使用普通指令耸彪,所以Ring3級(jí)別被運(yùn)行在用戶態(tài)伞芹,Ring0級(jí)別被成為運(yùn)行在內(nèi)核態(tài)

用戶空間與內(nèi)核空間的交互

進(jìn)程內(nèi)兩個(gè)空間的交互需要通過(guò)系統(tǒng)調(diào)用,主要函數(shù)

copy_from_user():將用戶空間的數(shù)據(jù)拷貝到內(nèi)核空間

copy_to_user():將內(nèi)核空間的數(shù)據(jù)拷貝到用戶空間

進(jìn)程隔離&跨進(jìn)程通訊(IPC)

進(jìn)程間傳遞數(shù)據(jù)必須要經(jīng)過(guò)內(nèi)核空間而 發(fā)送到內(nèi)核 和從內(nèi)核拿出給另一個(gè)進(jìn)程時(shí)需要兩次數(shù)據(jù)的拷貝

Binder的優(yōu)勢(shì)

binder機(jī)制則只需要1次數(shù)據(jù)拷貝蝉娜,它通過(guò)Binder驅(qū)動(dòng)負(fù)責(zé)管理數(shù)據(jù)接受關(guān)村唱较,原理是內(nèi)存映射mmap系統(tǒng)調(diào)用、它連接兩個(gè)進(jìn)程召川,實(shí)現(xiàn)了mmap()系統(tǒng)調(diào)用南缓,主要負(fù)責(zé)創(chuàng)建數(shù)據(jù)接收的緩沖空間&管理數(shù)據(jù)接收緩存

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

(memory map)含義

關(guān)聯(lián)進(jìn)程中的1個(gè)虛擬內(nèi)存區(qū)域 & 1個(gè)磁盤(pán)上的對(duì)象,使二者存在映射關(guān)系

這樣如果從緩沖區(qū)中取數(shù)據(jù)扮宠,就相當(dāng)于讀文件中的相應(yīng)字節(jié)西乖,而將數(shù)據(jù)存入緩沖區(qū)狐榔,就相當(dāng)于寫(xiě)文件中的相應(yīng)字節(jié),這樣不需要read和write也能直接之心I/O了

就是操作內(nèi)存就可以操作磁盤(pán)中的對(duì)象了

示意圖

如果多個(gè)進(jìn)程虛擬內(nèi)存區(qū)域和同1個(gè)共享對(duì)象获雕,簡(jiǎn)歷映射關(guān)系后薄腻,若1個(gè)進(jìn)程對(duì)該虛擬區(qū)域進(jìn)行寫(xiě)操作,那么對(duì)于也把共享對(duì)象映射到其自身虛擬內(nèi)存區(qū)域的進(jìn)程也是可見(jiàn)的

實(shí)現(xiàn)過(guò)程

mmap()的返回值是內(nèi)存映射在用戶空間的地址

該函數(shù)的作用 = 創(chuàng)建虛擬內(nèi)存區(qū)域 + 與共享對(duì)象建立映射關(guān)系

/** * 函數(shù)原型 */

void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);

/** * 具體使用(用戶進(jìn)程調(diào)用mmap())

? * 下述代碼即常見(jiàn)了一片大小 = MAP_SIZE的接收緩存區(qū)

? & 關(guān)聯(lián)到共享對(duì)象中(即建立映射) */

fd = open("/dev/binder", O_RDWR);

mmap(NULL, MAP_SIZE, PROT_READ, MAP_PRIVATE, fd, 0);

? /** * 內(nèi)部原理 *

? 步驟1:創(chuàng)建虛擬內(nèi)存區(qū)域 *

? 步驟2:實(shí)現(xiàn)地址映射關(guān)系届案,即:進(jìn)程的虛擬地址空間 ->> 共享對(duì)象

? * 注: * a. 此時(shí)庵楷,該虛擬地址并沒(méi)有任何數(shù)據(jù)關(guān)聯(lián)到文件中,僅僅只是建立映射關(guān)系

? * b. 當(dāng)其中1個(gè)進(jìn)程對(duì)虛擬內(nèi)存寫(xiě)入數(shù)據(jù)時(shí)楣颠,則真正實(shí)現(xiàn)了數(shù)據(jù)的可見(jiàn)

? */

具體工作流程

Binder 模型

模型原理圖

基于CS模型即Client-Server 模式

模型組成角色說(shuō)明

角色作用備注

Client 進(jìn)程使用服務(wù) 的進(jìn)程Andoird 客戶端 各種App

Server 進(jìn)程提供服務(wù) 的進(jìn)程服務(wù)端 System_server

ServiceManager進(jìn)程管理Service查找和注冊(cè)服務(wù)

(將字符形式的Binder名字 轉(zhuǎn)化成Client中對(duì)該Binder 的引用)

init進(jìn)程啟動(dòng)的進(jìn)程尽纽,作為Binder IPC通訊的守護(hù)進(jìn)程

功能類似路由器

Binder 驅(qū)動(dòng)一種虛擬設(shè)備驅(qū)動(dòng),是連接Service進(jìn)程童漩、Client進(jìn)程和ServiceManager進(jìn)程的橋梁弄贿,它們之間的交互(使用open和ioctl文件操作函數(shù))而非直接交互

1.傳遞進(jìn)程間的數(shù)據(jù):通過(guò)內(nèi)存映射

2.實(shí)現(xiàn)線程控制:采用Binder的線程池,并由Binder驅(qū)動(dòng)自身進(jìn)行管理

Binder驅(qū)動(dòng)持有每個(gè)Service進(jìn)程在內(nèi)核空間中的Binder實(shí)體矫膨,并給Client進(jìn)程提供Binder實(shí)體的引用Proxy

模型原理步驟說(shuō)明

簡(jiǎn)單總結(jié)

注冊(cè)服務(wù)

系統(tǒng)Server服務(wù)進(jìn)程在啟動(dòng)時(shí)會(huì)先把所有服務(wù)注冊(cè)到ServiceManager進(jìn)程

獲取服務(wù)

Client進(jìn)程發(fā)起請(qǐng)求傳入獲取的服務(wù)名-》Binder驅(qū)動(dòng)將請(qǐng)求-》SeviceManager進(jìn)程找到所需服務(wù)后通過(guò)Binder驅(qū)動(dòng)返回給Client進(jìn)程差凹,此時(shí)返回的是代理對(duì)象 除非Client與Server在同一進(jìn)程

使用服務(wù)

Binder驅(qū)動(dòng):為跨進(jìn)程做準(zhǔn)備實(shí)現(xiàn)內(nèi)存映射(根據(jù)ServiceManager進(jìn)程里的Service信息找到對(duì)應(yīng)的Server進(jìn)程,實(shí)現(xiàn)內(nèi)核緩存區(qū) 和 Server 進(jìn)程用戶空間地址 同時(shí)映射到 同1個(gè)接收緩存區(qū)中)

Client進(jìn)程:將參數(shù)寫(xiě)入Parcel對(duì)象中打包(序列化)侧馅,通過(guò)BinderProxy的transact()將數(shù)據(jù)發(fā)送內(nèi)核緩存區(qū)(此時(shí)Binder驅(qū)動(dòng)由于存在映射關(guān)系相當(dāng)于給到Binder驅(qū)動(dòng))危尿,等待Server返回replay,并掛起Client當(dāng)前線程

Sever進(jìn)程:收到驅(qū)動(dòng)通知后馁痴,調(diào)用Binder對(duì)象的onTransact()將Parcel解包(反序列化)并執(zhí)行要client要調(diào)用目標(biāo)方法并返回replay谊娇,隨后把replay返回給Client,此時(shí)Client線程被喚醒 完成了一次服務(wù)的使用

流程如下圖

獲取服務(wù)

Client獲取服務(wù)時(shí)罗晕,會(huì)去ServiceManager獲取服務(wù)名對(duì)應(yīng)的IBinder济欢,隨后通過(guò)asInterface獲取服務(wù)

static publicINotificationManagergetService()

? ? {

if (sService!= null) {

returnsService;

? ? ? ? }

IBinderb=ServiceManager.getService("notification");

sService=INotificationManager.Stub.asInterface(b);

returnsService;

? ? }

而asInterface會(huì)去獲本地對(duì)象,否則就給到Binder代理類

? ? public static BookManager asInterface(IBinder binder){

? ? ? ? if (binder == null)

? ? ? ? ? ? return null;

? ? ? ? //尋找Binder本地對(duì)象

IInterface iin = binder.queryLocalInterface(DESCRIPTOR);

? ? ? ? if (iin != null && iin instanceof BookManager){

? ? ? ? ? ? return (BookManager) iin;

? ? ? ? }

? ? ? ? return new Proxy(binder);

/**

? ? ? ? * 如果server端(service所在的進(jìn)程)和client端處于同一個(gè)進(jìn)程 那么此時(shí)不需要跨進(jìn)程通信 直接調(diào)用Stub的方法即可(Stub實(shí)例化時(shí)已經(jīng)實(shí)現(xiàn)了具體的方法)

? ? ? ? * 反之攀例,則返回proxy對(duì)象? 從構(gòu)造方法看 該對(duì)象持有著遠(yuǎn)程Binder引用? 如果調(diào)用Stub.proxy接口 那么將會(huì)是IPC調(diào)用? 即通過(guò)transact方法與服務(wù)端進(jìn)行通信

? ? ? ? * 從字面意思看stub是服務(wù)端實(shí)現(xiàn)的存根(Stub工作在server進(jìn)程)船逮,

? ? ? ? * proxy則是stub的代理 proxy工作在client進(jìn)程

? ? ? ? */

? ? }

使用服務(wù)

步驟1: Client進(jìn)程 將參數(shù)(整數(shù)a和b)發(fā)送到Server進(jìn)程

// 1. Client進(jìn)程 將需要傳送的數(shù)據(jù)寫(xiě)入到Parcel對(duì)象中

// data = 數(shù)據(jù) = 目標(biāo)方法的參數(shù)(Client進(jìn)程傳進(jìn)來(lái)的,此處就是整數(shù)a和b) + IInterface接口對(duì)象的標(biāo)識(shí)符descriptor

? android.os.Parcel data = android.os.Parcel.obtain();

? data.writeInt(a);

? data.writeInt(b);

? data.writeInterfaceToken("add two int");粤铭;

? // 方法對(duì)象標(biāo)識(shí)符讓Server進(jìn)程在Binder對(duì)象中根據(jù)"add two int"通過(guò)queryLocalIInterface()查找相應(yīng)的IInterface對(duì)象(即Server創(chuàng)建的plus)挖胃,Client進(jìn)程需要調(diào)用的相加方法就在該對(duì)象中

? android.os.Parcel reply = android.os.Parcel.obtain();

? // reply:目標(biāo)方法執(zhí)行后的結(jié)果(此處是相加后的結(jié)果)

// 2. 通過(guò) 調(diào)用代理對(duì)象的transact() 將 上述數(shù)據(jù)發(fā)送到Binder驅(qū)動(dòng)

? binderproxy.transact(Stub.add, data, reply, 0)

? // 參數(shù)說(shuō)明:

? ? // 1. Stub.add:目標(biāo)方法的標(biāo)識(shí)符(Client進(jìn)程 和 Server進(jìn)程 自身約定,可為任意)

? ? // 2. data :上述的Parcel對(duì)象

? ? // 3. reply:返回結(jié)果

? ? // 0:可不管

// 注:在發(fā)送數(shù)據(jù)后梆惯,Client進(jìn)程的該線程會(huì)暫時(shí)被掛起

// 所以酱鸭,若Server進(jìn)程執(zhí)行的耗時(shí)操作,請(qǐng)不要使用主線程垛吗,以防止ANR

// 3. Binder驅(qū)動(dòng)根據(jù) 代理對(duì)象 找到對(duì)應(yīng)的真身Binder對(duì)象所在的Server 進(jìn)程(系統(tǒng)自動(dòng)執(zhí)行)

// 4. Binder驅(qū)動(dòng)把 數(shù)據(jù) 發(fā)送到Server 進(jìn)程中凹髓,并通知Server 進(jìn)程執(zhí)行解包(系統(tǒng)自動(dòng)執(zhí)行)

步驟2:Server進(jìn)程根據(jù)Client進(jìn)要求 調(diào)用 目標(biāo)方法(即加法函數(shù))

// 1. 收到Binder驅(qū)動(dòng)通知后,Server 進(jìn)程通過(guò)回調(diào)Binder對(duì)象onTransact()進(jìn)行數(shù)據(jù)解包 & 調(diào)用目標(biāo)方法

? public class Stub extends Binder {

? ? ? ? ? // 復(fù)寫(xiě)onTransact()

? ? ? ? ? @Override

? ? ? ? ? boolean onTransact(int code, Parcel data, Parcel reply, int flags){

? ? ? ? ? // code即在transact()中約定的目標(biāo)方法的標(biāo)識(shí)符

? ? ? ? ? switch (code) {

? ? ? ? ? ? ? ? case Stub.add: {

? ? ? ? ? ? ? ? ? // a. 解包Parcel中的數(shù)據(jù)

? ? ? ? ? ? ? ? ? ? ? data.enforceInterface("add two int");

? ? ? ? ? ? ? ? ? ? ? ? // a1. 解析目標(biāo)方法對(duì)象的標(biāo)識(shí)符

? ? ? ? ? ? ? ? ? ? ? int? arg0? = data.readInt();

? ? ? ? ? ? ? ? ? ? ? int? arg1? = data.readInt();

? ? ? ? ? ? ? ? ? ? ? // a2. 獲得目標(biāo)方法的參數(shù)


? ? ? ? ? ? ? ? ? ? ? // b. 根據(jù)"add two int"通過(guò)queryLocalIInterface()獲取相應(yīng)的IInterface對(duì)象(即Server創(chuàng)建的plus)的引用怯屉,通過(guò)該對(duì)象引用調(diào)用方法

? ? ? ? ? ? ? ? ? ? ? int? result = this.queryLocalIInterface("add two int") .add( arg0,? arg1);


? ? ? ? ? ? ? ? ? ? ? ? // c. 將計(jì)算結(jié)果寫(xiě)入到reply

? ? ? ? ? ? ? ? ? ? ? ? reply.writeInt(result);


? ? ? ? ? ? ? ? ? ? ? ? return true;

? ? ? ? ? ? ? ? ? }

? ? ? ? ? }

? ? ? return super.onTransact(code, data, reply, flags);

? ? ? // 2. 將結(jié)算結(jié)果返回 到Binder驅(qū)動(dòng)

步驟3:Server進(jìn)程 將目標(biāo)方法的結(jié)果(即加法后的結(jié)果)返回給Client進(jìn)程

? // 1. Binder驅(qū)動(dòng)根據(jù) 代理對(duì)象 沿原路 將結(jié)果返回 并通知Client進(jìn)程獲取返回結(jié)果

? // 2. 通過(guò)代理對(duì)象 接收結(jié)果(之前被掛起的線程被喚醒)

? ? binderproxy.transact(Stub.ADD, data, reply, 0)蔚舀;

? ? reply.readException();饵沧;

? ? result = reply.readInt();

? ? ? ? ? }

}

Binder驅(qū)動(dòng)加載過(guò)程中有哪些重要步驟

優(yōu)點(diǎn)

對(duì)比 Linux (Android基于Linux)上的其他進(jìn)程通信方式(管道赌躺、消息隊(duì)列狼牺、共享內(nèi)存、

信號(hào)量礼患、Socket)是钥,Binder 機(jī)制的優(yōu)點(diǎn)有:

IBinder、BpBinder缅叠、BBinder悄泥、Stub、IInterface

名稱描述

IBinder一個(gè)接口類肤粱,代表了一種跨進(jìn)程通訊的能力弹囚,實(shí)現(xiàn)這個(gè)接口,這個(gè)對(duì)象就能跨進(jìn)程傳輸

BpBinder代理Binder狼犯,當(dāng)clicnt調(diào)用service后余寥,會(huì)得到一個(gè)BpXXXService,它將str參數(shù)打包到Parcel中悯森,然后調(diào)用remote()->transact,remote()返回的就是一個(gè)BpBinder,所以實(shí)際上調(diào)用的是BpBinder的transact

BBinder服務(wù)端Binder绪撵,當(dāng)Service接收到client請(qǐng)求后瓢姻,會(huì)調(diào)用BBinder的taransact方法會(huì)調(diào)回子類實(shí)現(xiàn)的虛擬方法onTransact,該方法實(shí)現(xiàn)是在BnXXXservice中實(shí)現(xiàn)音诈,所以BBinder就是接受傳遞過(guò)來(lái)的信息幻碱,解包數(shù)據(jù),并調(diào)用XXXservice真正的實(shí)現(xiàn)

IInerfaceAIDL文件中定義的接口细溅,表示Server進(jìn)程對(duì)象具備哪些能力

Stub一個(gè)抽象類褥傍,其中由asInterface和onTransact關(guān)鍵函數(shù)組成

其中asInterface 傳入binder對(duì)象,如果同一進(jìn)程

序列化與反序列化

為什么要序列化與反序列化喇聊?

因?yàn)閷?duì)象內(nèi)的各種數(shù)據(jù)不能直接跨進(jìn)程傳遞恍风,所以需要將java對(duì)象轉(zhuǎn)換成字節(jié)序列(序列化)等到了接收方便要從字節(jié)序列中恢復(fù)出Java對(duì)象(反序列化)

序列化有哪些好處?

實(shí)現(xiàn)了數(shù)據(jù)的持久化誓篱,通過(guò)序列化可以把數(shù)據(jù)永久的保存在硬盤(pán)上

Serializable與Parcelable的區(qū)別

SerializableParcelable

原理通過(guò)I/O讀寫(xiě)存儲(chǔ)再磁盤(pán)上朋贬,同各國(guó)反射解析出對(duì)象描述、屬性的描述窜骄,以HandleTable 來(lái)解析存儲(chǔ)信息锦募,然后生成二進(jìn)制、存儲(chǔ)邻遏、傳輸主要用于Binder傳輸糠亩,將數(shù)據(jù)寫(xiě)入共享內(nèi)存虐骑,其他進(jìn)程通過(guò)Parcel可以從這塊共享內(nèi)存中讀出字節(jié)流

存儲(chǔ)介質(zhì)使用I/O讀寫(xiě)存儲(chǔ)在硬盤(pán)上直接在內(nèi)存中讀取,內(nèi)存中的結(jié)構(gòu)是一塊連續(xù)的內(nèi)存赎线,會(huì)根據(jù)需要的內(nèi)存大小自動(dòng)擴(kuò)展

來(lái)源JavaAndroid

效率通過(guò)反射富弦,需要大量的I/O操作自己實(shí)現(xiàn)封送和解封,效率更快

使用序列化:

要?jiǎng)?chuàng)建某些OutputStream對(duì)象

將其封裝到ObjectOutputStream對(duì)象內(nèi)

此后只需調(diào)用writeObject()即可完成對(duì)象的序列化

忘記關(guān)閉資源:objectOutputStream.close(), outputStream .close();

反序列化:

通過(guò)readObject()獲取資源

通過(guò)IPC傳遞的對(duì)象都要繼承于Parcelable接口氛驮,并實(shí)現(xiàn) writeToParcel腕柜,它會(huì)獲取對(duì)象的當(dāng)前狀態(tài)并將其寫(xiě)入 Parcel。為類添加CREATOR靜態(tài)字段矫废,該字段是實(shí)現(xiàn)Parcelable.Creator接口的對(duì)象盏缤。最后,創(chuàng)建聲明 Parcelable 類的.aidl文件

Binder中ServiceManager的作用

ServiceManage使用客戶端可以獲取binder實(shí)例對(duì)象的引用

AIDL

什么是AIDL

AIDL是Android提供的接口定義語(yǔ)言蓖扑,簡(jiǎn)化Binder的使用唉铜,會(huì)生成一個(gè)服務(wù)代理端對(duì)象的代理類,可以理解成服務(wù)端代碼律杠,與Client客戶端中要鏈接的binder相關(guān)如服務(wù)連接asInterface潭流、transact、序列化柜去,以及支持IPC的目標(biāo)方法等

使用步驟

(1)建立aidl的服務(wù)方:

a.建立一個(gè)含有activity的service,其實(shí)也可以直接建立一個(gè)service

b.建立aidl文件灰嫉,聲明接口以及方法,建立完成后ADT會(huì)自動(dòng)生成一個(gè)aild接口的實(shí)現(xiàn)java文件,在gen下面.

c.建立service繼承類嗓奢,內(nèi)部實(shí)現(xiàn)aidl的stub.且在onbind中進(jìn)行返回.

b.AndroidManifest.xml文件中配置AIDL服務(wù)讼撒,需要注意的是<action>標(biāo)簽中android:name的屬性值就是客戶端要引用該服務(wù)的ID,也就是Intent類的參數(shù)值股耽。

(2)建立客戶斷完成跨進(jìn)程的調(diào)用.

a.建立android project內(nèi)部會(huì)自動(dòng)創(chuàng)建一個(gè)activity根盒,在activity中bind服務(wù).bind服務(wù)成功后,onServiceConnected將會(huì)回調(diào)返回給service給定的ibind.

b.onServiceConnected根據(jù)返回的內(nèi)容物蝙,實(shí)現(xiàn)跨進(jìn)程的調(diào)用.

參考文章:

https://blog.csdn.net/carson_ho/article/details/73560642

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末炎滞,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子诬乞,更是在濱河造成了極大的恐慌册赛,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,946評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件丽惭,死亡現(xiàn)場(chǎng)離奇詭異击奶,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)责掏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,336評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)柜砾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人换衬,你說(shuō)我怎么就攤上這事痰驱≈ぐ牛” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,716評(píng)論 0 364
  • 文/不壞的土叔 我叫張陵担映,是天一觀的道長(zhǎng)废士。 經(jīng)常有香客問(wèn)我,道長(zhǎng)蝇完,這世上最難降的妖魔是什么官硝? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,222評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮短蜕,結(jié)果婚禮上氢架,老公的妹妹穿的比我還像新娘。我一直安慰自己朋魔,他們只是感情好岖研,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,223評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著警检,像睡著了一般孙援。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上扇雕,一...
    開(kāi)封第一講書(shū)人閱讀 52,807評(píng)論 1 314
  • 那天拓售,我揣著相機(jī)與錄音,去河邊找鬼洼裤。 笑死邻辉,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的腮鞍。 我是一名探鬼主播,決...
    沈念sama閱讀 41,235評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼莹菱,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼移国!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起道伟,我...
    開(kāi)封第一講書(shū)人閱讀 40,189評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤迹缀,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后蜜徽,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體祝懂,經(jīng)...
    沈念sama閱讀 46,712評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,775評(píng)論 3 343
  • 正文 我和宋清朗相戀三年拘鞋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了砚蓬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,926評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡盆色,死狀恐怖灰蛙,靈堂內(nèi)的尸體忽然破棺而出祟剔,到底是詐尸還是另有隱情,我是刑警寧澤摩梧,帶...
    沈念sama閱讀 36,580評(píng)論 5 351
  • 正文 年R本政府宣布物延,位于F島的核電站,受9級(jí)特大地震影響仅父,放射性物質(zhì)發(fā)生泄漏叛薯。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,259評(píng)論 3 336
  • 文/蒙蒙 一笙纤、第九天 我趴在偏房一處隱蔽的房頂上張望耗溜。 院中可真熱鬧,春花似錦粪糙、人聲如沸强霎。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,750評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)城舞。三九已至,卻和暖如春寞酿,著一層夾襖步出監(jiān)牢的瞬間家夺,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,867評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工伐弹, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拉馋,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,368評(píng)論 3 379
  • 正文 我出身青樓惨好,卻偏偏與公主長(zhǎng)得像煌茴,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子日川,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,930評(píng)論 2 361

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