Binder解析

前言

本文參考Carson_Ho的《圖文詳解 Android Binder跨進(jìn)程通信的原理》

1 什么是Binder双藕?

說(shuō)到Binder,有些人可能會(huì)說(shuō)Binder是Android在解決進(jìn)程通信間通信的技術(shù)遂鹊,是一個(gè)類實(shí)現(xiàn)了Ibinder接口栋艳,是一個(gè)虛擬設(shè)備驅(qū)動(dòng)等等,其實(shí)這些說(shuō)法都沒(méi)有錯(cuò)戳气,如果把這些說(shuō)法歸結(jié)起來(lái)可以有以下的定義:


Binder定義.png

可以這樣說(shuō):站在不同的角度上链患,Binder有不同的定義。

2知識(shí)鋪墊

在Linux中將一個(gè)進(jìn)程空間分為兩部分:用戶空間和內(nèi)核控件瓶您。

用戶空間:用戶空間的數(shù)據(jù)不可以共享
內(nèi)核空間:內(nèi)核空間的數(shù)據(jù)可以共享

那么一個(gè)進(jìn)程中的兩部部分如何進(jìn)行通信呢?其實(shí)是有copy_from_user和copy_to_user來(lái)實(shí)現(xiàn)的麻捻。

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

那么Linux中的進(jìn)程間通信的原理可以由下圖來(lái)表示


示意圖.png

這里需要注意的是:所有的進(jìn)程共用一個(gè)內(nèi)核空間

2.1 進(jìn)程隔離和IPC

進(jìn)程隔離:為了保證進(jìn)程的獨(dú)立性&安全性,Android不允許進(jìn)程之間直接相互訪問(wèn)或通信呀袱,保證了了每一個(gè)是相互隔離贸毕,獨(dú)立的。
IPC:進(jìn)程間通信
那么IPC是如何實(shí)現(xiàn)的呢夜赵?

進(jìn)程間通信.png

進(jìn)程間的通信原理如圖所示明棍,
1.發(fā)送進(jìn)程通過(guò)系統(tǒng)調(diào)用方法copy_from_user將需要傳遞的數(shù)據(jù)拷貝到內(nèi)核空間的緩存區(qū)中。
2.內(nèi)核服務(wù)程序喚醒接收進(jìn)程的接收線程寇僧,通過(guò)系統(tǒng)調(diào)用(copy_to_user)將內(nèi)核緩存區(qū)中的數(shù)據(jù)拷貝到接收進(jìn)程的用戶空間摊腋。
3.拷貝完成沸版,實(shí)現(xiàn)了進(jìn)程間的通信。
這里要說(shuō)明的有以下兩點(diǎn):
1.進(jìn)程間無(wú)法直接進(jìn)行數(shù)據(jù)的交互兴蒸,數(shù)據(jù)的交互需要通過(guò)內(nèi)核空間進(jìn)行视粮。
2.Linux的進(jìn)程間通信調(diào)用了兩次數(shù)據(jù)拷貝的系統(tǒng)調(diào)用。
3.接收數(shù)據(jù)的緩沖區(qū)大小由接收進(jìn)程決定类咧。

缺點(diǎn):
1.接收進(jìn)程的接收緩沖區(qū)大小不定馒铃。
2.效率低下,單向數(shù)據(jù)通信需要進(jìn)行兩次數(shù)據(jù)拷貝(用戶->內(nèi)核->用戶)

2.2 Binder模型

Android為了解決Linux中進(jìn)程間通信中的缺點(diǎn)痕惋,提出了Binder模型機(jī)制区宇,該模型機(jī)制的原理如下圖所示:


Binder機(jī)制模型.png

Binder模型屬于C/S模式,各部分的說(shuō)明如下:

