Binder簡(jiǎn)析

1.Binder簡(jiǎn)介

我們知道舔涎,在Android操作系統(tǒng)中乱凿,每個(gè)進(jìn)程都擁有屬于自己的獨(dú)立虛擬地址空間(用戶(hù)空間+內(nèi)核空間)。一般情況下粱胜,進(jìn)程的用戶(hù)空間是各自獨(dú)立的,無(wú)法進(jìn)行數(shù)據(jù)共享狐树;而內(nèi)核空間卻是所有進(jìn)程都可以共同訪(fǎng)問(wèn)的焙压。


進(jìn)程空間

對(duì)于Android系統(tǒng)來(lái)說(shuō),其特有的IPC機(jī)制是Binder抑钟。正如其名字所喻(粘粘劑)涯曲,通過(guò)Binder作為橋梁,將系統(tǒng)各個(gè)進(jìn)程組件進(jìn)行連接在塔。

2.Binder優(yōu)點(diǎn)

1.Binder更加簡(jiǎn)潔和快速幻件,消耗的內(nèi)存資源更小。
2.傳統(tǒng)的進(jìn)程間通信可能會(huì)增加進(jìn)程的開(kāi)銷(xiāo)蛔溃,而且有進(jìn)程過(guò)載和安全漏洞等方面的風(fēng)險(xiǎn)绰沥,Binder正好能解決和避免這些問(wèn)題篱蝇。
3.用驅(qū)動(dòng)程序來(lái)推進(jìn)進(jìn)程間的通信。
4.通過(guò)共享內(nèi)存來(lái)提高性能徽曲。
5.為進(jìn)程請(qǐng)求分配每個(gè)進(jìn)程的線(xiàn)程池零截。
6.針對(duì)系統(tǒng)中的對(duì)象引入了引用計(jì)數(shù)和跨進(jìn)程的對(duì)象引用映射。
7.進(jìn)程間同步調(diào)用秃臣。

3.Binder實(shí)現(xiàn)IPC通訊原理

3.1 Binder IPC基礎(chǔ)組件

Binder通訊采用C/S架構(gòu)涧衙,其進(jìn)行IPC涉及到的組件主要包含Client,Server,ServerManager和binder驅(qū)動(dòng)。

Client:客戶(hù)端
Server:服務(wù)端
ServerManager:用于管理系統(tǒng)中的各種服務(wù)甜刻。提供服務(wù)注冊(cè)功能和查詢(xún)服務(wù)功能绍撞。(此處的ServerManager是Native層的ServiceManager(c++),不是framework層的ServerManager(java))。
binder驅(qū)動(dòng):位于內(nèi)核空間得院,提供Client傻铣,Server,ServerManager跨進(jìn)程通訊功能祥绞。

3.2實(shí)例講解

我們知道非洲,Android提供的AIDL通訊底層采用的就是Binder機(jī)制。現(xiàn)在我們采用AIDL方式創(chuàng)建2個(gè)應(yīng)用進(jìn)行進(jìn)程間通訊蜕径。
(1)首先定義aidl接口:

// IMath.aidl
package com.yn.bindertest.aidl;

// Declare any non-default types here with import statements

interface IMath {
    int add(in int a,in int b);
    void result(in int justTestWithoutReturnValue);
}

(2)服務(wù)端代碼編寫(xiě):

public class Server extends Service {
    private static final String TAG = "ynServer";
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new IMath.Stub(){
            @Override
            public int add(int a, int b) throws RemoteException {
                Log.d(TAG, "add: "+Thread.currentThread().getName());
                return a+b;
            }

            @Override
            public void result(int justTestWithoutReturnValue) throws RemoteException {
                Log.d(TAG, "result: "+Thread.currentThread().getName());
            }
        };
    }
}

