Android 進(jìn)程管理概述

一、task_struct

Android的進(jìn)程管理建立在Linux內(nèi)核的基礎(chǔ)上颁湖。Linux內(nèi)核通過一個被稱為進(jìn)程描述符的task_struct結(jié)構(gòu)體來管理進(jìn)程宣蠕,這個結(jié)構(gòu)體包含了一個進(jìn)程所需的所有信息。它定義在include/linux/sched.h文件中或者Android的kernel/msm-4.9/include/linux/sched.h中甥捺。包含一下的信息:


image

其中抢蚀,進(jìn)程的狀態(tài)有以下取值:


image

二、進(jìn)程創(chuàng)建流程

idle進(jìn)程 -> init進(jìn)程 -> zygote進(jìn)程 -> system_server進(jìn)程 →App進(jìn)程
他們之間的關(guān)系如下:


image

64位下有兩個zygote镰禾,zygote64和zygote皿曲。64位應(yīng)用的父進(jìn)程是zygote64,它的pgid也是zygote64的pid吴侦;32位應(yīng)用的父進(jìn)程是zygote屋休,它的pgid卻是zygote64的pid,如:com.ss.android.article.news的父進(jìn)程是zygote(1112)备韧,但它的pgid是zygote64(1111)劫樟,這是怎么回事呢?原來不管32位或64位的zygote织堂,它在創(chuàng)建完子進(jìn)程后叠艳,會調(diào)用setChildPgid()來改變子進(jìn)程的pgid捧挺。


image

多個進(jìn)程組還可以構(gòu)成一個會話 (session)翅睛,sid標(biāo)識會話id捕发,Android中進(jìn)程的sid基本都是0。

一張更為詳細(xì)的圖:


image

ZygoteServer啟動過程:


image

Zygote本身是一個Native的應(yīng)用程序法挨,剛開始的名字為“app_process”窃植,運(yùn)行過程中巷怜,通過調(diào)用setArgv0將名字改為Zygote延塑。
ZygoteInit進(jìn)程啟動后,會注冊一個Socket豫缨,在runSelectLoop方法中開啟一個while死循環(huán)等待ActivityManagerService創(chuàng)建新進(jìn)程的請求,其次冲呢,ZygoteInit啟動了SystemServer進(jìn)程敬拓,執(zhí)行SystemServer的main方法。
Socket通信框架:


image

LocalSocket就是作為客戶端建立于服務(wù)端的連接营勤,發(fā)送數(shù)據(jù)葛作。LocalServerSocket作為服務(wù)端使用,建立服務(wù)端的socket監(jiān)聽客戶端請求虱岂,典型的C/S架構(gòu)

三、如何創(chuàng)建一個進(jìn)程

#inlucde<unistd.h>
#inlucde<stdio.h>
#inlucde<wait.h>
int main(){
  int count = 0;
  pid_t fpid = fork();
  if( fpid < 0){
    printf("創(chuàng)建子進(jìn)程失敗");
  } else if( fpid == 0){
    printf("子進(jìn)程Id:%d\n",getpid());
  } else {
    printf("父進(jìn)程Id:%d\n",getpid());
  }
  printf("count=%d\n",count);
  waitpid(fpid,NULL,0); // 暫時(shí)停止目前進(jìn)程的執(zhí)行难菌,直到有信號來到或子進(jìn)程結(jié)束
  return 0;
}
  1. fork函數(shù)執(zhí)行一次,返回兩次猎塞,第一次返回父進(jìn)程的id荠耽,第二次返回子進(jìn)程的id铝量。
  2. count是全局變量慢叨,子進(jìn)程和父進(jìn)程同時(shí)操作拍谐,但是互相不受影響

fork()使用寫時(shí)復(fù)制轩拨,copy-on-write,是一種可以推遲甚至避免拷貝數(shù)據(jù)的技術(shù)砍濒。內(nèi)核此時(shí)并不復(fù)制整個進(jìn)程的地址空間梯影,而是讓父子進(jìn)程共享同一個地址空間甲棍。只用在需要寫入的時(shí)候才會復(fù)制地址空間七扰,從而使各個進(jìn)行擁有各自的地址空間颈走。如下圖所示,同左到右大的方向箭頭表示復(fù)制內(nèi)容:


