BAT大廠Android工程師帶你學(xué)習(xí)Framework內(nèi)核解析

前言

對(duì)于Android開(kāi)發(fā)氛改,干上幾年后,都要進(jìn)階表悬,或者直接轉(zhuǎn)行了。如果你還在干Android丧靡,想要進(jìn)階 對(duì)Framework的了解是必不可少的過(guò)程蟆沫,下面就開(kāi)始進(jìn)入今天的主題吧。

我們知道温治,對(duì)于任何程序語(yǔ)言而言饭庞,入口一般都是main函數(shù)。

那Android的程序入口在哪呢熬荆? 他的main函數(shù)是怎么啟動(dòng)起來(lái)的呢舟山?

可能熟悉Android的同學(xué),知道一個(gè)應(yīng)用程序的入口在ActivityThread中卤恳,那有個(gè)問(wèn)題累盗,ActivityThread中的main函數(shù)是何時(shí)被誰(shuí)被調(diào)用的呢?

將從本文中找到以上答案纬黎,如果已經(jīng)熟悉了此過(guò)程的同學(xué)幅骄,可以在溫習(xí)一下。

Android架構(gòu)

Android 平臺(tái)的基礎(chǔ)是 Linux 內(nèi)核本今。Android Runtime (ART/Dalvik) 依靠 Linux 內(nèi)核來(lái)執(zhí)行底層功能拆座,例如線程和低層內(nèi)存管理等。

而在Android Runtime之上就是我們經(jīng)常接觸的Java API Framework層冠息, 如下圖是Android的系統(tǒng)架構(gòu)圖

image

今天的主題不是此架構(gòu)圖的各個(gè)部分解釋挪凑,而是離應(yīng)用層更近的Framework層啟動(dòng)過(guò)程分析。

Android Framework概述

如果我們這里拋開(kāi)Android架構(gòu)圖逛艰,那狹義的Framewrok主要包含那些內(nèi)容呢躏碳?

按我的理解,可以分為三個(gè)部分 服務(wù)端散怖,客戶端菇绵,和依賴Linux底層能力的驅(qū)動(dòng)部分。

服務(wù)端

主要是ActivityManagerService(AMS)镇眷, WindowManagerService(WMS)咬最,PackageM anerService(PMS)

  • AMS 主要用于管理所有應(yīng)用程序的Activity
  • WMS 管理各個(gè)窗口,隱藏欠动,顯示等
  • PMS 用來(lái)管理跟蹤所有應(yīng)用APK永乌,安裝惑申,解析,控制權(quán)限等.

還有用來(lái)處理觸摸消息的兩個(gè)類KeyInputQueue和InputDispatchThread翅雏,一個(gè)用來(lái)讀消息圈驼,一個(gè)用來(lái)分發(fā)消息.

客戶端

主要包括ActivityThread,Activity望几,DecodeView及父類View绩脆,PhoneWindow,ViewRootImpl及內(nèi)部類W等

  • ActivityThread主要用來(lái)和AMS通訊的客戶端橄抹,Activity是我們編寫(xiě)應(yīng)用比較熟悉的類

依賴Linux底層能力的驅(qū)動(dòng)

主要是SurfaceFlingger(SF)和Binder驅(qū)動(dòng)

  • 每一個(gè)窗口都對(duì)應(yīng)一個(gè)Surface衙伶,SF驅(qū)動(dòng)的作用就是把每一個(gè)Surface顯示到同一個(gè)屏幕上
  • Binder 內(nèi)核驅(qū)動(dòng)的作用,就是為上面的服務(wù)端和客戶端(或者服務(wù)端和服務(wù)端之間)害碾,提供IPC通訊用的矢劲。

Zygote

系統(tǒng)中運(yùn)行的第一個(gè)Dalvik虛擬機(jī)程序叫做zygote,該名稱的意義是“一個(gè)卵”慌随,芬沉,因?yàn)榻酉聛?lái)的所有 Dalvik虛擬機(jī)進(jìn)程都是通過(guò)這個(gè)“卵” 孵化出來(lái)的。

zygote進(jìn)程中包含兩個(gè)主要模塊阁猜,分別如下:

  • Socket服務(wù)端丸逸。該 Socket服務(wù)端用于接收啟動(dòng)新的Dalvik進(jìn)程的命令。
  • Framework共享類及共享資源剃袍。當(dāng)zygote進(jìn)程啟動(dòng)后黄刚,會(huì)裝載一些共享的類及資源,其中共享類是在preload-classes文件中被定義民效,共享資源是在preload-resources中被定義憔维。因?yàn)閦ygote進(jìn)程用于孵化出其他Dalvik進(jìn)程,因此畏邢,這些類和資源裝載后业扒,新的Dalvik進(jìn)程就不需要再裝載這些類和資源了,這也就是所謂的共享舒萎。