(3)客戶(hù)端代碼編寫(xiě):

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "ynClient";
    private TextView tvShow;
    private IMath mServer;
    private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.d(TAG, "onServiceConnected: "+Thread.currentThread().getName());
            mServer = IMath.Stub.asInterface(service);
            try {
                mServer.asBinder().linkToDeath(mDeathRecipient,0);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.d(TAG, "onServiceDisconnected: "+Thread.currentThread().getName());
        }
    };
    private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient(){

        @Override
        public void binderDied() {
            Log.d(TAG, "binderDied: "+Thread.currentThread().getName());
            bindService(new Intent(MainActivity.this, Server.class),mServiceConnection , Context.BIND_AUTO_CREATE);
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tvShow = (TextView)findViewById(R.id.tvShow);
        bindService(new Intent(this, Server.class),mServiceConnection , Context.BIND_AUTO_CREATE);


    }

    public void onClick(View view)
    {
        try {
            int sum = mServer.add(10,30);
            Log.d(TAG, "onClick: sum="+sum);
            tvShow.setText(sum+"");
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }
}

(4)記得在AndroidManifest.xml中將Service設(shè)置到另一個(gè)進(jìn)程中两踏。

 <service
            android:name=".Server"
            android:process="com.yn.bindertest.server" />

通過(guò)以上步驟,我們就實(shí)現(xiàn)了使用AIDL進(jìn)行跨進(jìn)程通訊功能兜喻,結(jié)果如下:

AIDL跨進(jìn)程通訊

當(dāng)程序啟動(dòng)時(shí)梦染,bindService()成功時(shí)就會(huì)回調(diào)onServiceConnected,然后手動(dòng)調(diào)用add可以看到add過(guò)程是運(yùn)行在Server端的binder線(xiàn)程池中的朴皆;由于為Server設(shè)置了死亡代理帕识,當(dāng)服務(wù)端異常被kill時(shí),會(huì)回調(diào)死亡代理IBinder.DeathRecipient.binderDied和ServiceConnection.onServiceDisconnected遂铡,兩者的區(qū)別就是binderDied是運(yùn)行在客戶(hù)端的binder線(xiàn)程池中的肮疗,而onServiceDisconnected是運(yùn)行在主線(xiàn)程中的
更關(guān)鍵的一點(diǎn)是:當(dāng)客戶(hù)端調(diào)用遠(yuǎn)程函數(shù)時(shí)扒接,客戶(hù)端進(jìn)程會(huì)被掛起伪货,等待遠(yuǎn)程服務(wù)端執(zhí)行完成后才重新運(yùn)行客戶(hù)端進(jìn)程,因此钾怔,這是一個(gè)同步調(diào)用碱呼,應(yīng)小心因?yàn)榉?wù)端的耗時(shí)方法導(dǎo)致客戶(hù)端發(fā)生ANR

3.3 aidl的binder機(jī)制講解

當(dāng)我們創(chuàng)建完成IMath.aidl文件后宗侦,rebuild一下巍举,可以看到IDE為我們生成了一個(gè).java文件,路徑為:app\build\generated\source\aidl\debug\com\yn\bindertest\aidl\IMath.java
該IMath.java的具體內(nèi)容如下:


IMath.java

可以看到凝垛,IDE為我們自動(dòng)生成的其實(shí)就是一個(gè)繼承了IInterface的接口懊悯,生成的接口類(lèi)名和方法與我們aidl中聲明的完全一致蜓谋,只是另外增加了一個(gè)Stub內(nèi)部抽象靜態(tài)類(lèi),而這個(gè)Stub類(lèi)繼承了Binder并且實(shí)現(xiàn)了我們這個(gè)IMath(由于IMath繼承了IInterface,而IInterface只有一個(gè)接口方法asBinder),所以這個(gè)Stub類(lèi)就是一個(gè)Binder炭分,并且必須實(shí)現(xiàn)我們自己定義的IMath中的接口方法桃焕,并提供asBinder方法給到系統(tǒng)調(diào)用。

