湖南大學(xué)操作系統(tǒng)ucore實(shí)驗(yàn)報(bào)告LAB3

實(shí)驗(yàn)三:虛擬內(nèi)存管理


  • 專業(yè)班級(jí):
  • 學(xué)號(hào):
  • 姓名:
  • 上課老師:

一跛溉、實(shí)驗(yàn)?zāi)康?/h2>

1.了解虛擬內(nèi)存的Page Fault異常處理實(shí)現(xiàn)
2.了解頁(yè)替換算法在操作系統(tǒng)中的實(shí)現(xiàn)

二佛嬉、實(shí)驗(yàn)內(nèi)容

本次實(shí)驗(yàn)是在實(shí)驗(yàn)二的基礎(chǔ)上镰惦,借助于頁(yè)表機(jī)制和實(shí)驗(yàn)一中涉及的中斷異常處理機(jī)制影晓,完成Page Fault異常處理和FIFO頁(yè)替換算法的實(shí)現(xiàn)镰吵,結(jié)合磁盤(pán)提供的緩存空間,從而能夠支持虛存管理挂签,提供一個(gè)比實(shí)際物理內(nèi)存空間“更大”的虛擬內(nèi)存空間給系統(tǒng)使用疤祭。這個(gè)實(shí)驗(yàn)與實(shí)際操作系統(tǒng)中的實(shí)現(xiàn)比較起來(lái)要簡(jiǎn)單,不過(guò)需要了解實(shí)驗(yàn)一和實(shí)驗(yàn)二的具體實(shí)現(xiàn)饵婆。實(shí)際操作系統(tǒng)系統(tǒng)中的虛擬內(nèi)存管理設(shè)計(jì)與實(shí)現(xiàn)是相當(dāng)復(fù)雜的勺馆,涉及到與進(jìn)程管理系統(tǒng)、文件系統(tǒng)等的交叉訪問(wèn)侨核。如果大家有余力草穆,可以嘗試完成擴(kuò)展練習(xí),實(shí)現(xiàn)extended clock頁(yè)替換法搓译。

三悲柱、實(shí)驗(yàn)步驟

練習(xí)0:填寫(xiě)已有實(shí)驗(yàn)

練習(xí)1:給末被映射的地址映射上物理頁(yè)(需要編程)

完成do_pgfault(mm/vmm.c)函數(shù),給未被映射的地址映射上物理頁(yè)侥衬。設(shè)置訪問(wèn)權(quán)限的時(shí)候需要參考頁(yè)面所在 VMA 的權(quán)限诗祸,同時(shí)需要注意映射物理頁(yè)時(shí)需要操作內(nèi)存控制結(jié)構(gòu)所指定的頁(yè)表,而不是內(nèi)核的頁(yè)表轴总。注意:在LAB2 EXERCISE 1處填寫(xiě)代碼直颅。執(zhí)行

make qemu

后,如果通過(guò)check_pgfault函數(shù)的測(cè)試后怀樟,會(huì)有“check_pgfault() succeeded!”的輸出功偿,表示練習(xí)1基本正確。

請(qǐng)?jiān)趯?shí)驗(yàn)報(bào)告中簡(jiǎn)要說(shuō)明你的設(shè)計(jì)實(shí)現(xiàn)過(guò)程。請(qǐng)回答如下問(wèn)題:

  • 請(qǐng)描述頁(yè)目錄項(xiàng)(Pag Director Entry)和頁(yè)表(Page Table Entry)中組成部分對(duì)ucore實(shí)現(xiàn)頁(yè)替換算法的潛在用處械荷。
  • 如果ucore的缺頁(yè)服務(wù)例程在執(zhí)行過(guò)程中訪問(wèn)內(nèi)存共耍,出現(xiàn)了頁(yè)訪問(wèn)異常,請(qǐng)問(wèn)硬件要做哪些事情吨瞎?

解析