角色 說(shuō)明 備注
Client進(jìn)程 使用服務(wù)的進(jìn)程 Andorid客戶端
Server進(jìn)程 提供服務(wù)的進(jìn)程 服務(wù)器端
ServiceManager 管理服務(wù)進(jìn)程的注冊(cè)和查詢(將客戶端提供的Bidner字符串轉(zhuǎn)換為相應(yīng)服務(wù)的Bidner引用) 相當(dāng)于一個(gè)DNS服務(wù)器
Binder驅(qū)動(dòng) 虛擬的設(shè)備驅(qū)動(dòng)值戳,將Client進(jìn)程议谷,Server進(jìn)程和ServiceManager進(jìn)程聯(lián)系起來(lái) 具體作用:1傳遞進(jìn)程服務(wù)消息(服務(wù)進(jìn)程注冊(cè),客戶進(jìn)程獲取服務(wù))2.傳遞進(jìn)程間需要傳遞的數(shù)據(jù)堕虹,通過(guò)內(nèi)存映射3.實(shí)現(xiàn)線程控制:采用binder連接池卧晓,并由binder驅(qū)動(dòng)自身管理 binder驅(qū)動(dòng)持有所有服務(wù)進(jìn)程在內(nèi)核進(jìn)程中的binder實(shí)體,在客戶進(jìn)程使用時(shí)將對(duì)應(yīng)的binder字符串轉(zhuǎn)換為binder引用赴捞。

在Binder模型中的重要角色就是Binder驅(qū)動(dòng)逼裆,它將其余的各個(gè)部分聯(lián)系起來(lái),形成了Bidner跨進(jìn)程通信模型赦政。那么Binder驅(qū)動(dòng)是如何工作的呢胜宇?

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

定義:


Binder驅(qū)動(dòng)示意圖.png

核心原理:


binder驅(qū)動(dòng)核心原理png.png

過(guò)程說(shuō)明:
1創(chuàng)建內(nèi)核空間的數(shù)據(jù)緩沖區(qū)
2并根據(jù)需要映射的接收進(jìn)程的信息通過(guò)地址映射實(shí)現(xiàn)內(nèi)核緩沖區(qū)和接收進(jìn)程用戶空間地址映射到同一個(gè)接收緩沖區(qū)(這時(shí)只是進(jìn)行接收緩沖區(qū)的創(chuàng)建和完成地址映射,并沒(méi)有進(jìn)行數(shù)據(jù)的讀寫操作)
3.發(fā)送進(jìn)程通過(guò)copy_from_user將需要傳輸?shù)臄?shù)據(jù)發(fā)送到內(nèi)核緩沖區(qū)中
4由于內(nèi)核緩沖區(qū)和接收進(jìn)程用戶空間地址映射到了同一個(gè)接收緩沖區(qū)恢着,相當(dāng)于將信息發(fā)送到了接收進(jìn)程用戶地址空間桐愉。即實(shí)現(xiàn)了進(jìn)程間通信。

優(yōu)點(diǎn):
1.傳輸效率高掰派,單項(xiàng)通信數(shù)據(jù)拷貝次數(shù)少(1次)从诲,內(nèi)核空間與用戶空間通過(guò)共享對(duì)象直接交互。
2.為接收進(jìn)程創(chuàng)建了大小不確定的接收緩沖區(qū)靡羡。

2.2.2Binder模型工作過(guò)程說(shuō)明

