深入解析Mac OS X & iOS 操作系統(tǒng) 學(xué)習(xí)筆記(十一)

Mach 原語(yǔ):一切以消息為媒介

XNU 的核心是Mach 微內(nèi)核靴姿。 Mach 是 OS X 和 iOS 的核心中的核心葵萎。盡管Mach 核心被 BSD 層包裝起來(lái)了,而且主要的內(nèi)核接口是標(biāo)準(zhǔn)的POSIX 系統(tǒng)調(diào)用扇住,但是這個(gè)Mach 核心具有一組獨(dú)特的API和原語(yǔ)缝其。

Mach 設(shè)計(jì)原則

Mach 采用的是極簡(jiǎn)主義的概念:具有一個(gè)簡(jiǎn)單最小的核心,支持面向?qū)ο蟮哪P图烧ぃ沟锚?dú)立的具有良好定義的組件(實(shí)際上就是子系統(tǒng))可以通過(guò)消息的方式互相通訊车酣。在Mach 中,所有的東西都是通過(guò)自己的對(duì)象實(shí)現(xiàn)的索绪。進(jìn)程(在Mach 中稱為任務(wù))湖员、線程、虛擬內(nèi)存都是對(duì)象者春,所有對(duì)象都有自己的屬性。其實(shí)對(duì)象就是C語(yǔ)言結(jié)構(gòu)體加上函數(shù)指針清女。Mach 的獨(dú)特之處在于選擇了通過(guò)消息傳遞的方式實(shí)現(xiàn)對(duì)象和對(duì)象之間的通信钱烟。XNU 的“官方”API 是BSD 的POSIX API,蘋果保持Mach絕對(duì)的極簡(jiǎn)嫡丙。由于外層具有非常豐富的Cocoa API拴袭,所以很多開(kāi)發(fā)者都根本意識(shí)不到Mach的存在。不過(guò)曙博,Mach調(diào)用仍然是整個(gè)架構(gòu)中最基礎(chǔ)的部分拥刻。

Mach 設(shè)計(jì)目標(biāo)

Mach的手機(jī)文檔列出了一些設(shè)計(jì)目標(biāo),其中首要目標(biāo)就是將所有功能移出內(nèi)核父泳,并放在用戶態(tài)中般哼,將內(nèi)核保持在極簡(jiǎn)的狀態(tài):

  • “控制點(diǎn)”或執(zhí)行單元(線程)管理
  • 線程或線程組(任務(wù))的資源分配
  • 虛擬內(nèi)存分配和管理
  • 底層物理資源:即CPU吴汪、內(nèi)存和任何其他物理設(shè)備的分配

Mach 消息

Mac 中最基本的概念就是消息了,消息在兩個(gè)端點(diǎn)(endpoint)或端口(port)之間傳遞蒸眠。消息是Mach IPC 的核心構(gòu)建塊漾橙。Mach 消息的設(shè)計(jì)考慮了參數(shù)串行話、對(duì)齊楞卡、填充(padding霜运,為了對(duì)齊)和字節(jié)順序的問(wèn)題。

發(fā)送消息

Mach 消息的發(fā)送和接收都是通過(guò)同一個(gè)API函數(shù) mach_msg( )進(jìn)行的蒋腮。這個(gè)函數(shù)在用戶態(tài)和內(nèi)核中都有實(shí)現(xiàn)的淘捡。Mach 消息原本是為真正的微內(nèi)核架構(gòu)而設(shè)計(jì)的。也就是說(shuō)池摧,mach_msg( )函數(shù)必須在發(fā)送者和接收者之間復(fù)制消息所在的內(nèi)存焦除。盡管這種實(shí)現(xiàn)忠實(shí)于微內(nèi)核的范式,但是事實(shí)證明頻繁內(nèi)存復(fù)制操作帶來(lái)的性能損耗是不能忍受的险绘,因此踢京,XNU 算是通過(guò)單一內(nèi)核的方式“作弊”:所有的內(nèi)核組件都共享一個(gè)地址空間,因此消息傳遞只需要傳遞消息的指針就可以了宦棺,從而省去了昂貴的內(nèi)存復(fù)制操作瓣距。
為了實(shí)現(xiàn)消息的發(fā)送和接收,mach_msg( ) 函數(shù)調(diào)用了一個(gè)Mach 陷阱(trap)代咸。Mach 陷阱就是和系統(tǒng)調(diào)用的概念蹈丸,在用戶態(tài)調(diào)用mach_msg_trap( ) 會(huì)引發(fā)陷阱機(jī)制,切換到內(nèi)核態(tài)呐芥,在內(nèi)核態(tài)中逻杖,內(nèi)核實(shí)現(xiàn)的mach_msg( ) 會(huì)完成實(shí)際的工作。