lab3的總體執(zhí)行流程如下:

  • 首先是初始化過(guò)程痹兜。參考ucore總控函數(shù)init的代碼,可以看到在調(diào)用完成虛擬內(nèi)存初始化的vmm_init函數(shù)之前颤诀,需要首先調(diào)用pmm_init函數(shù)完成物理內(nèi)存的管理字旭,這也是我們lab2已經(jīng)完成的內(nèi)容。
  • 接著是執(zhí)行中斷和異常相關(guān)的初始化工作崖叫,即調(diào)用pic_init函數(shù)和idt_init函數(shù)等遗淳,這些工作與lab1的中斷異常初始化工作的內(nèi)容是相同的。
  • 在調(diào)用完idt_init函數(shù)之后心傀,將進(jìn)一步調(diào)用三個(gè)lab3中才有的新函數(shù)vmm_init屈暗、ide_initswap_init。這三個(gè)函數(shù)設(shè)計(jì)了本次實(shí)驗(yàn)中的兩個(gè)練習(xí)脂男。第一個(gè)函數(shù)vmm_init是檢查我們的練習(xí)1是否正確實(shí)現(xiàn)了养叛。為了表述不在物理內(nèi)存中的“合法”虛擬頁(yè),需要有數(shù)據(jù)結(jié)構(gòu)來(lái)描述這樣的頁(yè)宰翅,為此ucore建立了mm_structvma_struct數(shù)據(jù)結(jié)構(gòu)(接下來(lái)的小節(jié)中有進(jìn)一步詳細(xì)描述)一铅,假定我們已經(jīng)描述好了這樣的“合法”虛擬頁(yè),當(dāng)ucore訪問(wèn)這些“合法”虛擬頁(yè)時(shí)堕油,會(huì)由于沒(méi)有虛實(shí)地址映射而產(chǎn)生頁(yè)訪問(wèn)異常。

do_pgfault函數(shù)會(huì)申請(qǐng)一個(gè)空閑物理頁(yè)肮之,并建立好虛實(shí)映射關(guān)系掉缺,從而使得這樣的“合法”虛擬頁(yè)有實(shí)際的物理頁(yè)幀對(duì)應(yīng)。

page_fault函數(shù)不知道哪些是“合法”的虛擬頁(yè)戈擒,原因是ucore還缺少一定的數(shù)據(jù)結(jié)構(gòu)來(lái)描述這種不在物理內(nèi)存中的“合法”虛擬頁(yè)眶明。為此ucore通過(guò)建立mm_structvma_struct數(shù)據(jù)結(jié)構(gòu),描述了ucore模擬應(yīng)用程序運(yùn)行所需的合法內(nèi)存空間筐高。

vma_struct的定義如下:

struct vma_struct{
    struct mm_struct *vm_mm; // the set of vma using the same PDT
    uintptr_t vm_start;      // start addr of vma    
    uintptr_t vm_end;        // end addr of vma
    uint32_t vm_flags;       // flags of vma
    list_entry_t list_link;  // linear list link which sorted by start addr of vma
};
  • vm_mm是一個(gè)指針搜囱,指向一個(gè)比vma_struct更高的抽象層次的數(shù)據(jù)結(jié)構(gòu)mm_struct
  • vm_startvm_end描述的是一個(gè)合理的地址空間范圍(即嚴(yán)格確保 vm_start < vm_end的關(guān)系);
  • list_link是一個(gè)雙向鏈表柑土,按照從小到大的順序把一系列用vma_struct表示的虛擬內(nèi)存空間鏈接起來(lái)蜀肘,并且還要求這些鏈起來(lái)的vma_struct應(yīng)該是不相交的,即vma之間的地址空間無(wú)交集稽屏;
  • vm_flags表示了這個(gè)虛擬內(nèi)存空間的屬性扮宠,目前的屬性包括

#define VM_READ 0x00000001 //只讀
#define VM_WRITE 0x00000002 //可讀寫(xiě)
#define VM_EXEC 0x00000004 //可執(zhí)行

mm_struct的定義如下:

struct mm_struct{
    list_entry_t mmap_list;        // linear list link which sorted by start addr of vma
    struct vma_struct *mmap_cache; // current accessed vma, used for speed purpose
    pde_t *pgdir;                  // the PDT of these vma
    int map_count;                 // the count of these vma
    void *sm_priv;                 // the private data for swap manager
};
  • mmap_list是雙向鏈表頭,鏈接了所有屬于同一頁(yè)目錄表的虛擬內(nèi)存空間狐榔,
  • mmap_cache是指向當(dāng)前正在使用的虛擬內(nèi)存空間坛增,由于操作系統(tǒng)執(zhí)行的“局部性”原理获雕,當(dāng)前正在用到的虛擬內(nèi)存空間在接下來(lái)的操作中可能還會(huì)用到,這時(shí)就不需要查鏈表收捣,而是直接使用此指針就可找到下一次要用到的虛擬內(nèi)存空間届案。由于mmap_cache 的引入,可使得 mm_struct 數(shù)據(jù)結(jié)構(gòu)的查詢加速 30% 以上罢艾。
  • pgdir所指向的就是 mm_struct數(shù)據(jù)結(jié)構(gòu)所維護(hù)的頁(yè)表楣颠。通過(guò)訪問(wèn)pgdir可以查找某虛擬地址對(duì)應(yīng)的頁(yè)表項(xiàng)是否存在以及頁(yè)表項(xiàng)的屬性等。
  • map_count記錄mmap_list 里面鏈接的 vma_struct的個(gè)數(shù)昆婿。
  • sm_priv指向用來(lái)鏈接記錄頁(yè)訪問(wèn)情況的鏈表頭球碉,這建立了mm_struct和后續(xù)要講到的swap_manager之間的聯(lián)系。