所以這個(gè)Stub類(lèi)才是我們要著重進(jìn)行研究的捧毛,那么這個(gè)Stub類(lèi)的具體如下所示:

    /**
     * Local-side IPC implementation stub class.
     */
    public static abstract class Stub extends android.os.Binder implements com.yn.bindertest.aidl.IMath {
        private static final java.lang.String DESCRIPTOR = "com.yn.bindertest.aidl.IMath";

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

        /**
         * Cast an IBinder object into an com.yn.bindertest.aidl.IMath interface,
         * generating a proxy if needed.
         */
        public static com.yn.bindertest.aidl.IMath asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.yn.bindertest.aidl.IMath))) {
                return ((com.yn.bindertest.aidl.IMath) iin);
            }
            return new com.yn.bindertest.aidl.IMath.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;
                }
                case TRANSACTION_result: {
                    data.enforceInterface(DESCRIPTOR);
                    int _arg0;
                    _arg0 = data.readInt();
                    this.result(_arg0);
                    reply.writeNoException();
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags);
        }

        private static class Proxy implements com.yn.bindertest.aidl.IMath {
            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;
            }

            @Override
            public void result(int justTestWithoutReturnValue) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeInt(justTestWithoutReturnValue);
                    mRemote.transact(Stub.TRANSACTION_result, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
        }

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

看一下asInterface()內(nèi)容:

asInterface

可以看出观堂,通過(guò)DESCRIPTOR(即包名+類(lèi)名:"com.yn.bindertest.aidl.IMath")先進(jìn)行本地查找,如果找到呀忧,那么返回本地binder類(lèi)對(duì)象(即onBind返回的那個(gè)binder對(duì)象)师痕,如果找不到,那么返回一個(gè)binder代理類(lèi)而账,這個(gè)代理類(lèi)具體內(nèi)容如下:

       private static class Proxy implements com.yn.bindertest.aidl.IMath {
            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;
            }

            @Override
            public void result(int justTestWithoutReturnValue) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeInt(justTestWithoutReturnValue);
                    mRemote.transact(Stub.TRANSACTION_result, _data, _reply, 0);
                    _reply.readException();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
            }
        }

可以看到胰坟,這個(gè)Proxy也實(shí)現(xiàn)了IMath接口,并且持有一個(gè)遠(yuǎn)程服務(wù)的IBinder對(duì)象(其實(shí)這個(gè)IBinder是一個(gè)BinderProxy對(duì)象泞辐,是bindservice時(shí)笔横,向ServiceManager獲取得到的)。所以咐吼,當(dāng)處于不同的進(jìn)程時(shí)吹缔,客戶(hù)端得到的是一個(gè)Proxy代理類(lèi),然后由于該代理類(lèi)實(shí)現(xiàn)了aidl定義的接口锯茄,并且持有一個(gè)遠(yuǎn)程IBinder接口厢塘,所以在調(diào)用aidl接口方法時(shí),可以看到肌幽,它通過(guò)將函數(shù)參數(shù)放入到一個(gè)Parcel(_data)中晚碾,提供一個(gè)Parcel(_reply)存儲(chǔ)返回結(jié)果(如果有返回的話(huà)),然后通過(guò)持有的遠(yuǎn)程IBinder對(duì)象的transact將函數(shù)標(biāo)識(shí)牍颈,參數(shù)Parcel和返回結(jié)果Parcel發(fā)送給遠(yuǎn)程服務(wù),客戶(hù)端調(diào)用transact時(shí)琅关,客戶(hù)端進(jìn)程被掛起煮岁,然后通過(guò)binder驅(qū)動(dòng)調(diào)用到遠(yuǎn)程服務(wù)的onTransact函數(shù),通過(guò)傳遞過(guò)來(lái)的函數(shù)標(biāo)識(shí)涣易,就可以知道要執(zhí)行哪個(gè)函數(shù)画机,然后取出對(duì)應(yīng)的函數(shù)參數(shù),運(yùn)行完成后新症,將返回結(jié)果存儲(chǔ)到_reply中步氏,通過(guò)binder驅(qū)動(dòng)返回給客戶(hù)端,客戶(hù)端只要讀取_reply就可以獲取到結(jié)果徒爹。這樣荚醒,就完成了一次IPC通訊芋类。