端口

消息在端點(diǎn)(也稱為端口)之間傳遞思瘟,端口只不過(guò)是32為整型的標(biāo)識(shí)符荸百。所有的mach 原生對(duì)象都是通過(guò)對(duì)于的端口訪問(wèn)的。也就是說(shuō)滨攻,查找一個(gè)對(duì)象的句柄(handle)時(shí)够话,實(shí)際上請(qǐng)求的是這個(gè)對(duì)象端口的句柄。

深入IPC

IPC 所需要的基本原語(yǔ):消息光绕、發(fā)送和接收消息的端口女嘲,以及確保安全并發(fā)的信號(hào)量和鎖。每一個(gè)Mach 任務(wù)(進(jìn)程的高級(jí)抽象)包含一個(gè)指針指向自己的IPC 名稱空間诞帐,在名稱空間中保存了自己的端口欣尼。此外,任務(wù)也可以獲得系統(tǒng)范圍內(nèi)的端口停蕉,例如主機(jī)端口愕鼓、特權(quán)端口和其他端口钙态。導(dǎo)出給用戶空間的端口對(duì)象實(shí)際上是對(duì)“真正”端口對(duì)象的一個(gè)句柄。

消息傳遞的實(shí)現(xiàn)

用戶態(tài)的Mach消息傳遞使用mach_msg( )函數(shù)拒啰。這個(gè)函數(shù)通過(guò)內(nèi)核的Mach 陷阱機(jī)制調(diào)用內(nèi)核函數(shù)mach_msg_trap( ) 驯绎。然后mach_msg_trap( )調(diào)用 mach_msg_overwrite_trap( ),mach_msg_overwrite_trap( ) 通過(guò)測(cè)試MACH_SEND_MSG和MACH_REV_MSG標(biāo)志位來(lái)判斷發(fā)送操作還是接收操作

發(fā)送消息

Mach 消息發(fā)送的邏輯在內(nèi)核中的兩處實(shí)現(xiàn):Mach_msg_overwrite_trap( ) 和 mach_msg_send( )谋旦。后者只用于內(nèi)核態(tài)的消息傳遞剩失,在用戶態(tài)不可見(jiàn)。
兩種情形的邏輯都差不多册着,遵循以下的流程:

  • 調(diào)用current_space( ) 獲得當(dāng)前的IPC空間
  • 調(diào)用current_map( ) 獲得的當(dāng)前的VM空間(vm_map)
  • 對(duì)消息的大小進(jìn)行正確性檢查
  • 計(jì)算要分配的消息大兴┕隆:從send_size參數(shù)獲得大小,然后加上硬編碼的MAX_REAILER_SIZE
  • 通過(guò)ipc_kmsg_alloc 分配消息
  • 復(fù)制消息(復(fù)制消息send_size字節(jié)的部分)甲捏,然后在消息頭設(shè)置msgh_size
  • 復(fù)制消息關(guān)聯(lián)的端口權(quán)限演熟,然后通過(guò)ipc_kmsg_copyin 將所有out-of-line 數(shù)據(jù)內(nèi)存復(fù)制到當(dāng)前的vm_map。ipc_kmsg_copyin 函數(shù)調(diào)用了ipc_kmsg_copyin_header 和 ipc_kmsg_copyin_body
  • 調(diào)用ipc_kmsg_send( )發(fā)送消息:
  • 首先司顿,獲得msgh_remote_port 引用芒粹,并鎖定端口
  • 如果端口是一個(gè)內(nèi)核端口(即端口的ip_receiver是內(nèi)核IPC空間),那么通過(guò)ipc_kobject_server( ) 函數(shù)處理消息大溜。這個(gè)函數(shù)會(huì)在內(nèi)核中找到相應(yīng)的函數(shù)來(lái)執(zhí)行消息(或者調(diào)用ipc_kobject_notify( )來(lái)執(zhí)行)化漆,而且一個(gè)會(huì)生成消息的應(yīng)答。
  • 不論是哪種端口:也就是說(shuō)如果端口不在內(nèi)核空間中钦奋,或者從ipc_kobjct_server( ) 返回了應(yīng)答座云,這個(gè)函數(shù)會(huì)貫穿到傳遞消息(或應(yīng)答消息)的部分,調(diào)用ipc_mqueue_send( )付材,這個(gè)函數(shù)將消息直接復(fù)制到端口的ip_messgaes 隊(duì)列中并喚醒任何正在等待的線程
