Android進程管理總結

目錄

概述

Android系統(tǒng)的進程管理理念是希望應用進程能夠盡量長時間的存活贺喝,提升用戶體驗。Android的應用進程在首次啟動的時候會比較慢死宣,因為第一次啟動的時候包含了進程的創(chuàng)建以及Application等信息的初始化,這個過程會消耗一定的時間,所以應用在啟動以后儒溉,不會輕易被殺死掉,以達到在下一次啟動的時候加快速度发钝。同樣APP自己也會使用一些手段顿涣,希望自己長時間存活。設備的內存以及一些資源是有限的酝豪,不可能承載無限多的進程運行涛碑,當進程達到一定的數(shù)量,大量消耗設備內存后孵淘,手機設備性能就會下降蒲障,如果放任所有進程一直存活下去,設備內存很快就會消耗完畢夺英。

所以系統(tǒng)需要殺死一些進程對內存進行回收晌涕,確保系統(tǒng)可以穩(wěn)定的一直運行下去。但是哪些進程應該被殺掉呢痛悯?Android系統(tǒng)會根據進程中的組件狀態(tài)來決定一個進程的優(yōu)先級adj值余黎,優(yōu)先級最低的進程會最先被殺掉,依次類推载萌,來確保系統(tǒng)正常運轉惧财。

AMS對進程的描述

Android 中AMS服務負責進程的創(chuàng)建和銷毀巡扇,Android系統(tǒng)對用戶屏蔽了進程的概念,用戶在開發(fā)自己的應用的時候無需太關系進程相關的處理垮衷。

進程在AMS中由一個ProcessRecord來表示厅翔,該對象記錄了一個進程的所有信息,但是ProcessRecord在AMS服務中只是代表一個進程搀突,真正的應用進程運行在獨立的進程中刀闷,主線程是ActivityThread。ProcessRecord的變量IApplicationThread thread用來關聯(lián)真正的進程仰迁,IApplicationThread是一個binder類甸昏,當他不為空的時候,thread持有了Binder的代理端徐许,而服務端實現(xiàn)在ActivityThread中施蜜。

Untitled Diagram (9).png

AMS可以通過IApplicationThread通知對應的進程做一些對應的操作。
ProcessRecord詳情可參考ProcessRecord分析

AMS服務創(chuàng)建進程

既然AMS負責管理進程雌隅,那么AMS是怎么創(chuàng)建一個進程的呢翻默?在什么場景下會創(chuàng)建新的進程呢?

進程的創(chuàng)建場景

  1. 啟動Activity的時候恰起,如果當前Activity的宿主進程尚未創(chuàng)建修械,則需要先創(chuàng)建對應的進程

ActivityStackSupervisor::startSpecificActivityLocked()

  1. 啟動一個Service組件的時候,Service組件的宿主進程尚未創(chuàng)建村缸,需要先創(chuàng)建對應的進程

ActiveServices::bringUpServiceLocked()

  1. 獲取一個ContentProvider組件連接的時候祠肥,ContentProvider宿主進程尚未創(chuàng)建且ContentProvider組件必須運行在其宿主進程中,需要先創(chuàng)建對應的進程

ActivityManagerService::getContentProviderImpl()

  1. 如果發(fā)送一個廣播的時候梯皿,發(fā)現(xiàn)接收該廣播的Receiver是靜態(tài)注冊的廣播仇箱,且注冊該廣播的進程尚未啟動,則需要先創(chuàng)建對應的進程

BroadcastQueue::processNextBroadcast()

  1. backup組件

ActivityManagerService::bindBackupAgent()

  1. systemServer進程啟動的時候东羹,persistent進程會被啟動

addAppLocked()