當(dāng)啟動(dòng)分頁(yè)機(jī)制以后仓蛆,如果一條指令或數(shù)據(jù)的虛擬地址所對(duì)應(yīng)的物理頁(yè)框不在內(nèi)存中或者訪問(wèn)的類型有錯(cuò)誤(比如寫(xiě)一個(gè)只讀頁(yè)或用戶態(tài)程序訪問(wèn)內(nèi)核態(tài)的數(shù)據(jù)等)睁冬,就會(huì)發(fā)生頁(yè)錯(cuò)誤異常。產(chǎn)生頁(yè)面異常的原因主要有:

  • 目標(biāo)頁(yè)面不存在(頁(yè)表項(xiàng)全為0看疙,即該線性地址與物理地址尚未建立映射或者已經(jīng)撤銷);
  • 相應(yīng)的物理頁(yè)面不在內(nèi)存中(頁(yè)表項(xiàng)非空豆拨,但Present標(biāo)志位=0,比如在swap分區(qū)或磁盤(pán)文件上)
  • 訪問(wèn)權(quán)限不符合(此時(shí)頁(yè)表項(xiàng)P標(biāo)志=1能庆,比如企圖寫(xiě)只讀頁(yè)面).
    當(dāng)出現(xiàn)上面情況之一,那么就會(huì)產(chǎn)生頁(yè)面page fault(#PF)異常施禾。

產(chǎn)生頁(yè)訪問(wèn)異常后,CPU把引起頁(yè)訪問(wèn)異常的線性地址裝到寄存器CR2中搁胆,并給出了出錯(cuò)碼errorCode弥搞,說(shuō)明了頁(yè)訪問(wèn)異常的類型。ucore OS會(huì)把這個(gè)值保存在struct trapframetf_err成員變量中渠旁。而中斷服務(wù)例程會(huì)調(diào)用頁(yè)訪問(wèn)異常處理函數(shù)do_pgfault進(jìn)行具體處理攀例。這里的頁(yè)訪問(wèn)異常處理是實(shí)現(xiàn)按需分頁(yè)、頁(yè)換入換出機(jī)制的關(guān)鍵之處顾腊。

ucore中do_pgfault函數(shù)是完成頁(yè)訪問(wèn)異常處理的主要函數(shù)粤铭,它根據(jù)從CPU的控制寄存器CR2中獲取的頁(yè)訪問(wèn)異常的物理地址以及根據(jù)errorCode的錯(cuò)誤類型來(lái)查找此地址是否在某個(gè)VMA的地址范圍內(nèi)以及是否滿足正確的讀寫(xiě)權(quán)限,如果在此范圍內(nèi)并且權(quán)限也正確杂靶,這認(rèn)為這是一次合法訪問(wèn)梆惯,但沒(méi)有建立虛實(shí)對(duì)應(yīng)關(guān)系。所以需要

分配一個(gè)空閑的內(nèi)存頁(yè)吗垮,并修改頁(yè)表完成虛地址到物理地址的映射垛吗,刷新TLB,然后調(diào)用iret中斷烁登,返回到產(chǎn)生頁(yè)訪問(wèn)異常的指令處重新執(zhí)行此指令职烧。

如果該虛地址不在某VMA范圍內(nèi),則認(rèn)為是一次非法訪問(wèn)。

do_pgfault部分具體實(shí)現(xiàn)如下:

// try to find a pte, if pte's PT(Page Table) isn't existed, then create a PT.
if ((ptep = get_pte(mm->pgdir, addr, 1)) == NULL) {
    cprintf("get_pte in do_pgfault failed\n");//如果找不到入口蚀之,是非法訪問(wèn)蝗敢,退出
    goto failed;
}
// if the phy addr isn't exist, then alloc a page & map the phy addr with logical addr
if (*ptep == 0) { 
    if (pgdir_alloc_page(mm->pgdir, addr, perm) == NULL) {
        cprintf("pgdir_alloc_page in do_pgfault failed\n");
        //嘗試申請(qǐng)一個(gè)頁(yè),如果申請(qǐng)失敗足删,就是內(nèi)存不足了寿谴,退出
        goto failed;
    }
}

練習(xí)2:補(bǔ)充完成基于FIFO的頁(yè)面置換算法(需要編程)

完成vmm.c中的do_pgfault函數(shù),并且在實(shí)現(xiàn)FIFO算法的swap_fifo.c中完成map_swappable swap_out_vistim函數(shù)失受。通過(guò)對(duì)swap的測(cè)試讶泰。注意:在LAB2 EXERCISE 2處填寫(xiě)代碼。執(zhí)行

make qemu

后拂到,如果通過(guò)check_swap函數(shù)的測(cè)試后痪署,會(huì)有“check_swap() succeeded!”的輸出,表示練習(xí)2基本正確兄旬。
請(qǐng)?jiān)趯?shí)驗(yàn)報(bào)告中簡(jiǎn)要說(shuō)明你的設(shè)計(jì)實(shí)現(xiàn)過(guò)程狼犯。

