【筆記】php內(nèi)核相關(guān)閱讀筆記:php7哀蘑、sapi、生命周期

此文章是讀書筆記,個(gè)人底層欠火候绘迁。文章的圖或找或自己試著畫一下楼吃。盡量少的抄書躲叼。

準(zhǔn)備

php 5.6忌锯、php 7.0.12 各一份

使用 vscode 凭疮,配置(vscode代替source insight

phpstudy 方便切換各種版本測代碼。

centos7的虛擬機(jī)膛腐,方便后續(xù)的使用睛约。

流程圖用的是https://www.processon.com

php 7變化

抽象語法樹

php5.x

PHP代碼在語法解析階段直接生成了ZendVM指令。zend_language_parse.y中生成opline指令

缺點(diǎn):編譯器與執(zhí)行器耦合在一起

php7

將php代碼解析成抽象語法樹,將抽象語法樹編譯為ZendVM指令

優(yōu)點(diǎn): php的編譯器與執(zhí)行器很好地隔離開哲身,編譯器不需要關(guān)心指令的生成規(guī)則痰腮,然后執(zhí)行器根據(jù)自己的規(guī)則將抽象語法樹編譯為對應(yīng)的指令。

Native TLS

php 5.x :

多線程環(huán)境不能簡單通過全局變量實(shí)現(xiàn)律罢,為適應(yīng)多線程應(yīng)用環(huán)境膀值。

php提供了一個(gè)線程安全資源管理器,將全局資源進(jìn)行線程隔離误辑,不同的線程互不干擾

php 7

使用Native TLS(線程局部存儲(chǔ))保存線程的資源池沧踏,__tread標(biāo)識(shí)一個(gè)全局變量,全局變量就是線程獨(dú)享巾钉,不同線程修改不會(huì)影響

指定函數(shù)參數(shù)翘狱、返回值類型

zval結(jié)構(gòu)變化

php 5.x

zend.h

zval

struct _zval_struct {
    /* Variable information */
    zvalue_value value;     /* value */
    zend_uint refcount__gc;
    zend_uchar type;    /* active type */
    zend_uchar is_ref__gc;
};

value

typedef union _zvalue_value {
    long lval;                  /* long value */
    double dval;                /* double value */
    struct {
        char *val;
        int len;
    } str;
    HashTable *ht;              /* hash table value */
    zend_object_value obj;
    zend_ast *ast;
} zvalue_value;

缺點(diǎn)

php5.x的引用計(jì)數(shù)在在zval中而不是在 value中,復(fù)制變量需要復(fù)制兩個(gè)結(jié)構(gòu)砰苍,zval跟value 始終綁定在一起

php 7

zend_types.h

zval

struct _zval_struct {
    zend_value        value;            /* value */
    union {
        struct {
            ZEND_ENDIAN_LOHI_4(
                zend_uchar    type,         /* active type */
                zend_uchar    type_flags,
                zend_uchar    const_flags,
                zend_uchar    reserved)     /* call info for EX(This) */
        } v;
        uint32_t type_info;
    } u1;
    union {
        uint32_t     var_flags;
        uint32_t     next;                 /* hash collision chain */
        uint32_t     cache_slot;           /* literal cache slot */
        uint32_t     lineno;               /* line number (for ast nodes) */
        uint32_t     num_args;             /* arguments number for EX(This) */
        uint32_t     fe_pos;               /* foreach position */
        uint32_t     fe_iter_idx;          /* foreach iterator index */
    } u2;
};

value

typedef union _zend_value {
    zend_long         lval;             /* long value */
    double            dval;             /* double value */
    zend_refcounted  *counted;
    zend_string      *str;
    zend_array       *arr;
    zend_object      *obj;
    zend_resource    *res;
    zend_reference   *ref;
    zend_ast_ref     *ast;
    zval             *zv;
    void             *ptr;
    zend_class_entry *ce;
    zend_function    *func;
    struct {
        uint32_t w1;
        uint32_t w2;
    } ww;
} zend_value;

優(yōu)點(diǎn):

引用計(jì)數(shù)在具體value(元素zend_refcounted )中潦匈,zval只是載體,value才是真正的值

php變量之間復(fù)制赚导、傳遞更加簡潔茬缩、易懂

zval結(jié)構(gòu)大小從24byte減少到了16byte,也是php7能夠降低系統(tǒng)資源的一個(gè)優(yōu)化點(diǎn)

異常處理

php5.x

很多操作會(huì)拋出error錯(cuò)誤

php7

將多數(shù)錯(cuò)誤改為了異常拋出吼旧,這樣就可以通過try catch 捕捉到了

調(diào)用未定義函數(shù)凰锡。示例代碼:

try {
    call();
} catch (Throwable $e) {
    echo $e->getMessage();
}

php5.6:Fatal error: Call to undefined function call() in E:\isoftbox\phpstudy\WWW\1.php on line 4

php7輸出:Call to undefined function call()

HashTable

php7,hashtable結(jié)構(gòu)的大小從72byte減小到了56byte圈暗。數(shù)組元素bucket從72byte減少到了32byte

php的構(gòu)成

php的構(gòu)成

SAPI層適配不同的執(zhí)行場景掂为。常用的如下:

 apache2handler
 cgi
 cli
 embed #嵌入式
 fpm
 litespeed #LiteSpeed 一種被特別設(shè)計(jì)用作大型網(wǎng)站的商業(yè)web服務(wù)器。 其中一個(gè)優(yōu)勢就是它能直接讀取Apache 的配置信息员串。并輕易將它現(xiàn)有的產(chǎn)品結(jié)合在一起來代替Apache 勇哗。這種服務(wù)器是輕量級的就如它的名字暗示出非常快寸齐。

ZendVM

ZendVM兩部分組成:編譯器欲诺、執(zhí)行器抄谐。

Extension

擴(kuò)展分為PHP擴(kuò)展、Zend擴(kuò)展(應(yīng)用于ZendVM比如Opcache)

目錄

build/
ext/
main/
netware/
pear/
sapi/
scripts/
tests/
travis/
TSRM/
win32/
Zend/

生命周期

模塊初始化瞧栗、請求初始化斯稳、執(zhí)行腳本階段海铆、請求關(guān)閉階段迹恐、模塊關(guān)閉階段

php聲明周期

在main/main.c文件中能看到對應(yīng)的函數(shù)定義。

不同的sapi場景使用不同的方法卧斟。

image.png

拿fpm舉例

main() ,殴边,在文件/sapi/fpm/fpm/fpm_main.c。main函數(shù)中能看到調(diào)用的情況珍语。

模塊初始化階段

php_module_startup 函數(shù)(./main/main.c)

未命名文件 (3).jpg

主要干了:

  • 激活SAPI:sapi_activate()(函數(shù)的定義在./main/SAPI.c锤岸,之后看到sapi開頭就找sapi.c)

初始化請求信息

……
/*初始化請求信息*/
SG(sapi_headers).send_default_content_type = 1;

/*
SG(sapi_headers).http_response_code = 200;
*/
SG(sapi_headers).http_status_line = NULL;
SG(sapi_headers).mimetype = NULL;
SG(headers_sent) = 0;
ZVAL_UNDEF(&SG(callback_func));
SG(read_post_bytes) = 0;
SG(request_info).request_body = NULL;
……

處理請求,讀取post 數(shù)據(jù)板乙,讀取cookie是偷。

/* Handle request method 處理請求方法*/
if (SG(server_context)) {
    if (PG(enable_post_data_reading)
    &&  SG(request_info).content_type
    &&  SG(request_info).request_method
    && !strcmp(SG(request_info).request_method, "POST")) {
        /* HTTP POST may contain form data to be processed into variables
            * depending on given content type 
            * HTTP POST可能包含要根據(jù)給定內(nèi)容類型處理為變量的表單數(shù)據(jù)
            * */
        sapi_read_post_data();
    } else {
        SG(request_info).content_type_dup = NULL;
    }

    /* Cookies  讀取Cookie*/
    SG(request_info).cookie_data = sapi_module.read_cookies();

    if (sapi_module.activate) {
        sapi_module.activate();
    }
}
if (sapi_module.input_filter_init) {
    sapi_module.input_filter_init();
}
  • 啟動(dòng)php輸出:php_output_startup()。
PHPAPI void php_output_startup(void)
{
    ZEND_INIT_MODULE_GLOBALS(output, php_output_init_globals, NULL);
    zend_hash_init(&php_output_handler_aliases, 8, NULL, NULL, 1);
    zend_hash_init(&php_output_handler_conflicts, 8, NULL, NULL, 1);
    zend_hash_init(&php_output_handler_reverse_conflicts, 8, NULL, reverse_conflict_dtor, 1);
    php_output_direct = php_output_stdout;
}

分析參考 跟廠長學(xué)PHP7內(nèi)核(五):系統(tǒng)分析生命周期

  • 初始化垃圾回收器:gc_globals_ctor()(文件./Zend/zend_gc.c募逞,含有g(shù)c_ 開頭的你懂的)蛋铆,分配zend_gc_globals內(nèi)存
ZEND_API void gc_globals_ctor(void)
{
#ifdef ZTS /* 線程安全 執(zhí)行ts_allocate_id,繼續(xù)追這個(gè)函數(shù)就能看到tsrm_mutex_lock放接、tsrm_mutex_unlock*/
    ts_allocate_id(&gc_globals_id, sizeof(zend_gc_globals), (ts_allocate_ctor) gc_globals_ctor_ex, (ts_allocate_dtor) root_buffer_dtor);
#else
    gc_globals_ctor_ex(&gc_globals);
#endif
}

更多關(guān)于內(nèi)存分配參考 PHP新的垃圾回收機(jī)制:Zend GC詳解

  • 啟動(dòng)zend引擎:zend_startup()
……
start_memory_manager(); /*啟動(dòng)內(nèi)存池*/

/* Set up utility functions and values 
    設(shè)置一些util函數(shù)句柄
    */
zend_error_cb = utility_functions->error_function;
zend_printf = utility_functions->printf_function;
zend_write = (zend_write_func_t) utility_functions->write_function;
zend_fopen = utility_functions->fopen_function;

/* 設(shè)置 Zend 虛擬機(jī)編譯刺啦、執(zhí)行器的函數(shù)句柄 zend_compile_file、zend_execute_ex */
#if HAVE_DTRACE
/* build with dtrace support */
    zend_compile_file = dtrace_compile_file;
    zend_execute_ex = dtrace_execute_ex;
    zend_execute_internal = dtrace_execute_internal;
#else
    zend_compile_file = compile_file;
    zend_execute_ex = execute_ex;
    zend_execute_internal = NULL;
#endif /* HAVE_SYS_SDT_H */
    zend_compile_string = compile_string;
    zend_throw_exception_hook = NULL;

    /* Set up the default garbage collection implementation. 
        設(shè)置垃圾回收的函數(shù)句柄
    */
    gc_collect_cycles = zend_gc_collect_cycles;

    /*分配函數(shù)符號表(CG(function_table))纠脾、類符號表(CG(class_table))玛瘸、常量符號表
(EG(zend_constants))等,這個(gè)CG是非線程安全下的一個(gè)宏定義 # define GLOBAL_FUNCTION_TABLE      CG(function_table)*/
    GLOBAL_FUNCTION_TABLE = (HashTable *) malloc(sizeof(HashTable));
    GLOBAL_CLASS_TABLE = (HashTable *) malloc(sizeof(HashTable));
    GLOBAL_AUTO_GLOBALS_TABLE = (HashTable *) malloc(sizeof(HashTable));
    GLOBAL_CONSTANTS_TABLE = (HashTable *) malloc(sizeof(HashTable));


#ifdef ZTS
    /*如果是多線程的話苟蹈,還會(huì)分配編譯器糊渊、執(zhí)行器的全局變
量*/
    ts_allocate_id(&executor_globals_id, sizeof(zend_executor_globals), (ts_allocate_ctor) executor_globals_ctor, (ts_allocate_dtor) executor_globals_dtor);
……

/* 注冊 zend核心擴(kuò)展,擴(kuò)展是內(nèi)核提供的慧脱,該過程將注冊Zend核心擴(kuò)展提供的函數(shù)再来,比如:strlen、define磷瘤、func_get_args芒篷、class_exists等*/
zend_startup_builtin_functions();
/*注冊 Zend 定義的標(biāo)準(zhǔn)常量:zend_register_standard_constants(),比如:E_ERROR采缚、
E_WARNING针炉、E_ALL、TRUE扳抽、FALSE 等*/
zend_register_standard_constants();
/* 注冊$GLOBALS 超全局變量的獲取 handler */
zend_register_auto_global(zend_string_init("GLOBALS", sizeof("GLOBALS") - 1, 1), 1, php_auto_globals_create_globals);
/*分配 php.ini 配置的存儲(chǔ)符號表:*/
zend_ini_startup();
  • 注冊php定義的常量
REGISTER_MAIN_STRINGL_CONSTANT("PHP_VERSION", PHP_VERSION, sizeof(PHP_VERSION)-1, CONST_PERSISTENT | CONST_CS);
    REGISTER_MAIN_LONG_CONSTANT("PHP_MAJOR_VERSION", PHP_MAJOR_VERSION, CONST_PERSISTENT | CONST_CS);
    REGISTER_MAIN_LONG_CONSTANT("PHP_MINOR_VERSION", PHP_MINOR_VERSION, CONST_PERSISTENT | CONST_CS);
……
  • 解析php.ini:解析完成后所有的 php.ini 配置保存在 configuration_hash 哈希表中(php_init_config()篡帕,在php_ini.c)
if (php_init_config() == FAILURE) {
    return FAILURE;
}

*映射 PHP殖侵、Zend 核心的 php.ini 配置:根據(jù)解析出的 php.ini,獲取對應(yīng)的配置值镰烧,將
最終的配置插入 EG(ini_directives)哈希表拢军。

/* Register PHP core ini entries  注冊 php 核心 ini 入口*/ 
    REGISTER_INI_ENTRIES();
  • 注冊用于獲取_GET、_POST怔鳖、_COOKIE茉唉、_SERVER、_ENV结执、_REQUEST度陆、$_FILES
    變量的 handler。
php_startup_auto_globals();/* 具體定義在./main/php_variables.c*/
  • 注冊靜態(tài)編譯的擴(kuò)展:php_register_internal_extensions_func()

  • 注冊動(dòng)態(tài)加載的擴(kuò)展:php_ini_register_extensions()

  • 回調(diào)各擴(kuò)展定義的 module starup 鉤子函數(shù)献幔,即通過 PHP_MINIT_FUNCTION()定義的函數(shù)懂傀。

  • 禁用php.ini 配置的函數(shù)與類。默認(rèn)disable_functions =蜡感、disable_classes =蹬蚁。

php_disable_functions();
php_disable_classes();

請求初始化

int php_request_startup(void)

請求初始化

主要處理:

  • 激活輸出:php_output_activate()

  • 激活Zend引擎:zend_activate()

ZEND_API void zend_activate(void) /* {{{ */
{
#ifdef ZTS
    virtual_cwd_activate();
#endif
    gc_reset();/* 重置垃圾回收器 */
    init_compiler(); /* 初始化編譯器 */
    init_executor(); /* 初始化執(zhí)行器 */
    startup_scanner();/* 初始化詞法掃描器*/
}
  • 激活SAPI:sapi_activate()(注意:模塊初始化階段也做了這件事情)

  • 回調(diào)個(gè)擴(kuò)展定義的request startup鉤子函數(shù):zend_activate_modules()(文件./Zend/zend_API.c)


ZEND_API void zend_activate_modules(void) /* {{{ */
{
    zend_module_entry **p = module_request_startup_handlers;

    while (*p) {
        zend_module_entry *module = *p;

        if (module->request_startup_func(module->type, module->module_number)==FAILURE) {
            zend_error(E_WARNING, "request_startup() for %s module failed", module->name);
            exit(1);
        }
        p++;
    }
}

執(zhí)行腳本階段

php_execute_script(),包括php代碼編譯郑兴、執(zhí)行兩個(gè)核心階段(zend引擎最重要的功能)犀斋。編譯階段,php腳本經(jīng)歷從PHP源碼到抽象語法樹再到opline指令的轉(zhuǎn)化過程杈笔,生成zend引擎識(shí)別的執(zhí)行指令(opline指令)闪水,指令被執(zhí)行器執(zhí)行,php解釋執(zhí)行的過程蒙具。

執(zhí)行腳本階段
ZEND_API int zend_execute_scripts(int type, zval *retval, int file_count, ...) /* {{{ */
{
    va_list files;
    int i;
    zend_file_handle *file_handle;
    zend_op_array *op_array;

    va_start(files, file_count);
    for (i = 0; i < file_count; i++) {
        file_handle = va_arg(files, zend_file_handle *);
        if (!file_handle) {
            continue;
        }
        /* 編譯 opcodes(詞法球榆、語法分析—)*/
        op_array = zend_compile_file(file_handle, type);
        if (file_handle->opened_path) {
            zend_hash_add_empty_element(&EG(included_files), file_handle->opened_path);
        }
        zend_destroy_file_handle(file_handle);
        if (op_array) {
            /* 指令執(zhí)行  */
            zend_execute(op_array, retval);
            zend_exception_restore();
            zend_try_exception_handler();
            if (EG(exception)) {
                zend_exception_error(EG(exception), E_ERROR);
            }
            destroy_op_array(op_array);
            efree_size(op_array, sizeof(zend_op_array));
        } else if (type==ZEND_REQUIRE) {
            va_end(files);
            return FAILURE;
        }
    }
    va_end(files);

    return SUCCESS;
}
ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type)
{
    zend_lex_state original_lex_state;
    zend_op_array *op_array = NULL;
    zend_save_lexical_state(&original_lex_state);

    if (open_file_for_scanning(file_handle)==FAILURE) {
        if (type==ZEND_REQUIRE) {
            zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename);
            zend_bailout();
        } else {
            zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename);
        }
    } else {
        zend_bool original_in_compilation = CG(in_compilation);
        CG(in_compilation) = 1;

        CG(ast) = NULL;
        CG(ast_arena) = zend_arena_create(1024 * 32);
        /* yacc 不斷調(diào)用re2cc掃描token生成抽象語法樹*/
        if (!zendparse()) {
            zval retval_zv;
            zend_file_context original_file_context;
            zend_oparray_context original_oparray_context;
            zend_op_array *original_active_op_array = CG(active_op_array);
            op_array = emalloc(sizeof(zend_op_array));
            init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE);
            CG(active_op_array) = op_array;
            ZVAL_LONG(&retval_zv, 1);

            if (zend_ast_process) {
                zend_ast_process(CG(ast));
            }

            zend_file_context_begin(&original_file_context);
            zend_oparray_context_begin(&original_oparray_context);
            /* 從抽象語法樹 生成 op_array*/
            zend_compile_top_stmt(CG(ast));
            zend_emit_final_return(&retval_zv);
            op_array->line_start = 1;
            op_array->line_end = CG(zend_lineno);
            pass_two(op_array);
            zend_oparray_context_end(&original_oparray_context);
            zend_file_context_end(&original_file_context);

            CG(active_op_array) = original_active_op_array;
        }

        zend_ast_destroy(CG(ast));
        zend_arena_destroy(CG(ast_arena));
        CG(in_compilation) = original_in_compilation;
    }

    zend_restore_lexical_state(&original_lex_state);
    return op_array;
}