綜上所述,通過(guò)aidl實(shí)現(xiàn)IPC的原理如下:
1.IDE根據(jù)我們定義的aidl生成一個(gè)同名接口界阁,并繼承IInterface,目的是為了客戶(hù)端可以通過(guò)asBinder獲取到binder對(duì)象(同個(gè)進(jìn)程則獲取的是同一個(gè)binder侯繁,不同進(jìn)程獲取到的是一個(gè)BinderProxy代理對(duì)象)。
2.當(dāng)Server(Service)啟動(dòng)時(shí)泡躯,它會(huì)通過(guò)binder驅(qū)動(dòng)向ServiceManager進(jìn)行注冊(cè)(binder標(biāo)識(shí)+binder引用)贮竟;當(dāng)Client要獲取遠(yuǎn)程服務(wù)(bindservice)時(shí),它首先要通過(guò)binder驅(qū)動(dòng)向ServiceManger獲取特定遠(yuǎn)程服務(wù)的binder引用较剃,獲取成功后咕别,就可以對(duì)遠(yuǎn)程服務(wù)進(jìn)行IPC通訊(也是通過(guò)binder驅(qū)動(dòng))。

總結(jié)

應(yīng)用間通過(guò)Binder實(shí)現(xiàn)IPC的整體過(guò)程如下圖所示:

binder綜合流程

1.當(dāng)Server啟動(dòng)時(shí)写穴,它會(huì)通過(guò)進(jìn)程內(nèi)的0號(hào)binder引用惰拱,將服務(wù)名和binder傳遞給內(nèi)核0號(hào)binder引用,再依次傳給ServiceManager內(nèi)核binder實(shí)體确垫,最后傳入ServiceManager的進(jìn)程binder中弓颈。經(jīng)過(guò)這個(gè)過(guò)程后,ServiceManager內(nèi)部就記錄了Server相應(yīng)的信息删掀,該過(guò)程即是Server向ServiceManager的注冊(cè)過(guò)程翔冀。

2.當(dāng)Client要進(jìn)行遠(yuǎn)程服務(wù)通訊時(shí),它首先會(huì)經(jīng)由進(jìn)程內(nèi)0號(hào)binder引用通知到內(nèi)核0號(hào)binder引用披泪,然后經(jīng)由ServiceManager內(nèi)核binder實(shí)體纤子,最后將所需的服務(wù)信息傳入到ServiceManager進(jìn)程的binder實(shí)體中,那么ServiceManager通過(guò)查詢(xún)相關(guān)服務(wù)信息款票,如果存在對(duì)應(yīng)服務(wù)控硼,就會(huì)通過(guò)binder驅(qū)動(dòng)傳遞一個(gè)擁有訪(fǎng)問(wèn)遠(yuǎn)程服務(wù)能力的BinderProxy給到Client(即bindservice時(shí),onServiceConnection中的onConnected中的IBinder參數(shù))艾少。這個(gè)過(guò)程就是Client的獲取遠(yuǎn)程服務(wù)過(guò)程卡乾。

3.Client獲取遠(yuǎn)程服務(wù)成功后嫩舟,就可以通過(guò)ServiceManager傳遞過(guò)來(lái)的BinderProxy對(duì)象創(chuàng)建出一個(gè)遠(yuǎn)程服務(wù)Binder的代理類(lèi)對(duì)象(asInterface)筷弦,通過(guò)這個(gè)代理類(lèi)對(duì)象,Client就可以執(zhí)行遠(yuǎn)程服務(wù)相關(guān)方法了傍菇,從而實(shí)現(xiàn)跨進(jìn)程IPC通訊谍椅。