步驟 過(guò)程說(shuō)明 備注
服務(wù)進(jìn)程注冊(cè)服務(wù) 1.服務(wù)進(jìn)程向binder驅(qū)動(dòng)發(fā)送注冊(cè)服務(wù)請(qǐng)求2.binder驅(qū)動(dòng)將請(qǐng)求轉(zhuǎn)發(fā)到serviceManager3.serviceManager進(jìn)程添加服務(wù)進(jìn)程(注冊(cè)服務(wù)進(jìn)程) 此時(shí)serviceManager擁有了服務(wù)進(jìn)程的信息
客戶進(jìn)程獲取服務(wù) 1.客戶進(jìn)程向binder驅(qū)動(dòng)發(fā)送獲取服務(wù)請(qǐng)求2.binder驅(qū)動(dòng)將請(qǐng)求轉(zhuǎn)發(fā)給serviceManager3.serviceManager查找客戶進(jìn)程需要的服務(wù)進(jìn)程信息4.serviceManager將找到的服務(wù)進(jìn)程信息通過(guò)binder驅(qū)動(dòng)傳遞給客戶進(jìn)程系洛。 此時(shí)客戶進(jìn)程與服務(wù)進(jìn)程建立了聯(lián)系
客戶進(jìn)程使用服務(wù)(1) binder驅(qū)動(dòng)為跨進(jìn)程調(diào)用做準(zhǔn)備(系統(tǒng)調(diào)用mmap) 1.binder驅(qū)動(dòng)創(chuàng)建接收緩沖區(qū)2.通過(guò)serviceManager提供的服務(wù)進(jìn)程信息地址映射將服務(wù)進(jìn)程用戶空間地址與內(nèi)核緩沖區(qū)映射到同一個(gè)接收緩沖區(qū)(即Binder驅(qū)動(dòng)創(chuàng)建的接收緩沖區(qū))
客戶進(jìn)程使用服務(wù)(2) 客戶進(jìn)程將參數(shù)傳遞到服務(wù)進(jìn)程 1.服務(wù)進(jìn)程調(diào)用copy_from_user將數(shù)據(jù)傳遞到內(nèi)核緩沖區(qū)(當(dāng)前進(jìn)程被掛起)2.內(nèi)核緩沖區(qū)與服務(wù)進(jìn)程用戶空間地址映射到同一個(gè)接收緩沖區(qū),相當(dāng)于參數(shù)被傳遞到了服務(wù)進(jìn)程的用戶空間3.binder驅(qū)動(dòng)通知服務(wù)進(jìn)程進(jìn)行解包
客戶進(jìn)程使用服務(wù)(3) 服務(wù)進(jìn)程根據(jù)客戶進(jìn)程要求調(diào)用目標(biāo)方法 1.收到binder解包通知后亿眠,server從binder線程池中取出線程碎罚,進(jìn)行解包和方法調(diào)用2.將方法結(jié)果寫到自己的共享內(nèi)存中
客戶進(jìn)程使用服務(wù)(4) 服務(wù)進(jìn)程將目標(biāo)方法的結(jié)果返回給客戶進(jìn)程 1.將結(jié)果寫入映射的用戶空間地址指向的內(nèi)存區(qū)域中2.由于內(nèi)核緩沖區(qū)與服務(wù)進(jìn)程用戶空間地址通過(guò)地址映射映射到同一個(gè)接收緩沖區(qū),相當(dāng)于目標(biāo)方法的結(jié)果傳遞到了內(nèi)核緩沖區(qū)纳像,3.Binder驅(qū)動(dòng)通知客戶進(jìn)程取出結(jié)果4.客戶進(jìn)程通過(guò)系統(tǒng)調(diào)用copy_to_user將內(nèi)核緩沖區(qū)的目標(biāo)結(jié)果拷貝到客戶進(jìn)程用戶空間

優(yōu)點(diǎn):
1.傳輸效率高荆烈,單項(xiàng)通信數(shù)據(jù)拷貝次數(shù)少(1次),內(nèi)核空間與用戶空間通過(guò)共享對(duì)象直接交互。
2.為接收進(jìn)程創(chuàng)建了大小不確定的接收緩沖區(qū)憔购。

2.3額外說(shuō)明:

(1)客戶進(jìn)程宫峦,服務(wù)進(jìn)程,ServiceManager進(jìn)程均屬于用戶空間不能直接相互通信玫鸟。Binder驅(qū)動(dòng)屬于內(nèi)核空間导绷,可以進(jìn)行用戶空間/內(nèi)核空間交互。
(2)Binder和ServiceManager屬于Android基礎(chǔ)架構(gòu)不需要開(kāi)發(fā)者去實(shí)現(xiàn)屎飘,開(kāi)發(fā)者需要關(guān)心的是自定義客戶進(jìn)程和服務(wù)進(jìn)程妥曲,借助基礎(chǔ)架構(gòu)就能實(shí)現(xiàn)跨進(jìn)程通信。
(3)服務(wù)進(jìn)程會(huì)創(chuàng)建多個(gè)線程來(lái)處理Binder請(qǐng)求(默認(rèn)16個(gè))钦购,Binder模型的線程管理 采用Binder驅(qū)動(dòng)的線程池檐盟,并由Binder驅(qū)動(dòng)自身進(jìn)行管理(不是服務(wù)進(jìn)程進(jìn)行管理)