** 接收消息**

和消息發(fā)送的情形類似朦拖,Mach 消息接收的邏輯也是現(xiàn)在內(nèi)核中的兩個(gè)地方,和發(fā)送一樣厌衔,mach_msg_overwrite_trap( ) 從用戶態(tài)接收請(qǐng)求璧帝,而內(nèi)核態(tài)通過(guò)mach_msg_receive( ) 接收消息

  • 調(diào)用current_space( ) 獲得當(dāng)前的IPC空間
  • 調(diào)用current_map( ) 獲得當(dāng)前的VM控件(vm_map)
  • 不對(duì)消息的大小進(jìn)行檢查。這種檢查沒(méi)有必要富寿,因?yàn)橄⒃诎l(fā)送時(shí)已經(jīng)驗(yàn)證過(guò)了
  • 通過(guò)調(diào)用ipc_mqueue_copyin( ) 獲得IPC隊(duì)列
  • 持有當(dāng)前線程的一個(gè)引用睬隶。使用當(dāng)前線程的引用可使它適應(yīng)使用Mach 的續(xù)體(continuation)模型,續(xù)體模型可以避免維護(hù)完整線程棧的必要性
  • 調(diào)用ipc_mqueue_receive( )從隊(duì)列中取出消息
  • 最后作喘,調(diào)用mach_msg_receive_results( ) 函數(shù)理疙。這個(gè)函數(shù)也可以從續(xù)體中調(diào)用

同步原語(yǔ)

消息傳遞機(jī)制只是Mach IPC架構(gòu)中的一個(gè)組件晕城。另一個(gè)組件是同步機(jī)制(synchronization)泞坦,同步機(jī)制用于判定兩個(gè)或多個(gè)并發(fā)的操作如何訪問(wèn)共享資源。Mach 的同步原語(yǔ)如下表

對(duì)象 所有者 空可見(jiàn)性 等待
互斥體(lck_mtx_t) 1個(gè) 內(nèi)核態(tài) 阻塞
信號(hào)量(semaphore_t) 多個(gè) 用戶態(tài) 阻塞
自旋鎖(hw_lock_t等) 1個(gè) 內(nèi)核態(tài) 忙等
鎖集(lock_set_t) 一個(gè) 用戶態(tài) 阻塞

Mach 的鎖也是由兩個(gè)層次組合而成的:

  • 硬件相關(guān)層:依賴于硬件的特殊性質(zhì)砖顷,并且通過(guò)特定的匯編指令實(shí)現(xiàn)原子性和互斥性
  • ** 硬件無(wú)關(guān)層**:通過(guò)統(tǒng)一的API包裝硬件特定的調(diào)用贰锁。這些API使得Mach 之上的層(或用戶 API)完全不用關(guān)心實(shí)現(xiàn)的細(xì)節(jié)赃梧,這通常是通過(guò)一組簡(jiǎn)單的宏實(shí)現(xiàn)的