zygote進(jìn)程對(duì)應(yīng)的具體程序是app_rocess,該程序存在于system/bin目錄下程储,啟動(dòng)該程序的指令是 在 init.rc中進(jìn)行配置的。

Zygote 有?兩個(gè)優(yōu)秀的特點(diǎn)

  • 每fork出的一個(gè)進(jìn)程都是一個(gè)Dalvik虛擬機(jī)臂寝,獨(dú)立的進(jìn)程可以防止一個(gè)程序的崩潰導(dǎo)致所有程序都崩潰章鲤,這種虛擬機(jī)類似Java虛擬機(jī),對(duì)于程序員來(lái)說(shuō)咆贬,可以直接使用Java開(kāi)發(fā)應(yīng)用
  • zygote進(jìn)程預(yù)先會(huì)裝載共享類和共享資源败徊,這些類及資源實(shí)際上就是SDK中定義的大部分類和資源。因此素征,當(dāng)通過(guò)zygote孵化出新的進(jìn)程后集嵌,新的APK進(jìn)程只需要去裝載A PK 自身包含的類和資源即可,這就有效地解決了多個(gè)APK共享Framework資源的問(wèn)題御毅。

SystemServer

zygote孵化出的第一個(gè)Dalvik進(jìn)程叫做SystemServer根欧,SystemServer僅僅是該進(jìn)程的別名,而該進(jìn)程具體對(duì)應(yīng)的程序依然是app_process端蛆,因?yàn)镾ystemServer是從app_process中孵化出來(lái)的凤粗。

SystemServer中創(chuàng)建了一個(gè)Socket客戶端,并有AmS負(fù)責(zé)管理該客戶端今豆,之后所有的Dalvik進(jìn)程都將通過(guò)該Socket客戶端間接被啟動(dòng)嫌拣。當(dāng)需要啟動(dòng)新的APK進(jìn)程時(shí),AmS中會(huì)通過(guò)該Socket客戶端向 zygote進(jìn)程的Socket服務(wù)端發(fā)送一個(gè)啟動(dòng)命令呆躲,然 后 zygote會(huì)孵化出新的進(jìn)程异逐。 上面提到的服務(wù)端,AMS插掂,PMS灰瞻,WMS等都是在SystemServer中啟動(dòng)的.

Android Framework 源頭

操作系統(tǒng)的一般啟動(dòng)流程,分為三個(gè)步驟

  1. 開(kāi)機(jī)通電后辅甥,加載bootloader程序
  2. 操作系統(tǒng)內(nèi)核初始化
  3. 執(zhí)行第一個(gè)應(yīng)用程序

Android 系統(tǒng)是基于Linux 內(nèi)核Kernel酝润,前面Linux bootloader這里不做介紹,直接介紹操作系統(tǒng)內(nèi)核初始化璃弄,在這個(gè)時(shí)候要销,它會(huì)加載init.rc文件.

init.rc文件

在Android根目錄下面,可以直接找到init.rc

generic_x86:/ # ls
acct     bin        cache   config data         dev init            init.rc              init.usb.rc      lost+found mnt oem  product sdcard  sys    ueventd.rc 
adb_keys bugreports charger d      default.prop etc init.environ.rc init.usb.configfs.rc init.zygote32.rc metadata   odm proc sbin    storage system vendor     

打開(kāi)init.rc

generic_x86:/ # cat init.rc
# ..... 省略其他
 # Now we can start zygote for devices with file based encryption
trigger zygote-start

# It is recommended to put unnecessary data/ initialization from post-fs-data
# to start-zygote in device's init.rc to unblock zygote start.
on zygote-start 
    # A/B update verifier that marks a successful boot.
    exec_start update_verifier_nonencrypted
    start netd
    start zygote
    start zygote_secondary

on property:vold.decrypt=trigger_restart_framework
    stop surfaceflinger
# 啟動(dòng)SF
    start surfaceflinger  

# ..... 省略其他 media(媒體)  network(網(wǎng)絡(luò))等啟動(dòng)

也就是在 init.rc時(shí)夏块,啟動(dòng)Android 內(nèi)核疏咐。

app_process