Binder機(jī)制 在Android中的具體實(shí)現(xiàn)原理

Binder機(jī)制在Android中主要依靠Binder類進(jìn)行實(shí)現(xiàn),該類實(shí)現(xiàn)了IBinder接口押桃。
實(shí)例說(shuō)明:Client進(jìn)程 需要調(diào)用 Server進(jìn)程的加法函數(shù)(將整數(shù)a和b相加)

Client進(jìn)程提供相加的數(shù)字a和b給服務(wù)進(jìn)程
Server進(jìn)程負(fù)責(zé)將兩個(gè)數(shù)相加并將結(jié)果返回給Client進(jìn)程

1.Server進(jìn)程注冊(cè)服務(wù)
過(guò)程描述
Server進(jìn)程 通過(guò)Binder驅(qū)動(dòng) 向 Service Manager進(jìn)程 注冊(cè)服務(wù)
代碼實(shí)現(xiàn)
Server進(jìn)程 創(chuàng)建 一個(gè) Binder 對(duì)象

該Binder對(duì)象是Server進(jìn)程在Binder驅(qū)動(dòng)中的存在形式
該Binder對(duì)象保存著Server進(jìn)程和ServiceManager的信息(保存在內(nèi)核空間中)
當(dāng)客戶進(jìn)程獲取服務(wù)時(shí)葵萎,通過(guò)該Binder找到對(duì)應(yīng)的服務(wù)進(jìn)程

以下代碼是系統(tǒng)根據(jù)AIDL文件生成的接口代碼:

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: D:\\code\\BinderServerDemo\\app\\src\\main\\aidl\\com\\zhqy\\binderserverdemo\\AddInterface.aidl
 */
package com.zhqy.binderserverdemo;
// Declare any non-default types here with import statements

public interface AddInterface extends android.os.IInterface {
    /**
     * Local-side IPC implementation stub class.
     */
    public static abstract class Stub extends android.os.Binder implements com.zhqy.binderserverdemo.AddInterface {
        private static final java.lang.String DESCRIPTOR = "com.zhqy.binderserverdemo.AddInterface";

        /**
         * Construct the stub at attach it to the interface.
         */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an com.zhqy.binderserverdemo.AddInterface interface,
         * generating a proxy if needed.
         */
        public static com.zhqy.binderserverdemo.AddInterface asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.zhqy.binderserverdemo.AddInterface))) {
                return ((com.zhqy.binderserverdemo.AddInterface) iin);
            }
            return new com.zhqy.binderserverdemo.AddInterface.Stub.Proxy(obj);
        }

        @Override
        public android.os.IBinder asBinder() {
            return this;
        }

        @Override
        public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
            switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(DESCRIPTOR);
                    return true;
                }
                case TRANSACTION_add: {
                    data.enforceInterface(DESCRIPTOR);
                    int _arg0;
                    _arg0 = data.readInt();
                    int _arg1;
                    _arg1 = data.readInt();
                    int _result = this.add(_arg0, _arg1);
                    reply.writeNoException();
                    reply.writeInt(_result);
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }

        private static class Proxy implements com.zhqy.binderserverdemo.AddInterface {
            private android.os.IBinder mRemote;

            Proxy(android.os.IBinder remote) {
                mRemote = remote;
            }

            @Override
            public android.os.IBinder asBinder() {
                return mRemote;
            }

            public java.lang.String getInterfaceDescriptor() {
                return DESCRIPTOR;
            }

            @Override
            public int add(int a, int b) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                int _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeInt(a);
                    _data.writeInt(b);
                    mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readInt();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }

        static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    }

    public int add(int a, int b) throws android.os.RemoteException;
}