進程創(chuàng)建流程

  1. 從AMS的進程列表中查詢對應的ProcessRecord信息
  2. 如果AMS進程列表中未找到對應的ProcessRecord信息剂桥,說明進程還未啟動,需要創(chuàng)建新的進程
  3. 創(chuàng)建一個ProcessRecord來描述要創(chuàng)建進程的信息属提,并進程初始化权逗,保存到AMS的ProcessRecord列表中,此時的ProcessRecord值保存了基本的信息冤议,尚未和一個真正的進程進行關聯(lián)
  4. 為新啟動進程設置必須的參數(shù)
  5. 調用Process.start來啟動一個新的進程
  6. 將參數(shù)通過socket發(fā)送給Zygote進程斟薇,Zygote進程fork出一個新的進程,返回新創(chuàng)建的進程pid
  7. 將進程的Pid保存到ProcessRecord對象的pid變量中. AMS端創(chuàng)建進程的邏輯就執(zhí)行完成了恕酸。
  8. Zygote fork出的新進程會執(zhí)行ActivityThread.main方法堪滨,初始化新的進程,此時一個新的進程真正的運行起來了蕊温,同時也創(chuàng)建了一個IApplicationThread的服務端用于接收AMS的消息.
  9. 新進程調用AMS.attachApplicationLocked方法袱箱,將IApplicationThread的代理端發(fā)送給了AMS, AMS查找到對應的ProcessRecord對象遏乔,將Binder代理端保存到ProcessRecord的thread變量中,此時ProcessRecord對象和一個進程就關聯(lián)起來了发笔。

AMS服務查殺進程

殺死進程的方法有那些盟萨?

方法名稱 方法描述 調用角色
System.exit(0) 退出虛擬機 應用
killProcessGroup(int uid, int pid) 殺死pid所在進程組內的所有進程 系統(tǒng) 應用
killPids(int[] pids, String pReason, boolean secure) 只有系統(tǒng)UID可以調用,根據指定的pid信息計算一個worstType, 小于某一個adj的進程會被殺死了讨,不能保證指定的pid進程一定被殺掉 系統(tǒng)
killUid(int appId, int userId, String reason) 殺死UID下所有的進程捻激, system_server和native進程除外 系統(tǒng) 應用
killApplication(String pkg, int appId, int userId, String reason) 只有系統(tǒng)Uid可以調用方库,強制殺死某一個應用 系統(tǒng)
killApplicationProcess(String processName, int uid) 系統(tǒng)uid才能調用泣港,通過進程見調用通知進程自殺 系統(tǒng)
killAllBackgroundProcesses() 殺死所有優(yōu)先級小于CACHE的進程,需要權限 系統(tǒng)
killBackgroundProcesses(final String packageName, int userId) 殺死指定Package下所有優(yōu)先級小于Service的進程 系統(tǒng)
killProcessesBelowForeground(String reason) 殺死優(yōu)先級小于FOREGROUND的進程 系統(tǒng)
killProcessesBelowAdj(int belowAdj, String reason) 殺死優(yōu)先級小于指定值的進程 系統(tǒng)
killPackageDependents(String packageName, int userId) 殺死指定Package所有優(yōu)先級小于FOREGROUND的進程 系統(tǒng)
killPackageProcessesLocked 殺死指定package下小于指定優(yōu)先級的進程,非系統(tǒng)UID只能殺死自己進程 系統(tǒng) 應用

以上方法提供了殺死進程的接口残炮,用于應用或者系統(tǒng)主動殺死一些進程。這些進程會調用一些方法

  1. handleAppDiedLocked() 進程被殺死后的善后處理
    參考binderDied()過程分析
  2. forceStopPackageLocked() 強制殺死對應進程

AMS自己會根據一些邏輯來殺死部分進程缩滨, App也會主動調用ActivityManager的接口來殺死指定進程势就,當進程僥幸逃脫AMS或者應用的屠刀后,就會被保存到內存中脉漏,此時這些進程就會交由LowMemoryKiller來監(jiān)控了苞冯,這些進程的生死就轉移到了LMK的手上.

LMK進程監(jiān)控查殺

需要監(jiān)控的進程,ProcessList會通過socket將他的進程id添加到lmkd的進程列表中侧巨,同時舅锄,如果進程被殺死了,則需要通ProcessList通過socket接口通過lmkd從列表中移除司忱。這個列表就是lmkd監(jiān)控的進程列表,詳情參考LowMemoryKiller的實現(xiàn)

Android設備原始的adj閥值如圖:


原始內存閥值

Android進程分為了6個等級皇忿,對應不同內存閥值, 當lmkd監(jiān)控的系統(tǒng)內存小于某一個閥值的時候坦仍,就會開始查殺小于或等于對應優(yōu)先級的進程鳍烁,當釋放的內存達到最大閥值之后就停止查殺。

  1. 前臺進程 FOREGROUND_APP_ADJ (0)