請求關(guān)閉階段

php_request_shutdown()
這個(gè)階段將flush輸出內(nèi)容、發(fā)送HTTP應(yīng)答header頭禁筏、清理全局變量持钉、關(guān)閉編譯器、關(guān)閉執(zhí)行器等篱昔。還會(huì)回調(diào)各擴(kuò)展的request shutdown 鉤子函數(shù)每强。這個(gè)階段是請求初始化相反的操作,與初始化階段處理一一對應(yīng)州刽。

請求關(guān)閉階段
    /* 1. Call all possible shutdown functions registered with register_shutdown_function() */
    if (PG(modules_activated)) zend_try {
        php_call_shutdown_functions();
    } zend_end_try();

    /* 2. Call all possible __destruct() functions */
    zend_try {
        zend_call_destructors();
    } zend_end_try();

    /* 3. Flush all output buffers */
    zend_try {
        zend_bool send_buffer = SG(request_info).headers_only ? 0 : 1;

        if (CG(unclean_shutdown) && PG(last_error_type) == E_ERROR &&
            (size_t)PG(memory_limit) < zend_memory_usage(1)
        ) {
            send_buffer = 0;
        }

        if (!send_buffer) {
            php_output_discard_all();
        } else {
            php_output_end_all();
        }
    } zend_end_try();

    /* 4. Reset max_execution_time (no longer executing php code after response sent) */
    zend_try {
        zend_unset_timeout();
    } zend_end_try();

    /* 5. Call all extensions RSHUTDOWN functions */
    if (PG(modules_activated)) {
        zend_deactivate_modules();
    }

    /* 6. Shutdown output layer (send the set HTTP headers, cleanup output handlers, etc.) */
    zend_try {
        php_output_deactivate();
    } zend_end_try();

    /* 7. Free shutdown functions */
    if (PG(modules_activated)) {
        php_free_shutdown_functions();
    }

    /* 8. Destroy super-globals */
    zend_try {
        int i;

        for (i=0; i<NUM_TRACK_VARS; i++) {
            zval_ptr_dtor(&PG(http_globals)[i]);
        }
    } zend_end_try();

    /* 9. free request-bound globals */
    php_free_request_globals();

    /* 10. Shutdown scanner/executor/compiler and restore ini entries */
    zend_deactivate();

    /* 11. Call all extensions post-RSHUTDOWN functions */
    zend_try {
        zend_post_deactivate_modules();
    } zend_end_try();

    /* 12. SAPI related shutdown (free stuff) */
    zend_try {
        sapi_deactivate();
    } zend_end_try();

    /* 13. free virtual CWD memory */
    virtual_cwd_deactivate();

    /* 14. Destroy stream hashes */
    zend_try {
        php_shutdown_stream_hashes();
    } zend_end_try();

    /* 15. Free Willy (here be crashes) */
    zend_interned_strings_restore();
    zend_try {
        shutdown_memory_manager(CG(unclean_shutdown) || !report_memleaks, 0);
    } zend_end_try();

    /* 16. Reset max_execution_time */
    zend_try {
        zend_unset_timeout();
    } zend_end_try();