請(qǐng)?jiān)趯?shí)驗(yàn)報(bào)告中回答如下問(wèn)題:

  • 如果要在ucore上實(shí)現(xiàn)"extended clock頁(yè)替換算法"請(qǐng)給你的設(shè)計(jì)方案,現(xiàn)有的swap_manager框架是否足以支持在ucore中實(shí)現(xiàn)此算法领铐?如果是悯森,請(qǐng)給你的設(shè)計(jì)方案。如果不是绪撵,請(qǐng)給出你的新的擴(kuò)展和基此擴(kuò)展的設(shè)計(jì)方案瓢姻。并需要回答如下問(wèn)題:
    1. 需要被換出的頁(yè)的特征是什么?
    2. 在ucore中如何判斷具有這樣特征的頁(yè)音诈?
    3. 何時(shí)進(jìn)行換入和換出操作幻碱?

解析

當(dāng)應(yīng)用程序訪問(wèn)它認(rèn)為應(yīng)該在內(nèi)存中的的數(shù)據(jù)或代碼時(shí),如果這些數(shù)據(jù)或代碼不在內(nèi)存中细溅,則根據(jù)上一小節(jié)的介紹收班,會(huì)產(chǎn)生頁(yè)訪問(wèn)異常。這時(shí)谒兄,操作系統(tǒng)必須能夠應(yīng)對(duì)這種頁(yè)訪問(wèn)異常,即盡快把應(yīng)用程序當(dāng)前需要的數(shù)據(jù)或代碼放到內(nèi)存中來(lái)社付,然后重新執(zhí)行應(yīng)用程序產(chǎn)生異常的訪存指令承疲。(換入)

如果在把硬盤(pán)中對(duì)應(yīng)的數(shù)據(jù)或代碼調(diào)入內(nèi)存前,操作系統(tǒng)發(fā)現(xiàn)物理內(nèi)存已經(jīng)沒(méi)有空閑空間了鸥咖,這時(shí)操作系統(tǒng)必須把它認(rèn)為“不常用”的頁(yè)換出到磁盤(pán)上去燕鸽,以騰出內(nèi)存空閑空間給應(yīng)用程序所需的數(shù)據(jù)或代碼。(換出)

頁(yè)面替換主要分為兩個(gè)方面啼辣,頁(yè)面換出和頁(yè)面換入啊研。
頁(yè)面換入主要在vmm.c中的do_pgfault()函數(shù)實(shí)現(xiàn);頁(yè)面換出主要在swap_fifo.c中的swap_out_vistim()函數(shù)實(shí)現(xiàn)。

  • 在換入時(shí)党远,需要先檢查產(chǎn)生訪問(wèn)異常的地址是否屬于某個(gè)vma表示的合法虛擬地址削解,并且保存在硬盤(pán)的swap文件中(對(duì)應(yīng)的PTE的高24位不為0)。如果滿足以上兩點(diǎn)沟娱,則執(zhí)行swap_in()函數(shù)換入頁(yè)面氛驮。
  • 換出則相對(duì)簡(jiǎn)單,當(dāng)申請(qǐng)空閑頁(yè)面時(shí)济似,alloc_pages()函數(shù)不能獲得空閑頁(yè)矫废,則需要調(diào)用swap_out()函數(shù)換出不常用的頁(yè)面。

換入