前臺進程是指那些有組件正和用戶進行交互的應用程序的進程繁扎,也稱為Active進程幔荒。這些都是Android嘗試通過回收其他應用程序來使其保持相應的進程。這些進程的數(shù)量非常少梳玫,只有等到最后關頭才會終止這些進程爹梁,是用戶最不希望終止的進程。例如:而當你運行瀏覽器這類應用時提澎,它們的界面就會顯示在前臺姚垃,它們就屬于前臺進程,當你按home鍵回到主界面虱朵,他們就變成了后臺程序莉炉。
如果一個進程滿足以下任一條件钓账,即視為前臺進程:
(1)托管處于活動狀態(tài)的Activity,也就是說絮宁,它們位于前臺并對用戶事件進行響應梆暮,此時的情形為響應了Activity中的onResume()生命周期方法,但沒有響應onPause()绍昂。
(2)托管正在執(zhí)行onReceive()方法處理事件程序的BroadcastReceiver啦粹。
(3)托管正在執(zhí)行onStart()、onCreate()或onDestroy()事件處理程序的Service窘游。
(4)托管正在運行且被標記為在前臺運行的Service唠椭,即調用了該Service的startForeground()方法。
(5)托管某個Service忍饰,且該Service正綁定在用戶正在交互的Activity的Service贪嫂,即該Activity正處于活動狀態(tài)。

  1. 可見進程 VISIBLE_APP_ADJ (100)

沒有任何前臺組件艾蓝、但仍然會影響用戶在屏幕上所見內容的進程力崇。如果一個進程滿足以下任一條件,即視為可見進程:
(1)托管不在前臺赢织、但仍對用戶可見的Activity(已調用其onPause()方法)亮靴。例如:如果前臺Acitivty啟動了一個對話框,或者啟動了一個非全屏于置,亦或是一個透明的Activity茧吊,允許在其后顯示上一個Activity,則可能會發(fā)生這種情況八毯,這類Activity不在前臺運行搓侄,也不能對用戶事件作出反應。
(2)托管綁定到可見Activity的Service
可見進程被視為是極其重要的進程宪彩,這類進程的數(shù)量也很少休讳,只有在資源極度匱乏的環(huán)境下,為保證前臺進程繼續(xù)執(zhí)行時才會終止尿孔。

  1. 可感知進程 PERCEPTIBLE_APP_ADJ (200)

用戶可以感知到的進程俊柔,如后臺播放音樂的進程

  1. 備份進程 BACKUP_APP_ADJ (300)

處于備份過程中的進程

  1. CACHED_APP_MIN (900)

緩存進程ADJ最小值

  1. CACHED_APP_MAX (906)

緩存進程ADJ的最大值

lmkd根據以上6個等級對進程進程查殺,只要內存閥值達到某個等級活合,小于該優(yōu)先級等級的進程都屬于查殺對象雏婶。

當進程被LMK殺死后,binder死亡通知會通知AMS, AMS執(zhí)行handleAppDiedLocked來進程善后處理白指。清理該進程的信息留晚,并將該進程從AMS中移除。
LMK對進程的查殺是依賴adj等級的告嘲,但是進程adj如何進行分配的错维?這就要看下AMS對進程adj的管理策略奖地。

AMS對保存在內存中的進程管理策略

Android對進程管理是最大限度的將進程保留在內存中,在內存不夠的時候殺死一些不重要的進程赋焕,如何決定哪些進程是不重要的参歹,哪些進程是重要的,以及如何殺死進程隆判,這個就是Android進程管理的策略犬庇。

優(yōu)先級分類

ADJ取值 進程類別 含義
-1000 NATIVE_ADJ native進程
-900 SYSTEM_ADJ System_server進程
-800 PERSISTENT_PROC_ADJ 系統(tǒng)persistent進程
-700 PERSISTENT_SERVICE_ADJ 系統(tǒng)或者persistent進程綁定的進程
0 FOREGROUND_APP_ADJ 前臺進程 :和用戶交互的進程,不到萬不得已不能殺死
100 VISIBLE_APP_ADJ 可見進程:該進程的某個UI組件是可以被用戶看見的侨嘀,但是沒有和用戶進行交互臭挽,不能隨便殺死,影響用戶體驗
200 PERCEPTIBLE_APP_ADJ 可感知進程:該進程的某個組件可以被用戶感知到咬腕,如后臺音樂播放
300 BACKUP_APP_ADJ 備份進程:不可輕易打斷欢峰,否則容易引起不可修復的數(shù)據錯誤
400 HEAVY_WEIGHT_APP_ADJ 重量級進程
500 SERVICE_ADJ 服務進程
600 HOME_APP_ADJ Lanucher進程
700 PREVIOUS_APP_ADJ 上一個訪問的進程
800 SERVICE_B_ADJ B list中的進程
900 CACHED_APP_MIN_ADJ 不可見進程adj最小值
906 CACHED_APP_MAX_ADJ 不可見進程adj最大值
1001 UNKNOWN_ADJ 錯誤的adj值