下面對(duì)相關(guān)方法進(jìn)行說(shuō)明:
DESCRIPTOR:Binder的唯一標(biāo)識(shí),一般用類名進(jìn)行標(biāo)識(shí)
asInterface(android.os.IBinder obj):用于將Binder對(duì)象轉(zhuǎn)換成客戶進(jìn)程需要的AIDL接口類型的對(duì)象唱凯,該方法區(qū)分所在的進(jìn)程羡忘,如果服務(wù)進(jìn)程和客戶進(jìn)程在同一個(gè)進(jìn)程中則返回服務(wù)端Stub對(duì)象本身,否則返回的是服務(wù)進(jìn)程Stub的代理類Stub.proxy對(duì)象磕昼。
asBinder:返回Binder對(duì)象卷雕。
onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags):這個(gè)方法在運(yùn)行在服務(wù)進(jìn)程的binder線程池中,當(dāng)客戶進(jìn)程發(fā)起獲取服務(wù)時(shí)票从,獲取服務(wù)的請(qǐng)求會(huì)由系統(tǒng)底層封裝后交給此方法執(zhí)行爽蝴。其中code表示調(diào)用的是哪一個(gè)目標(biāo)方法,data為執(zhí)行該方法所需要的參數(shù)(如果有的話),reply為執(zhí)行完該目標(biāo)方法時(shí)纫骑,如果有返回值的話將返回值寫入reply。返回值表示該方法是否調(diào)用成功九孩,如果返回false則客戶進(jìn)程調(diào)用失敗先馆。
注冊(cè)服務(wù)后,Binder驅(qū)動(dòng)持有 Server進(jìn)程創(chuàng)建的Binder實(shí)體躺彬。
proxy#add(int a, int b):該方法會(huì)在客戶進(jìn)程中調(diào)用煤墙,當(dāng)客戶端獲取服務(wù)時(shí),首先會(huì)創(chuàng)建輸入行Parcel對(duì)象_data和輸出項(xiàng)_reply和返回值對(duì)象_result宪拥,將遠(yuǎn)程過(guò)程調(diào)用(RPC)所需要的參數(shù)寫入_data中仿野,然后執(zhí)行transact方法進(jìn)行遠(yuǎn)程過(guò)程調(diào)用(客戶進(jìn)程被掛起),服務(wù)進(jìn)程執(zhí)行onTransact方法她君,當(dāng)服務(wù)進(jìn)程返回目標(biāo)方法執(zhí)行的結(jié)果后脚作,喚醒客戶進(jìn)程的transact方法,將服務(wù)進(jìn)程返回的執(zhí)行結(jié)果寫入_result,最后返回_result球涛。

2.客戶進(jìn)程獲取服務(wù)
過(guò)程:客戶進(jìn)程在使用服務(wù)進(jìn)程的目標(biāo)方法時(shí)劣针,須通過(guò)Binder驅(qū)動(dòng)從ServiceManager中獲取服務(wù)進(jìn)程信息

過(guò)程描述 代碼實(shí)現(xiàn) 說(shuō)明
客戶進(jìn)程向Binder驅(qū)動(dòng)發(fā)送獲取服務(wù)請(qǐng)求,并寫入需要獲得的服務(wù)名稱 從客戶進(jìn)程組件中執(zhí)行bindService
Binder驅(qū)動(dòng)將客戶進(jìn)程發(fā)送的請(qǐng)求轉(zhuǎn)發(fā)到ServiceManager亿扁,ServiceManager查找客戶進(jìn)程需要的服務(wù)進(jìn)程的Bidner實(shí)體的引用信息返回給binder驅(qū)動(dòng) 服務(wù)進(jìn)程中的onBind執(zhí)行并返回binder的代理對(duì)象--BinderProxy 該代理對(duì)象類即上面代碼所定義的代理類
Binder驅(qū)動(dòng)將代理對(duì)象返回給客戶進(jìn)程 客戶進(jìn)程調(diào)用ServiceConnection中的onServiceConnected接收代理對(duì)象轉(zhuǎn)化的AIDL接口對(duì)象 客戶進(jìn)程獲得是服務(wù)進(jìn)程binder類的代理類對(duì)象捺典,并不是真正的服務(wù)進(jìn)程的binder對(duì)象,客戶進(jìn)程通過(guò)操作該代理對(duì)象通過(guò)binder驅(qū)動(dòng)最終由服務(wù)進(jìn)程的bidner對(duì)象執(zhí)行操作

此時(shí)服務(wù)進(jìn)程與客戶進(jìn)程建立了聯(lián)系