image

為這四個部分分配物理塊锐膜,P2的:正文段-->PI的正文段的物理塊道盏,指的是不為P2分配正文段塊,讓P2的正文段指向P1的正文段塊种远,數(shù)據(jù)段-->P2自己的數(shù)據(jù)段塊(為其分配對應(yīng)的塊)院促,堆-->P2自己的堆塊,棧-->P2自己的棧塊辉浦。

一個進(jìn)程有正文段宪郊、數(shù)據(jù)段弛槐、堆和棧等段乎串,內(nèi)核只為新生成的子進(jìn)程創(chuàng)建虛擬空間結(jié)構(gòu)叹誉,它們來復(fù)制于父進(jìn)程的虛擬空間結(jié)構(gòu)钧唐,但是不為這些段分配物理內(nèi)存钝侠,它們共享父進(jìn)程的物理空間,當(dāng)父子進(jìn)程中有更改相應(yīng)段的行為發(fā)生時(shí)弱匪,再為子進(jìn)程相應(yīng)的段分配物理空間萧诫。
對應(yīng)到Android系統(tǒng)中:


image

4、Zygote進(jìn)程預(yù)加載資源

android系統(tǒng)資源加載分兩種方式及刻,預(yù)加載和使用進(jìn)程中加載。 預(yù)加載是指在zygote進(jìn)程啟動的時(shí)候就加載颗搂,這樣系統(tǒng)只在zygote執(zhí)行一次加載操作丢氢,所有APP用到該資源不需要再重新加載,減少資源加載時(shí)間貌嫡,加快了應(yīng)用啟動速度嫁艇,一般情況下步咪,系統(tǒng)中App共享的資源會被列為預(yù)加載資源。

預(yù)加載的內(nèi)容:


image

上面文件中列舉的四千多個類都要通過Class.forName加載到系統(tǒng)中,生成字節(jié)碼
preload的過程主要發(fā)生在ZygoteInit.preload()函數(shù)里面:

static void preload(TimingsTraceLog bootTimingsTraceLog) {
        Log.d(TAG, "begin preload");
        beginIcuCachePinning();
        preloadClasses();
        preloadResources();
        nativePreloadAppProcessHALs();
        preloadOpenGL();
        preloadSharedLibraries();
        preloadTextResources();
        WebViewFactory.prepareWebViewInZygote();
        endIcuCachePinning();
        warmUpJcaProviders();
        Log.d(TAG, "end preload");

        sPreloadComplete = true;
    }

會輸出以下log:

Zygote  : begin preload
Zygote  : Preloading ICU data...
Zygote  : Preloading classes...
Zygote  : ...preloaded 6558 classes in 441ms.
Zygote64Timing: PreloadClasses took to complete: 545ms
Zygote  : Preloading resources...
Zygote  : ...preloaded 86 resources in 45ms.
Zygote  : ...preloaded 41 resources in 2ms.
Zygote  : Preloading shared libraries...
Zygote  : end preload

可見preload加載的有類,資源闰挡,共享庫长酗。系統(tǒng)中有大量的資源可以直接被App所使用,比如一個顏色咧叭,一個drawble,這些都是通過preloadResources加載的听想。

4衔峰、進(jìn)程優(yōu)先級

進(jìn)程管理主要涉及到兩個值:
adj:通過調(diào)整oom_score_adj來影響進(jìn)程壽命(Lowmemorykiller殺進(jìn)程策略)威彰;
schedGroup:影響進(jìn)程的CPU資源調(diào)度與分配歇盼;
adj,即進(jìn)程的優(yōu)先級粗略劃分如下:

image