鎖組對(duì)象

大部分Mach 同步對(duì)象都不是自己獨(dú)立存在的,而是屬于一個(gè) lck_grp_t 對(duì)象豌熄。lck_grp_t 就是一個(gè)鏈表中的一個(gè)元素授嘀,帶有一個(gè)給定的名字,以及最多3種鎖的類型:自旋鎖锣险、互斥鎖和讀寫鎖蹄皱。鎖組還帶有統(tǒng)計(jì)信息(lck_grp_stat_t 數(shù)據(jù)結(jié)構(gòu)),用于調(diào)試和同步相關(guān)的問(wèn)題芯肤。在Mach 和 BSD 中幾乎每一個(gè)子系統(tǒng)在初始化時(shí)都會(huì)創(chuàng)建一個(gè)自己使用的鎖組巷折。

互斥體對(duì)象

互斥體是最常用的鎖對(duì)象⊙伦桑互斥體定義為lck_mtx_t锻拘,互斥體必須屬于一個(gè)鎖組。

讀寫鎖對(duì)象

互斥體有一個(gè)最大的缺點(diǎn)击蹲,就是一次只能有一個(gè)線程持有鎖署拟。在很多情況下,多個(gè)線程可能對(duì)資源請(qǐng)求只讀的訪問(wèn)歌豺,這些情況下推穷,使用互斥鎖會(huì)阻止并發(fā)訪問(wèn)。讀寫鎖(read-write lock)就是問(wèn)題的解決方案世曾。讀寫鎖是個(gè)“更智能”的互斥體缨恒,能夠區(qū)分讀訪問(wèn)和寫訪問(wèn)。多個(gè)讀者可以同時(shí)持有鎖轮听,而一次只能有一個(gè)寫者可以獲得鎖骗露。

自旋鎖對(duì)象

互斥體和信號(hào)量都是阻塞等待的對(duì)象。阻塞等待的意思是說(shuō):如果鎖對(duì)象被其他線程持有血巍,那么請(qǐng)求訪問(wèn)的線程就被加入到等待隊(duì)列中萧锉,因而被阻塞。阻塞一個(gè)線程就意味著放棄線程的時(shí)間片述寡,把處理器讓給調(diào)度器認(rèn)為下一個(gè)要執(zhí)行的線程柿隙。當(dāng)鎖可用時(shí),調(diào)度器會(huì)得到通知鲫凶,然后根據(jù)自己的判斷將線程從等待隊(duì)列中取出并重新調(diào)度禀崖。然而這個(gè)方式可能會(huì)嚴(yán)重地影響性能,由于在很多情況下螟炫,鎖對(duì)象只需要持有短短幾個(gè)周期的時(shí)間波附,因而造成了兩次或更多次的上下文切換帶來(lái)的開(kāi)銷則要大好幾個(gè)數(shù)量級(jí)。這種情況下,如果線程不是放棄處理器掸屡,而是重復(fù)地嘗試訪問(wèn)鎖對(duì)象可能是更明智的選擇封寞,這種方式稱之為“忙等(busy-wait)”,如果當(dāng)前鎖的持有者確實(shí)在幾個(gè)周期后就放棄鎖了仅财,那么這樣就可以節(jié)省至少兩次上下文切換狈究。當(dāng)然這個(gè)鎖要慎用,否則很可能進(jìn)入一個(gè)非痴登螅可怕的死鎖場(chǎng)景抖锥,導(dǎo)致整個(gè)系統(tǒng)陷入停滯狀態(tài)。

信號(hào)量對(duì)象