Android 內(nèi)核也是main方法開(kāi)始,他的main方法在 frameworks/base/cmds/app_process/app_main.cpp下

int main(int argc, char* const argv[])
{
    ...
    //初始化AndroidRuntime
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));

    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;

    // 根據(jù)參數(shù)具體判斷啟動(dòng)那個(gè)服務(wù)
    ++i;  // Skip unused "parent dir" argument.
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true;
        } else if (strcmp(arg, "--application") == 0) {
            application = true;
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
            niceName.setTo(arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }
    if (!className.isEmpty()) {
        args.add(application ? String8("application") : String8("tool"));
        runtime.setClassNameAndArgs(className, argc - i, argv + i);
    }else{
        ....
        //啟動(dòng)SystemServer
        if (startSystemServer) {
            args.add(String8("start-system-server"));
        }
    }
    ....
     if (zygote) {
       //啟動(dòng)Zygote
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
    }
}

在這個(gè)Main方法中脐供,先初始化了AppRuntime凳鬓,他的父類是AndroidRuntime。然后我們看到了啟動(dòng)了Java類ZygoteInit缩举。

那c++代碼里怎么啟動(dòng)Java類呢,我們繼續(xù)看 start方法

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
   ...
   //啟動(dòng)Java虛擬機(jī)
     if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
        return;
    }
    ...
    //找到Java 里面的Main方法
     jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");
        if (startMeth == NULL) {
            ALOGE("JavaVM unable to find main() in '%s'\n", className);
            /* keep going */
        } else {
        //執(zhí)行Main方法
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
    }
    ....    
}

可以看到最后先創(chuàng)建了Java虛擬機(jī)匹颤,調(diào)用了Java的main方法仅孩,是不是感覺(jué)有些熟悉感了。

ZygoteInit

上面介紹到印蓖,會(huì)啟動(dòng)Java的ZygoteInit類辽慕,那他里面干了些什么呢? 我們來(lái)看一下關(guān)鍵代碼赦肃,還是從Main方法開(kāi)始

//ZygoteInit.java
  public static void main(String argv[]) {
    ZygoteServer zygoteServer = new ZygoteServer();
    ZygoteHooks.startZygoteNoThreadCreation();

    //創(chuàng)建socket
    zygoteServer.createZygoteSocket(socketName);
    Zygote.createBlastulaSocket(blastulaSocketName);

    if (!enableLazyPreload) {
            bootTimingsTraceLog.traceBegin("ZygotePreload");
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
            SystemClock.uptimeMillis());
            //預(yù)加載系統(tǒng)資源
            preload(bootTimingsTraceLog);
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                    SystemClock.uptimeMillis());
            bootTimingsTraceLog.traceEnd(); // ZygotePreload
    } else {
        Zygote.resetNicePriority();
    }

    //fork SystemServer進(jìn)程
    if (startSystemServer) {
        Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
        // child (system_server) process.
        if (r != null) {
            r.run();
            return;
        }
    }

    //等待Socket的接入
    if (caller == null) {
        Log.i(TAG, "Accepting command socket connections");
        // The select loop returns early in the child process after a fork and
        // loops forever in the zygote.
        caller = zygoteServer.runSelectLoop(abiList);
    }

注釋寫(xiě)了大概Zygote 啟動(dòng)里面的初始化內(nèi)容

  • 創(chuàng)建Socket
  • 加載系統(tǒng)資源
  • 啟動(dòng)SystemServer
  • runSelectLoop 等待socket接入溅蛉,開(kāi)始執(zhí)行fork新的進(jìn)程.

SystemServer

下面繼續(xù)看SystemServer 啟動(dòng)的過(guò)程公浪,從Main方法開(kāi)始

//SystemServer.java
   /**
     * The main entry point from zygote.
     */
    public static void main(String[] args) {
        new SystemServer().run();
    }

很簡(jiǎn)單,創(chuàng)建一個(gè)自己的對(duì)象船侧,并執(zhí)行run方法,看一下run方法