Android將進程的優(yōu)先級分為以上幾種,從表格中可以看出郎汪,值越小優(yōu)先級越高赤赊,小于0的優(yōu)先級的進程基本上不會被殺死的,這些都是系統(tǒng)的重要進程煞赢,殺死之后會影響到整個系統(tǒng)的運行。

進程的優(yōu)先級是如何分配的呢哄孤?
Android的ProcessRecord中有adj變量照筑,代表當前進程的優(yōu)先級,每當系統(tǒng)中的進程組件發(fā)生變化瘦陈,就會調整某個或者調整全部進程的adj優(yōu)先級凝危。

進程的LRU列表管理

在AMS服務中對于進程管理有一系列保存進程信息ProcessRecord的容器,其中mLruProcesses列表用于按照進程的最近的使用情況晨逝,對進程進行排序保存.

 final ArrayList<ProcessRecord> mLruProcesses = new ArrayList<ProcessRecord>();

AMS將mLruProcesses列表分成了三個區(qū)域蛾默,使用兩個變量來記錄三個區(qū)域的分割點

  1. mLruProcessServiceStart 表示從這個位置之后存放包含Service相關組件的進程信息
  2. mLruProcessActivityStart 表示從這個位置之后存放包含Activity相關組件的進程信息
LRU列表

LRU列表中進程位置調整主要遵循的策略如下:

  1. 如果當前正在和用戶交互的進程放在列表的尾部
  2. 如果包含Activity的進程,但是卻不是Top進程的捉貌,放到尾部倒數(shù)第二位置
  3. 如果只包含Service的進程支鸡,放到Service部分的尾部
  4. 如果其他進程,則放到其他進程部分的尾部
    調整完當前進程的位置后趁窃,還需要調整當前進程所依賴進程的優(yōu)先級牧挣,比如依賴另一個進程的Service或者Provider,則不希望其進程被kill掉醒陆。調整依賴進程優(yōu)先級的邏輯總體如下:
  • 如果其他進程的位置被自己進程位置靠后瀑构,說明自己依賴進程優(yōu)先級本身就是比自己進程高的,這時候不需要處理
  • 如果依賴進程的是包含有Acitivity組件的刨摩,也不需要處理
  • 如果依賴進程的位置比自己靠前寺晌,優(yōu)先級被自己低世吨,則要適當?shù)膶⑵湮恢猛笳{,因為越靠近LRU列表尾部的進程呻征,說明該進程剛剛運行過另假,重要性比較高.

根據以上一系列邏輯之后,進程在LRU列表中的位置就調整完了怕犁,但是边篮,不是要調整進程的優(yōu)先級adj么?調整LRU做什么呢奏甫?LRU Cache中存放的進程是根據最近使用過的來排順序的戈轿,越是最近使用的越是靠近列表尾部,當然分為三個區(qū)域的阵子。LRU列表調整完成之后思杯,adj調整的時候就會根據LRU列表尾部開始循環(huán)遍歷計算進程的adj值, 最近使用的進程adj值會被先計算。

并不是所有的進程都會被計算adj值挠进,保存到內存中色乾,在內存中保存到進程是有限制的,比如系統(tǒng)會限制Cache類型的進程和Empty類型的進程每種最多保存16個领突,也就是最多32個. 超過32個之后的進程會被直接殺死暖璧。也就是說LRU列表中靠近底部的很久未使用的進程很可能會被AMS直接殺死,根本不會保存到內存中君旦。

進程優(yōu)先級計算

  1. 優(yōu)先級 < 0的系統(tǒng)重要進程
  • NATIVE_ADJ(-1000):是由init進程fork出來的Native進程澎办,并不受system管控;
  • SYSTEM_ADJ(-900):是指system_server進程金砍;
  • PERSISTENT_PROC_ADJ(-800): 是指在AndroidManifest.xml中申明android:persistent=”true”的系統(tǒng)(即帶有FLAG_SYSTEM標記)進程局蚀,persistent進程一般情況并不會被殺,即便被殺或者發(fā)生Crash系統(tǒng)會立即重新拉起該進程恕稠。
  • PERSISTENT_SERVICE_ADJ(-700):是由startIsolatedProcess()方式啟動的進程琅绅,或者是由system_server或者persistent進程所綁定(并且?guī)в蠦IND_ABOVE_CLIENT或者BIND_IMPORTANT)的服務進程