模塊關(guān)閉階段

php_module_shutdown()

該階段與模塊初始化階段對應(yīng)空执,主要進(jìn)行資源清理、php各模塊的關(guān)閉操作穗椅,回調(diào)各擴(kuò)展的module shutdown鉤子函數(shù)辨绊。

php_module_shutdown()
    sapi_flush();

    zend_shutdown();/* 清理持久化符號表 */

    /* Destroys filter & transport registries too */
    php_shutdown_stream_wrappers(module_number);

    UNREGISTER_INI_ENTRIES(); /* 清理ini hashTable 元素*/

    /* close down the ini config */
    php_shutdown_config();

#ifndef ZTS
    zend_ini_shutdown();
    shutdown_memory_manager(CG(unclean_shutdown), 1);
#else
    zend_ini_global_shutdown(); /* 銷毀 EG(ini_directive*/
#endif

    php_output_shutdown(); /* 關(guān)閉output */

    module_initialized = 0;

#ifndef ZTS
    core_globals_dtor(&core_globals); /*釋放 PG*/
    gc_globals_dtor();
#else
    ts_free_id(core_globals_id);
#endif

參考資料:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市匹表,隨后出現(xiàn)的幾起案子门坷,更是在濱河造成了極大的恐慌宣鄙,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件默蚌,死亡現(xiàn)場離奇詭異冻晤,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)绸吸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進(jìn)店門鼻弧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人惯裕,你說我怎么就攤上這事温数⌒逑酰” “怎么了蜻势?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長鹉胖。 經(jīng)常有香客問我握玛,道長,這世上最難降的妖魔是什么甫菠? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任挠铲,我火速辦了婚禮,結(jié)果婚禮上寂诱,老公的妹妹穿的比我還像新娘拂苹。我一直安慰自己,他們只是感情好痰洒,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布瓢棒。 她就那樣靜靜地躺著,像睡著了一般丘喻。 火紅的嫁衣襯著肌膚如雪脯宿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天泉粉,我揣著相機(jī)與錄音连霉,去河邊找鬼。 笑死嗡靡,一個(gè)胖子當(dāng)著我的面吹牛跺撼,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播讨彼,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼歉井,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了点骑?” 一聲冷哼從身側(cè)響起酣难,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤谍夭,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后憨募,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體紧索,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年菜谣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了珠漂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,675評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡尾膊,死狀恐怖媳危,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情冈敛,我是刑警寧澤待笑,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站抓谴,受9級特大地震影響暮蹂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜癌压,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一仰泻、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧滩届,春花似錦集侯、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至券犁,卻和暖如春术健,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背粘衬。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工荞估, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人稚新。 一個(gè)月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓勘伺,卻偏偏與公主長得像,于是被迫代替她去往敵國和親褂删。 傳聞我的和親對象是個(gè)殘疾皇子飞醉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評論 2 360