前臺進(jìn)程:正在與用戶進(jìn)行交互的進(jìn)程
可見進(jìn)程:可在屏幕上顯示但不在前臺運(yùn)行,比如一個前臺進(jìn)程以對話框的形式顯示在該進(jìn)程前面氮惯。典型的如輸入法。
服務(wù)進(jìn)程:正在運(yùn)行已使用 startService() 方法啟動的服務(wù)且不屬于上述兩個更高類別進(jìn)程的進(jìn)程铛纬。盡管服務(wù)進(jìn)程與用戶所見內(nèi)容沒有直接關(guān)聯(lián),但是它們通常在執(zhí)行一些用戶關(guān)心的操作(例如唬滑,在后臺播放音樂或從網(wǎng)絡(luò)下載數(shù)據(jù))告唆。
后臺進(jìn)程:包含目前對用戶不可見的 Activity 的進(jìn)程(已調(diào)用 Activity 的 onStop() 方法)。這些進(jìn)程對用戶體驗(yàn)沒有直接影響晶密,系統(tǒng)可能隨時(shí)終止它們擒悬,以回收內(nèi)存供前臺進(jìn)程、可見進(jìn)程或服務(wù)進(jìn)程使用稻艰。
空進(jìn)程:不含任何活動應(yīng)用組件的進(jìn)程懂牧。保留這種進(jìn)程的的唯一目的是用作緩存,以縮短下次在其中運(yùn)行組件所需的啟動時(shí)間。

image

進(jìn)程的優(yōu)先級取決于進(jìn)程四大組件的運(yùn)行狀態(tài)尸变。例如Activity是否在前臺痛垛,用戶是否可見蹂析;Service正在被哪些客戶端使用;ContentProvider正在被哪些客戶端使用;BroadcastReceiver是否正在接受廣播
ProcessRecord中有以下成員變量:

// all activities running in the process
final ArrayList<ActivityRecord> activities = new ArrayList<>();
// any tasks this process had run root activities in
final ArrayList<TaskRecord> recentTasks = new ArrayList<>();
// all ServiceRecord running in this process
final ArraySet<ServiceRecord> services = new ArraySet<>();
// services that are currently executing code (need to remain foreground).
final ArraySet<ServiceRecord> executingServices = new ArraySet<>();
// All ConnectionRecord this process holds
final ArraySet<ConnectionRecord> connections = new ArraySet<>();
// all IIntentReceivers that are registered from this process.
final ArraySet<ReceiverList> receivers = new ArraySet<>();
// class (String) -> ContentProviderRecord
final ArrayMap<String, ContentProviderRecord> pubProviders = new ArrayMap<>();
// All ContentProviderRecord process is using
final ArrayList<ContentProviderConnection> conProviders = new ArrayList<>();

activities 記錄了進(jìn)程中運(yùn)行的Activity
services,executingServices 記錄了進(jìn)程中運(yùn)行的Service
receivers 記錄了進(jìn)程中運(yùn)行的BroadcastReceiver
pubProviders 記錄了進(jìn)程中運(yùn)行的ContentProvider
而:
connections 記錄了對于Service連接
conProviders 記錄了對于ContentProvider的連接

連接的意義在于:連接的客戶端的進(jìn)程優(yōu)先級會影響被使用的Service和ContentProvider所在進(jìn)程的優(yōu)先級它匕。 例如:當(dāng)一個后臺的Service正在被一個前臺的Activity使用烧给,那么這個后臺的Service就需要設(shè)置一個較高的優(yōu)先級以便不會被回收榴鼎。(否則后臺Service進(jìn)程一旦被回收,便會對前臺的Activity造成影響心赶。)

ADJ的具體數(shù)值:

級別 常量名稱 簡述
-1000 NATIVE_ADJ 并不被系統(tǒng)管理的native進(jìn)程的優(yōu)先級
-900 SYSTEM_ADJ 系統(tǒng)進(jìn)程
-800 PERSISTENT_PROC_ADJ 系統(tǒng)級常駐進(jìn)程咏闪,比如telephony
-700 PERSISTENT_SERVICE_ADJ 關(guān)聯(lián)著系統(tǒng)進(jìn)程或者常駐進(jìn)程的進(jìn)程
0 FOREGROUND_APP_ADJ 前臺APP
100 VISIBLE_APP_ADJ 可見APP
200 PERCEPTIBLE_APP_ADJ 可感知的APP
300 BACKUP_APP_ADJ 正在備份的進(jìn)程
400 HEAVY_WEIGHT_APP_ADJ 后臺重量級進(jìn)程,在system/rootdir.init.rc中配置
500 SERVICE_ADJ 正在運(yùn)行這service的進(jìn)程
600 HOME_APP_ADJ 桌面進(jìn)程
700 PREVIOUS_APP_ADJ 上一個APP的進(jìn)程(通過back返回)
800 SERVICE_B_ADJ List B中的service進(jìn)程(區(qū)分于上一個 service list瓶籽,更老裤唠、使用到的可能性更胁着)
900 CACHED_APP_MIN_ADJ 緩存進(jìn)程的最小值
906 CACHED_APP_MAX_ADJ 緩存進(jìn)程的最大值