以上進程都是系統(tǒng)重要進程,其adj優(yōu)先級是在啟動的時候就設置好鹅巍,無需重新計算其優(yōu)先級千扶。

  1. FOREGROUND_APP_ADJ (0) 前臺進程

1:滿足以下任一條件的進程都屬于FOREGROUND_APP_ADJ(0)優(yōu)先級:
正處于resumed狀態(tài)的Activity
正執(zhí)行一個生命周期回調的Service(比如執(zhí)行onCreate,onStartCommand,onDestroy等)
正執(zhí)行onReceive()的BroadcastReceiver
通過startInstrumentation()啟動的進程
場景2: 當客戶端進程activity里面調用bindService()方法時flags帶有BIND_ADJUST_WITH_ACTIVITY參數(shù),并且該activity處于可見狀態(tài)昆著,則當前服務進程也屬于前臺進程县貌,源碼如下:
場景3: 對于provider進程,還有以下兩個條件能成為前臺進程:
當Provider的客戶端進程ADJ<=FOREGROUND_APP_ADJ時凑懂,則Provider進程ADJ等于FOREGROUND_APP_ADJ
當Provider有外部(非框架)進程依賴煤痕,也就是調用了getContentProviderExternal()方法,則ADJ至少等于FOREGROUND_APP_ADJ

  1. VISIBLE_APP_ADJ (100) 可見進程

當ActivityRecord的visible=true,也就是Activity可見的進程摆碉。
可見進程VISIBLE_APP_ADJ(100)跟PERCEPTIBLE_APP_ADJ(200)可感知進程之間有99個槽塘匣,用于細化可見進程的adj值.

調用rankTaskLayersIfNeed對TaskRecord進行排序,按照TaskRecord對VisibleApp進行細化


ActivityStack.png
  1. PERCEPTIBLE_APP_ADJ(200) 可感知進程

foregroundServices非空:前臺服務進程巷帝,執(zhí)行startForegroundService()方法
app.forcingToImportant非空:執(zhí)行setProcessImportant()方法忌卤,比如Toast彈出過程。
hasOverlayUi非空:非activity的UI位于屏幕最頂層楞泼,比如顯示類型TYPE_APPLICATION_OVERLAY的窗口

  1. BACKUP_APP_ADJ(300) 備份進程

執(zhí)行bindBackupAgent()過程驰徊,設置mBackupTarget值;
執(zhí)行clearPendingBackup()或unbindBackupAgent()過程堕阔,置空mBackupTarget值棍厂;

  1. HEAVY_WEIGHT_APP_ADJ(400) 重量級進程

realStartActivityLocked()過程,當應用的privateFlags標識PRIVATE_FLAG_CANT_SAVE_STATE超陆,設置mHeavyWeightProcess值牺弹;
finishHeavyWeightApp(), 置空mHeavyWeightProcess值

  1. SERVICE_ADJ(500) 服務進程

沒有啟動過Activity,并且30分鐘之內活躍過的服務進程

  1. HOME_APP_ADJ(600) Launcher進程

當類型為ACTIVITY_TYPE_HOME的應用啟動后會設置mHomeProcess时呀,比如桌面APP张漂。

  1. PREVIOUS_APP_ADJ(700) 上一個活動的進程

用戶上一個使用的包含UI的進程,為了給用戶在兩個APP之間更好的切換體驗谨娜,將上一個進程ADJ設置到PREVIOUS_APP_ADJ的檔次航攒。 當activityStoppedLocked()過程會更新上一個應用

當provider進程,上一次使用時間不超過20S的情況下瞧预,優(yōu)先級不低于PREVIOUS_APP_ADJ

  1. SERVICE_B_ADJ(800) B類服務進程

A類Service占比過高:當A類Service個數(shù) > Service總數(shù)的1/3時屎债,則加入到B類Service。
內存緊張&&A類Service占用內存較高:當系統(tǒng)內存緊張級別(mLastMemoryLevel)高于ADJ_MEM_FACTOR_NORMAL垢油,且該應用所占內存lastPss大于或等于CACHED_APP_MAX_ADJ級別所對應的內存閾值的1/3