else {//頁(yè)表項(xiàng)非空砰蠢,可以嘗試換入頁(yè)面          
    if(swap_init_ok) {
        struct Page *page=NULL;
        //根據(jù)mm結(jié)構(gòu)和addr地址蓖扑,嘗試將硬盤(pán)中的內(nèi)容換入至page中
        if ((ret = swap_in(mm, addr, &page)) != 0) {
            cprintf("swap_in in do_pgfault failed\n");
            goto failed;
        }    
        page_insert(mm->pgdir, page, addr, perm);//建立虛擬地址和物理地址之間的對(duì)應(yīng)關(guān)系
        swap_map_swappable(mm, addr, page, 1);//將此頁(yè)面設(shè)置為可交換的
        page->pra_vaddr = addr;
    }
    else {
        cprintf("no swap_init_ok but ptep is %x, failed\n",*ptep);
        goto failed;
    }
}

換出

FIFO替換算法會(huì)維護(hù)一個(gè)隊(duì)列,隊(duì)列按照頁(yè)面調(diào)用的次序排列台舱,越早被加載到內(nèi)存的頁(yè)面會(huì)越早被換出律杠。
具體實(shí)現(xiàn)的函數(shù)如下:
首先是_fifo_map_swappable(),它的主要作用是將最近被用到的頁(yè)面添加到算法所維護(hù)的次序隊(duì)列柿赊。

static int _fifo_map_swappable(struct mm_struct *mm, uintptr_t addr, struct Page *page, int swap_in) {        
    list_entry_t *head=(list_entry_t*) mm->sm_priv;   
    list_entry_t *entry=&(page->pra_page_link);          
    assert(entry != NULL && head != NULL);   
    list_add(head, entry); //將最近用到的頁(yè)面添加到次序隊(duì)尾  
    return 0;   
} 

然后是_fifo_swap_out_victim()函數(shù)是用來(lái)查詢哪個(gè)頁(yè)面需要被換出俩功,它的主要作用是用來(lái)查詢哪個(gè)頁(yè)面需要被換出。

static int  
_fifo_swap_out_victim(struct mm_struct *mm, struct Page ** ptr_page, int in_tick) {       
    list_entry_t *head=(list_entry_t*) mm->sm_priv;          
    assert(head != NULL);      
    assert(in_tick==0);
    list_entry_t *le = head->prev;  //用le指示需要被換出的頁(yè)             
    assert(head!=le);  
    struct Page *p = le2page(le, pra_page_link);//le2page宏可以根據(jù)鏈表元素獲得對(duì)應(yīng)的Page指針p      
    list_del(le);      //將進(jìn)來(lái)最早的頁(yè)面從隊(duì)列中刪除      
    assert(p !=NULL);       
    *ptr_page = p; //將這一頁(yè)的地址存儲(chǔ)在ptr_page中
    return 0; 
}

實(shí)驗(yàn)結(jié)果

擴(kuò)展練習(xí)

實(shí)驗(yàn)總結(jié)

經(jīng)過(guò)本次試驗(yàn)碰声,明白了頁(yè)面置換诡蜓。
可以說(shuō)非常有用了。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末胰挑,一起剝皮案震驚了整個(gè)濱河市蔓罚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌瞻颂,老刑警劉巖豺谈,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異贡这,居然都是意外死亡茬末,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)盖矫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)丽惭,“玉大人,你說(shuō)我怎么就攤上這事辈双≡鹛停” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵湃望,是天一觀的道長(zhǎng)换衬。 經(jīng)常有香客問(wèn)我痰驱,道長(zhǎng),這世上最難降的妖魔是什么瞳浦? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任担映,我火速辦了婚禮,結(jié)果婚禮上术幔,老公的妹妹穿的比我還像新娘另萤。我一直安慰自己,他們只是感情好诅挑,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布四敞。 她就那樣靜靜地躺著,像睡著了一般拔妥。 火紅的嫁衣襯著肌膚如雪忿危。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,365評(píng)論 1 302
  • 那天没龙,我揣著相機(jī)與錄音铺厨,去河邊找鬼。 笑死硬纤,一個(gè)胖子當(dāng)著我的面吹牛解滓,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播筝家,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼洼裤,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了溪王?” 一聲冷哼從身側(cè)響起腮鞍,我...
    開(kāi)封第一講書(shū)人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎莹菱,沒(méi)想到半個(gè)月后移国,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡道伟,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年迹缀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蜜徽。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡祝懂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出娜汁,到底是詐尸還是另有隱情,我是刑警寧澤兄朋,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布掐禁,位于F島的核電站怜械,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏傅事。R本人自食惡果不足惜缕允,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蹭越。 院中可真熱鬧障本,春花似錦、人聲如沸响鹃。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)买置。三九已至粪糙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間忿项,已是汗流浹背蓉冈。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留轩触,地道東北人寞酿。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像脱柱,于是被迫代替她去往敵國(guó)和親伐弹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

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