Mach 提供了信號(hào)量(semaphore)碎罚,信號(hào)量是泛化的互斥體宁改。互斥體的值只能是0和1魂莫,而信號(hào)量的值這樣的一種互斥體还蹲。取值可以達(dá)到某個(gè)正數(shù),即允許并發(fā)持有信號(hào)量的持有者的個(gè)數(shù)耙考,換句話說(shuō)谜喊,互斥體可以看成是二值信號(hào)量的特殊情況业舍。信號(hào)量可以在用戶態(tài)使用鉴吹,而互斥體只能在內(nèi)核態(tài)使用。信號(hào)量本身是一個(gè)不可鎖的對(duì)象梅猿。信號(hào)量對(duì)象是一個(gè)很小的結(jié)構(gòu)體鞋邑,包含指向所有者和端口的引用诵次。此外,還保護(hù)桿一個(gè)wait_queue_t枚碗,這是一個(gè)保存正在等待這個(gè)信號(hào)量的線程的鏈表逾一。wait_queue_t會(huì)通過(guò)硬件所的方式鎖定。信號(hào)量還有一個(gè)有意思的屬性:信號(hào)量可以轉(zhuǎn)換為端口肮雨,也可以由端口轉(zhuǎn)換而來(lái)遵堵。

鎖集對(duì)象

任務(wù)可以在用戶態(tài)使用鎖集。鎖集就是鎖(實(shí)際上就是互斥體)的數(shù)組怨规。通過(guò)給定的鎖ID 可以訪問(wèn)鎖陌宿。鎖也可以傳遞給其他線程。交出一個(gè)鎖會(huì)阻塞交出鎖的線程波丰,并喚醒接受鎖的線程壳坪。鎖集實(shí)際上是對(duì)內(nèi)核互斥體lck_mtx_t的封裝,如下圖所示:

通過(guò)互斥體實(shí)現(xiàn)鎖集的過(guò)程.png

鎖集的有趣之處在于允許鎖的傳遞掰烟。鎖的傳遞指是將鎖從一個(gè)任務(wù)傳遞給另一個(gè)任務(wù)的過(guò)程爽蝴。Mach 在調(diào)度中也使用了傳遞的概念扩灯,允許一個(gè)線程放棄處理器但是指定哪一個(gè)線程接替允許。

機(jī)器原語(yǔ)

Mach 通過(guò)一些所謂的“機(jī)器原語(yǔ)”對(duì)運(yùn)行的機(jī)器進(jìn)行抽象霜瘪,機(jī)器原語(yǔ)處理的對(duì)象包括主機(jī)、時(shí)鐘惧磺、處理器以及處理器集颖对。

主機(jī)對(duì)象

Mach 最基礎(chǔ)的對(duì)象是“主機(jī)(host)”,也就是表示機(jī)器本身的對(duì)象磨隘。主機(jī)對(duì)象是一個(gè)簡(jiǎn)單的數(shù)據(jù)結(jié)構(gòu)缤底。主機(jī)只不過(guò)是一組“特殊端口”的集合(用于向主機(jī)發(fā)送各種消息),以及一組異常處理程序的集合番捂。主機(jī)定于了一個(gè)鎖組用于保護(hù)異常處理的并發(fā)訪問(wèn)个唧。
主機(jī)的數(shù)據(jù)結(jié)構(gòu)主要有三個(gè)基本功能:

  • 提供機(jī)器信息:Mach 提供了一組異常豐富的API調(diào)用用于查詢機(jī)器信息,所有這些調(diào)用都要求獲得主機(jī)端口才能工作设预。
  • 提供子系統(tǒng)的訪問(wèn):通過(guò)主機(jī)抽象徙歼,應(yīng)用程序可以請(qǐng)求訪問(wèn)子系統(tǒng)使用的任何“特殊”端口。此外鳖枕,還可以獲得所有其他機(jī)器抽象(例如:processor 和 processor_set)的訪問(wèn)權(quán)魄梯。
  • 提供默認(rèn)的異常處理:異常從線程基本提升到進(jìn)程(任務(wù))基本,如果沒(méi)有被處理的話宾符。則進(jìn)一步提升到主機(jī)級(jí)別做通用的處理酿秸。
時(shí)鐘對(duì)象