4.當(dāng)Client調(diào)用遠(yuǎn)程方法時(shí)误堡,本地遠(yuǎn)程binder的代理類(lèi)對(duì)象會(huì)調(diào)用其持有的BinderProxy對(duì)象的transact方法,這個(gè)方法會(huì)將要調(diào)用的函數(shù)標(biāo)識(shí)雏吭,參數(shù)和返回值(如果有的話(huà))放入到Client的共享內(nèi)存中锁施,然后經(jīng)由內(nèi)核binder驅(qū)動(dòng)運(yùn)輸?shù)较鄳?yīng)遠(yuǎn)程服務(wù)的共享內(nèi)存中,然后遠(yuǎn)程服務(wù)的進(jìn)程binder實(shí)體的onTransact函數(shù)會(huì)被調(diào)用,這個(gè)函數(shù)的功能就是從共享內(nèi)存中獲取傳遞過(guò)來(lái)的相關(guān)信息悉抵,通過(guò)函數(shù)標(biāo)識(shí)就知道要運(yùn)行哪個(gè)函數(shù)肩狂,然后再將相關(guān)的參數(shù)提取出來(lái)(如果有的話(huà)),執(zhí)行完畢后基跑,就將返回結(jié)果存入之前傳遞過(guò)來(lái)的容器(Parcel)內(nèi)婚温,最后經(jīng)由內(nèi)核binder驅(qū)動(dòng)傳遞回給到Client中。這樣媳否,一次完整的binder IPC通訊就完成了栅螟。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市篱竭,隨后出現(xiàn)的幾起案子力图,更是在濱河造成了極大的恐慌,老刑警劉巖掺逼,帶你破解...
    沈念sama閱讀 212,222評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吃媒,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡吕喘,警方通過(guò)查閱死者的電腦和手機(jī)赘那,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,455評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)氯质,“玉大人募舟,你說(shuō)我怎么就攤上這事∥挪欤” “怎么了拱礁?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,720評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)辕漂。 經(jīng)常有香客問(wèn)我呢灶,道長(zhǎng),這世上最難降的妖魔是什么钉嘹? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,568評(píng)論 1 284
  • 正文 為了忘掉前任鸯乃,我火速辦了婚禮,結(jié)果婚禮上跋涣,老公的妹妹穿的比我還像新娘缨睡。我一直安慰自己,他們只是感情好仆潮,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,696評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布宏蛉。 她就那樣靜靜地躺著遣臼,像睡著了一般性置。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上揍堰,一...
    開(kāi)封第一講書(shū)人閱讀 49,879評(píng)論 1 290
  • 那天鹏浅,我揣著相機(jī)與錄音嗅义,去河邊找鬼。 笑死隐砸,一個(gè)胖子當(dāng)著我的面吹牛之碗,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播季希,決...
    沈念sama閱讀 39,028評(píng)論 3 409
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼褪那,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了式塌?” 一聲冷哼從身側(cè)響起博敬,我...
    開(kāi)封第一講書(shū)人閱讀 37,773評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎峰尝,沒(méi)想到半個(gè)月后偏窝,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,220評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡武学,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,550評(píng)論 2 327
  • 正文 我和宋清朗相戀三年祭往,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片火窒。...
    茶點(diǎn)故事閱讀 38,697評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡硼补,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出沛鸵,到底是詐尸還是另有隱情括勺,我是刑警寧澤,帶...
    沈念sama閱讀 34,360評(píng)論 4 332
  • 正文 年R本政府宣布曲掰,位于F島的核電站疾捍,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏栏妖。R本人自食惡果不足惜乱豆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,002評(píng)論 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望吊趾。 院中可真熱鬧宛裕,春花似錦、人聲如沸论泛。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,782評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)屁奏。三九已至岩榆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背勇边。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,010評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工犹撒, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人粒褒。 一個(gè)月前我還...
    沈念sama閱讀 46,433評(píng)論 2 360
  • 正文 我出身青樓识颊,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親奕坟。 傳聞我的和親對(duì)象是個(gè)殘疾皇子祥款,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,587評(píng)論 2 350

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