以上各值數(shù)值越小椅贱,優(yōu)先級越高

BACKUP_APP_ADJ(300):執(zhí)行bindBackupAgent()過程的進(jìn)程
HEAVY_WEIGHT_APP_ADJ(400): realStartActivityLocked()過程舍悯,當(dāng)應(yīng)用的privateFlags標(biāo)識PRIVATE_FLAG_CANT_SAVE_STATE的進(jìn)程馁蒂;

進(jìn)程由SERVICE_ADJ(500)降低到SERVICE_B_ADJ(800),有以下兩種情況:
A類Service占比過高:當(dāng)A類Service個數(shù) > Service總數(shù)的1/3時(shí),則加入到B類Service。換句話說蝙云,B Service的個數(shù)至少是A Service的2倍。

內(nèi)存緊張&&A類Service占用內(nèi)存較高:當(dāng)系統(tǒng)內(nèi)存緊張級別(mLastMemoryLevel)高于ADJ_MEM_FACTOR_NORMAL垢揩,且該應(yīng)用所占內(nèi)存lastPss大于或等于CACHED_APP_MAX_ADJ級別所對應(yīng)的內(nèi)存閾值的1/3(默認(rèn)值閾值約等于110MB)悬包。

Android P開始垫释,進(jìn)一步細(xì)化VISIBLE_APP_ADJ級別:


image

從Android P開始,進(jìn)一步細(xì)化ADJ級別,增加了VISIBLE_APP_LAYER_ MAX(99)吁朦,是指VISIBLE_APP_ADJ(100)跟PERCEPTIBLE_APP_ADJ(200)之間有99個槽,則可見級別ADJ的取值范圍為[100,199]擂仍。 算法會根據(jù)其所在task的mLayerRank來調(diào)整其ADJ囤屹,100加上mLayerRank就等于目標(biāo)ADJ,layer越大逢渔,則ADJ越小肋坚。

如何查看進(jìn)程優(yōu)先級:

  1. cat proc/[pid]/oom_score_adj
  2. adb shell dumpsys activity o/p

5、進(jìn)程的回收

image

LMK基本原理

所有應(yīng)用進(jìn)程都是從zygote孵化出來的肃廓,記錄在AMS中mLruProcesses列表中智厌,由AMS進(jìn)行統(tǒng)一管理,AMS中會根據(jù)進(jìn)程的狀態(tài)更新進(jìn)程對應(yīng)的oom_adj值盲赊,這個值會通過文件傳遞到kernel中去铣鹏,kernel有個低內(nèi)存回收機(jī)制,在內(nèi)存達(dá)到一定閥值時(shí)會觸發(fā)清理oom_adj值高的進(jìn)程騰出更多的內(nèi)存空間哀蘑,這就是LowMemoryKiller工作原理诚卸。

LMK基本實(shí)現(xiàn)方案

根據(jù)不同手機(jī)的配置,就有對應(yīng)的殺進(jìn)程標(biāo)準(zhǔn)绘迁,這個標(biāo)準(zhǔn)用minfree和adj兩個文件來定義:
/sys/module/lowmemorykiller/parameters/minfree:里面是以","分割的一組數(shù)合溺,每個數(shù)字代表一個內(nèi)存級別。
/sys/module/lowmemorykiller/parameters/adj:對應(yīng)上面的一組數(shù)缀台,每個數(shù)組代表一個進(jìn)程優(yōu)先級級別
例如:

$ adb shell cat /sys/module/lowmemorykiller/parameters/minfree
18432,23040,27648,32256,85296,120640
$ adb shell cat /sys/module/lowmemorykiller/parameters/adj
0,100,200,300,900,906

Minfree是一個閾值棠赛,它跟內(nèi)存大小和分辨率有關(guān)系,通過ProcessList中updateOomLevels計(jì)算設(shè)置的,這里的adj并不是直接對應(yīng)ProcessList中定義的恭朗。
而是adj*17/1000=ProcessList文件里面的值