Mach 內(nèi)核提供了一個(gè)簡(jiǎn)單的“時(shí)鐘(clock)”對(duì)象抽象。這個(gè)對(duì)象用于計(jì)時(shí)和鬧鐘魏烫。時(shí)鐘是一個(gè)帶有兩個(gè)端口的對(duì)象:一個(gè)用于“服務(wù)類”的函數(shù)(例如報(bào)時(shí)或鬧鈴)辣苏,另一個(gè)用于“控制類”的函數(shù),例如設(shè)置一天中的時(shí)間哄褒。

處理器對(duì)象

處理器(processor)對(duì)象表示機(jī)器上的一個(gè)邏輯CPU 或 CPU 核心稀蟋。如今多核架構(gòu)已是默認(rèn)架構(gòu),多核架構(gòu)中的每一個(gè)核心都可以看出一個(gè)CPU呐赡,處理器被分配給處理器集糊治,處理器集是一個(gè)或多個(gè)處理器的邏輯分組。處理器是CPU的簡(jiǎn)單抽象罚舱,被Mach 用于一些基本的操作井辜,例如啟動(dòng)和關(guān)閉一個(gè)CPU,以及向CPU分發(fā)要執(zhí)行的線程管闷。

處理器集對(duì)象

一個(gè)或多個(gè)processor_t 對(duì)象可以分組為處理器集(processor set)粥脚,或稱為pset(這是processor對(duì)象中的processor_set 成員),處理器集是將處理器綁定在一起的邏輯分組包个,Mach 可以以處理器集作為相關(guān)處理器的容器刷允,從而能夠高效地?cái)U(kuò)展到SMP架構(gòu)。
pset 中的處理器通過(guò)兩個(gè)隊(duì)列進(jìn)行維護(hù):一個(gè)是active_queue烘豹,保存當(dāng)前正在執(zhí)行的處理器憔鬼,另一個(gè)是idle_queue侮叮,用于保存當(dāng)前空閑的處理器(即正在執(zhí)行idle_thread的處理器)。處理器集還有一個(gè)全局的run_queue(pset_runq)映企,這個(gè)隊(duì)列保存了在這個(gè)集合中的處理器上執(zhí)行的線程得问。和其他所有對(duì)象一樣,處理器集也暴露一些端口:pset_self(用于對(duì)處理器集進(jìn)行操作) 和 pset_name_self(用于獲得處理器集的消息)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末艘希,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌唧席,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件榕暇,死亡現(xiàn)場(chǎng)離奇詭異蓬衡,居然都是意外死亡喻杈,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門狰晚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)筒饰,“玉大人,你說(shuō)我怎么就攤上這事壁晒〈擅牵” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵秒咐,是天一觀的道長(zhǎng)谬晕。 經(jīng)常有香客問(wèn)我,道長(zhǎng)携取,這世上最難降的妖魔是什么攒钳? 我笑而不...
    開(kāi)封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮雷滋,結(jié)果婚禮上不撑,老公的妹妹穿的比我還像新娘。我一直安慰自己晤斩,他們只是感情好焕檬,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著澳泵,像睡著了一般实愚。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上兔辅,一...
    開(kāi)封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天爆侣,我揣著相機(jī)與錄音,去河邊找鬼幢妄。 笑死兔仰,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蕉鸳。 我是一名探鬼主播乎赴,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼潮尝!你這毒婦竟也來(lái)了榕吼?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤勉失,失蹤者是張志新(化名)和其女友劉穎羹蚣,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體乱凿,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡顽素,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年咽弦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片胁出。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡型型,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出全蝶,到底是詐尸還是另有隱情闹蒜,我是刑警寧澤,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布抑淫,位于F島的核電站绷落,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏始苇。R本人自食惡果不足惜砌烁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望埂蕊。 院中可真熱鬧往弓,春花似錦疏唾、人聲如沸蓄氧。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)喉童。三九已至,卻和暖如春顿天,著一層夾襖步出監(jiān)牢的瞬間堂氯,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工牌废, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留咽白,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓鸟缕,卻偏偏與公主長(zhǎng)得像晶框,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子懂从,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

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