以上內存參考 解讀Android進程優(yōu)先級ADJ算法, 該文章分析更加詳細

  1. Cached和Empty進程 (900 ~ 906)
    Android默認對cached進程和Empty進程有最大數(shù)量限制為32個,Cached進程和Empty進程默認上限分別都是16個圆丹。
Untitled Diagram-2.png

系統(tǒng)將900 ~ 906 這幾個adj的值分成6個卡槽滩愁,分別用來放緩存進程和空進程
分別計算當前共有多少個空進程和緩存進程,分別平均放到對應的卡槽中辫封,每個卡槽中可能會放多個進程. 每種類型的進程超過16個之后就直接kill掉硝枉,不再為其分配adj有l(wèi)mk監(jiān)控了.

進程優(yōu)先級設置

ProcessList.setOomAdj(app.pid, app.uid, app.curAdj);

其他調整

Android進程優(yōu)先級ADJ的每一個ADJ級別往往都有多種場景,使用adjType完美地區(qū)分相同ADJ下的不同場景倦微; 不同ADJ進程所對應的schedGroup不同妻味,從而分配的CPU資源也不同,schedGroup大體分為TOP(T)欣福、前臺(F)责球、后臺(B); ADJ跟AMS中的procState有著緊密的聯(lián)系。

adj:通過調整oom_score_adj來影響進程壽命(Lowmemorykiller殺進程策略)雏逾;
schedGroup:影響進程的CPU資源調度與分配嘉裤;
procState:從進程所包含的四大組件運行狀態(tài)來評估進程狀態(tài),影響framework的內存控制策略栖博。比如控制緩存進程和空進程個數(shù)上限依賴于procState屑宠,再比如控制APP執(zhí)行handleLowMemory()的觸發(fā)時機等。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末仇让,一起剝皮案震驚了整個濱河市典奉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌丧叽,老刑警劉巖卫玖,帶你破解...
    沈念sama閱讀 211,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蠢正,居然都是意外死亡骇笔,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評論 3 385
  • 文/潘曉璐 我一進店門嚣崭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來笨触,“玉大人,你說我怎么就攤上這事雹舀÷樱” “怎么了?”我有些...
    開封第一講書人閱讀 157,435評論 0 348
  • 文/不壞的土叔 我叫張陵说榆,是天一觀的道長虚吟。 經常有香客問我,道長签财,這世上最難降的妖魔是什么串慰? 我笑而不...
    開封第一講書人閱讀 56,509評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮唱蒸,結果婚禮上邦鲫,老公的妹妹穿的比我還像新娘。我一直安慰自己神汹,他們只是感情好庆捺,可當我...
    茶點故事閱讀 65,611評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著屁魏,像睡著了一般滔以。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上氓拼,一...
    開封第一講書人閱讀 49,837評論 1 290
  • 那天你画,我揣著相機與錄音抵碟,去河邊找鬼。 笑死撬即,一個胖子當著我的面吹牛立磁,可吹牛的內容都是我干的。 我是一名探鬼主播剥槐,決...
    沈念sama閱讀 38,987評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼唱歧,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了粒竖?” 一聲冷哼從身側響起颅崩,我...
    開封第一講書人閱讀 37,730評論 0 267
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蕊苗,沒想到半個月后沿后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 44,194評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡朽砰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,525評論 2 327
  • 正文 我和宋清朗相戀三年尖滚,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瞧柔。...
    茶點故事閱讀 38,664評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡漆弄,死狀恐怖,靈堂內的尸體忽然破棺而出造锅,到底是詐尸還是另有隱情撼唾,我是刑警寧澤,帶...
    沈念sama閱讀 34,334評論 4 330
  • 正文 年R本政府宣布哥蔚,位于F島的核電站倒谷,受9級特大地震影響,放射性物質發(fā)生泄漏糙箍。R本人自食惡果不足惜渤愁,卻給世界環(huán)境...
    茶點故事閱讀 39,944評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望深夯。 院中可真熱鬧猴伶,春花似錦、人聲如沸塌西。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,764評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽捡需。三九已至,卻和暖如春筹淫,著一層夾襖步出監(jiān)牢的瞬間站辉,已是汗流浹背呢撞。 一陣腳步聲響...
    開封第一講書人閱讀 31,997評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留饰剥,地道東北人殊霞。 一個月前我還...
    沈念sama閱讀 46,389評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像汰蓉,于是被迫代替她去往敵國和親绷蹲。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,554評論 2 349

推薦閱讀更多精彩內容