3.客戶進(jìn)程調(diào)用服務(wù)
當(dāng)客戶進(jìn)程與服務(wù)進(jìn)程建立起聯(lián)系后从祝,客戶進(jìn)程通過(guò)操作服務(wù)進(jìn)程的代理對(duì)象類BinderProxy通過(guò)binder驅(qū)動(dòng)來(lái)執(zhí)行服務(wù)進(jìn)程中的相關(guān)方法

過(guò)程描述 代碼描述 說(shuō)明
客戶進(jìn)程提供目標(biāo)方法的參數(shù)通過(guò)Binder驅(qū)動(dòng)發(fā)送到服務(wù)進(jìn)程進(jìn)行解包 客戶進(jìn)程執(zhí)行代理對(duì)象類的目標(biāo)方法(add(int a,int b)),首先創(chuàng)建輸出型parcel對(duì)象—_data,輸入型parcel對(duì)象_reply,結(jié)果_result(類型為AIDL允許的類型)襟己,將目標(biāo)方法需要的參數(shù)屑放入_data并執(zhí)行transact進(jìn)行遠(yuǎn)程過(guò)程調(diào)用(RPC),客戶進(jìn)程被掛起。Binder驅(qū)動(dòng)通知服務(wù)進(jìn)程進(jìn)行解包
服務(wù)進(jìn)程接收Bidner驅(qū)動(dòng)的解包通知進(jìn)行解包并執(zhí)行目標(biāo)方法 服務(wù)進(jìn)程首先從進(jìn)程池中取出Binder對(duì)象并調(diào)用onTransact牍陌,首先根據(jù)code判定需要執(zhí)行那個(gè)方法擎浴,再?gòu)腳data中取出目標(biāo)方法需要的參數(shù)(如果有的話),然后執(zhí)行該目標(biāo)方法呐赡,將目標(biāo)方法的返回值寫入_result
服務(wù)進(jìn)程將目標(biāo)方法的返回值返回給客戶進(jìn)程 當(dāng)目標(biāo)方法執(zhí)行完后退客,會(huì)返回true通知binder驅(qū)動(dòng)方法調(diào)用成功,這是binder驅(qū)動(dòng)喚醒客戶進(jìn)程链嘀,從代理對(duì)象中獲取目標(biāo)方法的執(zhí)行結(jié)果并寫入_result萌狂,最終將_result進(jìn)行返回。這時(shí)客戶進(jìn)程就獲取到了服務(wù)進(jìn)程目標(biāo)方法執(zhí)行的結(jié)果怀泊。
原理圖.png

整個(gè)過(guò)程如下圖所示:


流程圖.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末茫藏,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子霹琼,更是在濱河造成了極大的恐慌务傲,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件枣申,死亡現(xiàn)場(chǎng)離奇詭異售葡,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)忠藤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門挟伙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人模孩,你說(shuō)我怎么就攤上這事尖阔。” “怎么了榨咐?”我有些...
    開(kāi)封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵介却,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我块茁,道長(zhǎng)齿坷,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮胃夏,結(jié)果婚禮上轴或,老公的妹妹穿的比我還像新娘。我一直安慰自己仰禀,他們只是感情好照雁,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著答恶,像睡著了一般饺蚊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上悬嗓,一...
    開(kāi)封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天污呼,我揣著相機(jī)與錄音,去河邊找鬼包竹。 笑死燕酷,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的周瞎。 我是一名探鬼主播苗缩,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼声诸!你這毒婦竟也來(lái)了酱讶?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤彼乌,失蹤者是張志新(化名)和其女友劉穎泻肯,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體慰照,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡灶挟,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了毒租。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片膏萧。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蝌衔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蝌蹂,我是刑警寧澤噩斟,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站孤个,受9級(jí)特大地震影響剃允,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一斥废、第九天 我趴在偏房一處隱蔽的房頂上張望椒楣。 院中可真熱鬧,春花似錦牡肉、人聲如沸捧灰。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)毛俏。三九已至,卻和暖如春饲窿,著一層夾襖步出監(jiān)牢的瞬間煌寇,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工逾雄, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留阀溶,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓鸦泳,卻偏偏與公主長(zhǎng)得像银锻,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子辽故,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

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