對于應(yīng)用進(jìn)程來說屏镊,也需要有自身的adj,由AMS負(fù)責(zé)更新痰腮。定義在oom_adj和oom_score_adj文件中:
/proc/pid/oom_adj:代表當(dāng)前進(jìn)程的優(yōu)先級而芥,這個優(yōu)先級是kernel中的優(yōu)先級。
/proc/pid/oom_score_adj:這個是AMS上層的優(yōu)先級膀值,與ProcessList中的優(yōu)先級對應(yīng)棍丐,例如:


image

LMK回收過程

image

用戶在啟動一個進(jìn)程之后,通常伴隨著啟動一個Activity游覽頁面或者一個Service播放音樂等等沧踏,這個時(shí)候此進(jìn)程的adj被AMS提高歌逢,LMK就不會殺死這個進(jìn)程,當(dāng)這個進(jìn)程要做的事情做完了翘狱,退出后臺了秘案,此進(jìn)程的adj很快又被AMS降低。
當(dāng)需要?dú)⑺酪粋€進(jìn)程釋放內(nèi)存時(shí)潦匈,一般先根據(jù)當(dāng)前手機(jī)剩余內(nèi)存的狀態(tài)阱高,在minfree節(jié)點(diǎn)中找到當(dāng)前等級,再根據(jù)這個等級去adj節(jié)點(diǎn)中找到這個等級應(yīng)該殺掉的進(jìn)程的優(yōu)先級茬缩, 之后遍歷所有進(jìn)程并比較進(jìn)程優(yōu)先級adj與優(yōu)先級閾值赤惊,并殺死優(yōu)先級低于閾值的進(jìn)程,達(dá)到釋放內(nèi)存的目的


image

AMS負(fù)責(zé)更新各應(yīng)用的進(jìn)程優(yōu)先級與閾值數(shù)組
lmkd負(fù)責(zé)接收AMS傳輸過來的數(shù)據(jù)然后寫入到sys與proc節(jié)點(diǎn)
lowmemorykiller則在內(nèi)存低于閾值時(shí)才會被觸發(fā)并負(fù)責(zé)殺死低優(yōu)先級的進(jìn)程凰锡。

AMS.updateConfiguration:更新窗口配置未舟,這個過程中,分別向/sys/module/lowmemorykiller/parameters目錄下的minfree和adj節(jié)點(diǎn)寫入相應(yīng)數(shù)值掂为;
AMS.applyOomAdjLocked:應(yīng)用adj裕膀,當(dāng)需要?dú)⒌裟繕?biāo)進(jìn)程則返回false;否則返回true勇哗,這個過程中魂角,調(diào)用setOomAdj(),向/proc/pid/oom_score_adj寫入oom_adj 后直接返回;
AMS.cleanUpApplicationRecordLocked & AMS.handleAppDiedLocked:進(jìn)程死亡后智绸,調(diào)用remove()野揪,直接返回;

時(shí)序圖:


image

AMS:


image

Lmkd.c:


image
image

LMK殺進(jìn)程過程:


image

入口是__init函數(shù), register_shrinker(&lowmem_shrinker);
關(guān)鍵點(diǎn)1:其實(shí)就是確定當(dāng)前低內(nèi)存對應(yīng)的閾值;
關(guān)鍵點(diǎn)2 :找到比該閾值優(yōu)先級低瞧栗,并且內(nèi)存占用較多的進(jìn)程(tasksize = get_mm_rss(p->mm)其實(shí)就是獲取內(nèi)存占用)斯稳。如何殺死的呢?很直接迹恐,通過Linux的中的信號量挣惰,發(fā)送SIGKILL信號直接將進(jìn)程殺死。
到這就分析完了LomemoryKiller內(nèi)核部分如何工作的。其實(shí)很簡單憎茂,一句話:被動掃描珍语,找到低優(yōu)先級的進(jìn)程,殺死竖幔。

onTrimMemory和onLowMemory

Activity, Service, ContentProvider和Application都實(shí)現(xiàn)了這個接口