private void run() {
    ...
    if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
        Slog.w(TAG, "System clock is before 1970; setting to 1970.");
        SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
    }

    VMRuntime.getRuntime().clearGrowthLimit();
    // The system server has to run all of the time, so it needs to be
    // as efficient as possible with its memory usage.
    VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);

    android.os.Process.setThreadPriority(
                android.os.Process.THREAD_PRIORITY_FOREGROUND);
    android.os.Process.setCanSelfBackground(false);
    Looper.prepareMainLooper();

   // Create the system service manager.
    mSystemServiceManager = new SystemServiceManager(mSystemContext);
    mSystemServiceManager.setStartInfo(mRuntimeRestart,
            mRuntimeStartElapsedTime, mRuntimeStartUptime);
    LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);

   try {
        traceBeginAndSlog("StartServices");
        startBootstrapServices();
        startCoreServices();
        startOtherServices();
        SystemServerInitThreadPool.shutdown();
    } catch (Throwable ex) {
           Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
    } finally {
        traceEnd();
    }

    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

run方法里面主要進(jìn)行了設(shè)置手機(jī)時(shí)間欠气,設(shè)置虛擬機(jī)內(nèi)存大小,創(chuàng)建消息循環(huán)Looper,創(chuàng)建SystemServiceManager等镜撩,最主要的是啟動(dòng)了各類服務(wù)预柒,我們接著看一下startBootstrapServices ,startCoreServices袁梗,startOtherServices方法

private void startBootstrapServices() {
    Installer installer = mSystemServiceManager.startService(Installer.class);
    mSystemServiceManager.startService(DeviceIdentifiersPolicyService.class);

    mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
    mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
    mActivityManagerService.setInstaller(installer);
    ....
}

private void startCoreServices() {
    ...
     mSystemServiceManager.startService(BatteryService.class);
     ...
}

 private void startOtherServices() {
        final Context context = mSystemContext;
        VibratorService vibrator = null;
        DynamicAndroidService dynamicAndroid = null;
        IStorageManager storageManager = null;
        NetworkManagementService networkManagement = null;
        IpSecService ipSecService = null;
        NetworkStatsService networkStats = null;
        NetworkPolicyManagerService networkPolicy = null;
        ConnectivityService connectivity = null;
        NsdService serviceDiscovery= null;
        WindowManagerService wm = null;
        SerialService serial = null;
        NetworkTimeUpdateService networkTimeUpdater = null;
        InputManagerService inputManager = null;
        TelephonyRegistry telephonyRegistry = null;
        ConsumerIrService consumerIr = null;
        MmsServiceBroker mmsService = null;
        HardwarePropertiesManagerService hardwarePropertiesService = null;
        ....
}

在這些方法中啟動(dòng)了宜鸯,我們的核心服務(wù),和常用服務(wù)遮怜。 代碼中也可以看到AMS淋袖,PMS,WMS等相關(guān)服務(wù).

Launcher啟動(dòng)介紹

一般服務(wù)啟動(dòng)完成后锯梁,就會(huì)想繼調(diào)用systemReady()方法适贸。 在SysytemServer startOtherServices中看到一個(gè)監(jiān)聽(tīng)回調(diào)

mActivityManagerService.systemReady(() -> {
  try {
        startSystemUi(context, windowManagerF);
    } catch (Throwable e) {
        reportWtf("starting System UI", e);
    }
  }
}

static final void startSystemUi(Context context, WindowManagerService windowManager) {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName("com.android.systemui",
                    "com.android.systemui.SystemUIService"));
        intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
        //Slog.d(TAG, "Starting service: " + intent);
        context.startServiceAsUser(intent, UserHandle.SYSTEM);
        windowManager.onSystemUiStarted();
}

而Ams啟動(dòng)完成后,顯示Launcher

//AMS.java
 public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
 ...
     startHomeActivityLocked(currentUserId, "systemReady");
     //
     mStackSupervisor.resumeFocusedStackTopActivityLocked();
 ...
 }

其實(shí)到這里大致流程就介紹完了涝桅,但是文章開(kāi)始的ActivityThread的main方法是何時(shí)被調(diào)用的拜姿,還沒(méi)回答,這里不詳細(xì)展開(kāi)冯遂,簡(jiǎn)略回答一些.

ActivityThread的main方法如何被調(diào)用的蕊肥?

AMS是管理Activity的啟動(dòng)結(jié)束等燎窘,查看AMS代碼宋彼,當(dāng)當(dāng)前啟動(dòng)的APP沒(méi)有創(chuàng)建進(jìn)程時(shí),會(huì)最終調(diào)用到ZygoteProcess阳懂,然后向 Zygote發(fā)送一個(gè)socket請(qǐng)求裸准。

resumeTopActivityLocked -> startProcessLocked -> Process.start() -> ZygoteProcess.start() -> ZygoteProcess.startViaZygote() —> ZygoteProcess.zygoteSendArgsAndGetResult()

接下來(lái)展东,看一下大致代碼