應(yīng)用處于Runnig狀態(tài)可能收到的級別
TRIM_MEMORY_RUNNING_MODERATE 表示系統(tǒng)內(nèi)存已經(jīng)稍低
TRIM_MEMORY_RUNNING_LOW 表示系統(tǒng)內(nèi)存已經(jīng)相當(dāng)?shù)?br> TRIM_MEMORY_RUNNING_CRITICAL 表示系統(tǒng)內(nèi)存已經(jīng)非常低板乙,你的應(yīng)用程序應(yīng)當(dāng)考慮釋放部分資源

應(yīng)用的可見性發(fā)生變化時(shí)收到的級別
TRIM_MEMORY_UI_HIDDEN 表示應(yīng)用已經(jīng)處于不可見狀態(tài),可以考慮釋放一些與顯示相關(guān)的資源

應(yīng)用處于后臺時(shí)可能收到的級別
TRIM_MEMORY_BACKGROUND 表示系統(tǒng)內(nèi)存稍低拳氢,你的應(yīng)用被殺的可能性不大募逞。但可以考慮適當(dāng)釋放資源
TRIM_MEMORY_MODERATE 表示系統(tǒng)內(nèi)存已經(jīng)較低,當(dāng)內(nèi)存持續(xù)減少馋评,你的應(yīng)用可能會被殺死
TRIM_MEMORY_COMPLETE 表示系統(tǒng)內(nèi)存已經(jīng)非常低放接,你的應(yīng)用即將被殺死,請釋放所有可能釋放的資源

這里的通知也是來自ActivityManagerService留特,在updateOomAdjLocked的時(shí)候纠脾,ActivityManagerService會根據(jù)系統(tǒng)內(nèi)存以及應(yīng)用的狀態(tài)通過app.thread.scheduleTrimMemory發(fā)送通知給應(yīng)用程序。

如果你不釋放資源蜕青,那么請看上面的算法:找到比該閾值優(yōu)先級低乳乌,并且內(nèi)存占用較多的進(jìn)程,你的應(yīng)用將最先被干掉

想學(xué)習(xí)更多Android知識市咆,或者獲取相關(guān)資料請加入Android技術(shù)開發(fā)交流2群:935654177。本群可免費(fèi)獲取Gradle再来,RxJava蒙兰,小程序,Hybrid芒篷,移動架構(gòu)搜变,NDK,React Native针炉,性能優(yōu)化等技術(shù)教程挠他!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市篡帕,隨后出現(xiàn)的幾起案子殖侵,更是在濱河造成了極大的恐慌,老刑警劉巖镰烧,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拢军,死亡現(xiàn)場離奇詭異,居然都是意外死亡怔鳖,警方通過查閱死者的電腦和手機(jī)茉唉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人度陆,你說我怎么就攤上這事艾凯。” “怎么了懂傀?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵趾诗,是天一觀的道長。 經(jīng)常有香客問我鸿竖,道長沧竟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任缚忧,我火速辦了婚禮悟泵,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘闪水。我一直安慰自己糕非,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布球榆。 她就那樣靜靜地躺著朽肥,像睡著了一般。 火紅的嫁衣襯著肌膚如雪持钉。 梳的紋絲不亂的頭發(fā)上衡招,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機(jī)與錄音每强,去河邊找鬼始腾。 笑死,一個胖子當(dāng)著我的面吹牛空执,可吹牛的內(nèi)容都是我干的浪箭。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼辨绊,長吁一口氣:“原來是場噩夢啊……” “哼奶栖!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起门坷,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤宣鄙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后默蚌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體框冀,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年敏簿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了明也。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宣虾。...
    茶點(diǎn)故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖温数,靈堂內(nèi)的尸體忽然破棺而出绣硝,到底是詐尸還是另有隱情,我是刑警寧澤撑刺,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布鹉胖,位于F島的核電站,受9級特大地震影響够傍,放射性物質(zhì)發(fā)生泄漏甫菠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一冕屯、第九天 我趴在偏房一處隱蔽的房頂上張望寂诱。 院中可真熱鬧,春花似錦安聘、人聲如沸痰洒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽丘喻。三九已至,卻和暖如春念颈,著一層夾襖步出監(jiān)牢的瞬間泉粉,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工榴芳, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留嗡靡,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓翠语,卻偏偏與公主長得像,于是被迫代替她去往敵國和親财边。 傳聞我的和親對象是個殘疾皇子肌括,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評論 2 354

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