//AMS.java
private final boolean startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, boolean disableHiddenApiChecks, String abiOverride) {
            //這里entryPoint為ActivityThread
     final String entryPoint = "android.app.ActivityThread";

    return startProcessLocked(hostingType, hostingNameStr, entryPoint, app, uid, gids,
                    runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith,
                    startTime);    
}

//ZygoteProcess.java
private Process.ProcessStartResult startViaZygote(final String processClass,... ){
    ArrayList<String> argsForZygote = new ArrayList<String>();
    argsForZygote.add("--runtime-args");
    argsForZygote.add("--setuid=" + uid);
    argsForZygote.add("--setgid=" + gid);
    argsForZygote.add("--runtime-flags=" + runtimeFlags);
    argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
    if (startChildZygote) {
        argsForZygote.add("--start-child-zygote");
    }
    argsForZygote.add(processClass);
    synchronized(mLock) {
        return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
                                              useBlastulaPool,
                                              argsForZygote);
    }
}

//發(fā)起Socket請(qǐng)求,給Zygote
private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
        ArrayList<String> args,..){
    blastulaSessionSocket = zygoteState.getBlastulaSessionSocket();

    final BufferedWriter blastulaWriter = new BufferedWriter(
            new OutputStreamWriter(blastulaSessionSocket.getOutputStream()),
                                Zygote.SOCKET_BUFFER_SIZE);
    final DataInputStream blastulaReader =
    new DataInputStream(blastulaSessionSocket.getInputStream());
    blastulaWriter.write(msgStr);
    blastulaWriter.flush();
    ...
}

最終 Zygote收到請(qǐng)求調(diào)用ZygoteInit中zygoteinit方法

//ZygoteInit.java
 public static final Runnable zygoteInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) {
        if (RuntimeInit.DEBUG) {
            Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
        }

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
        RuntimeInit.redirectLogStreams();

        RuntimeInit.commonInit();
        ZygoteInit.nativeZygoteInit();
        return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
    }

在 RuntimeInit中findStaticMain炒俱,最后在ZygoteInit中執(zhí)行最終返回的這個(gè)Runnable,達(dá)到調(diào)用main方法的目的.

protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) {
        nativeSetExitWithoutCleanup(true);
        VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
        final Arguments args = new Arguments(argv);
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        return findStaticMain(args.startClass, args.startArgs, classLoader);
    }

protected static Runnable findStaticMain(String className, String[] argv,
            ClassLoader classLoader) {
        ..
        m = cl.getMethod("main", new Class[] { String[].class });
        return new MethodAndArgsCaller(m, argv);
    }

歡迎各位大佬一起交流討論盐肃,想具體學(xué)習(xí)可私信我哈

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市权悟,隨后出現(xiàn)的幾起案子砸王,更是在濱河造成了極大的恐慌,老刑警劉巖峦阁,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件谦铃,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡榔昔,警方通過(guò)查閱死者的電腦和手機(jī)驹闰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)瘪菌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人嘹朗,你說(shuō)我怎么就攤上這事师妙。” “怎么了骡显?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)曾掂。 經(jīng)常有香客問(wèn)我惫谤,道長(zhǎng),這世上最難降的妖魔是什么珠洗? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任溜歪,我火速辦了婚禮,結(jié)果婚禮上许蓖,老公的妹妹穿的比我還像新娘蝴猪。我一直安慰自己,他們只是感情好膊爪,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布自阱。 她就那樣靜靜地躺著,像睡著了一般米酬。 火紅的嫁衣襯著肌膚如雪沛豌。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,046評(píng)論 1 285
  • 那天赃额,我揣著相機(jī)與錄音加派,去河邊找鬼。 笑死跳芳,一個(gè)胖子當(dāng)著我的面吹牛芍锦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播飞盆,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼娄琉,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了吓歇?” 一聲冷哼從身側(cè)響起车胡,我...
    開(kāi)封第一講書(shū)人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎照瘾,沒(méi)想到半個(gè)月后匈棘,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡析命,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年主卫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了逃默。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡簇搅,死狀恐怖完域,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情瘩将,我是刑警寧澤吟税,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站姿现,受9級(jí)特大地震影響肠仪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜备典,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一异旧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧提佣,春花似錦吮蛹、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至倚喂,卻和暖如春然低,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背务唐。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工雳攘, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人枫笛。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓吨灭,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親刑巧。 傳聞我的和親對(duì)象是個(gè)殘疾皇子喧兄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

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