哈工大操作系統(tǒng)實(shí)驗(yàn)(五)I/O設(shè)備管理

本次實(shí)驗(yàn)內(nèi)容:
本實(shí)驗(yàn)的基本內(nèi)容是修改Linux 0.11的終端設(shè)備處理代碼,對(duì)鍵盤輸入和字符顯示進(jìn)行非常規(guī)的控制仅政。

在初始狀態(tài)垢油,一切如常。用戶按一次F12后圆丹,把應(yīng)用程序向終端輸出所有字母都替換為“*”滩愁。用戶再按一次F12,又恢復(fù)正常辫封。第三次按F12硝枉,再進(jìn)行輸出替換。依此類推倦微。

以ls命令為例:

正常情況:

ls
hello.c hello.o hello
第一次按F12檀咙,然后輸入ls:

**
*****.* *****.* *****
第二次按F12,然后輸入ls:

ls
hello.c hello.o hello
第三次按F12璃诀,然后輸入ls:

**
*****.* *****.* *****

(一)修改linux-0.11/kernel/chr_drv/keyboard.S的文件

首先我們得知道 在修改之前,按下F12什么功能;
鍵盤I/O是典型的中斷驅(qū)動(dòng)弧可,在kernel/chr_drv/console.c文件中:

void con_init(void) //控制臺(tái)的初始化
{
set_trap_gate(0x21,&keyboard_interrupt); //鍵盤中斷響應(yīng)函數(shù)設(shè)為keyboard_interrupt
}
所以每次按鍵有動(dòng)作,keyboard_interrupt函數(shù)就會(huì)被調(diào)用劣欢,它在文件kernel/chr_drv/keyboard.S

func:
    /*程序210行子函數(shù)處理功能鍵
      將功能鍵轉(zhuǎn)化成轉(zhuǎn)義字符存取到讀隊(duì)列中*/
    pushl %eax
    pushl %ecx
    pushl %edx
    call show_stat  
    popl %edx
    popl %ecx
    popl %eax
調(diào)用 show_stat 函數(shù),顯示當(dāng)前 進(jìn)程狀態(tài)
屏蔽了 call  show_stat的功能再改成我們自己的的功能就好了
func:
    /*程序210行子函數(shù)處理功能鍵
      將功能鍵轉(zhuǎn)化成轉(zhuǎn)義字符存取到讀隊(duì)列中*/
    pushl %eax
    pushl %ecx
    pushl %edx
    //call show_stat  
    popl %edx
    popl %ecx
    popl %eax

(二)修改tty_io.c文件

linux-0.11/kernel/chr_drv/tty_io.c

鍵盤每次輸入一個(gè)字符,操作系統(tǒng)都會(huì)將這個(gè)字符送到字符緩沖區(qū)進(jìn)行處理.
f12是一個(gè)功能鍵,它的掃描碼是 esc,[,[,L
分別對(duì)應(yīng)ascii碼的27,91,91,76
所以要連續(xù)判斷四次 字符呀
你說(shuō) 那我判斷這幾個(gè)字符的時(shí)候輸出了一個(gè)其他的字符,它應(yīng)該顯示這個(gè)其他字符啊.
所以這段處理程序就應(yīng)該寫在 操作系統(tǒng)判斷字符做出功能的代碼之前.

判斷字符的代碼是copy_to_cooked函數(shù)

增加的全局變量
int judge=-1;
int f1=0,f2=0,f3=0;
long j=0;
void copy_to_cooked(struct tty_struct * tty)
{
    signed char c;
//now用來(lái)判斷當(dāng)前時(shí)間戳 
    long now;
     
    while (!EMPTY(tty->read_q) && !FULL(tty->secondary)) {
        GETCH(tty->read_q,c);
//開始添加代碼
        if(c==27)
    {   
        f1=1;
        j=jiffies;
//獲取當(dāng)前 函數(shù)的CPU心跳數(shù),用來(lái)計(jì)時(shí)
    }
            
        else if(f1==1&&f2==0&&c==91)
            f2=1;
        else if(f1==1&&f2==1&&c==91)
            f3=1;
        else if(f1==1&&f2==1&&f3==1&&c==76)
        {
            now=jiffies;
            if((now-j)>10)
//比如人為的輸入esc,[,[,J 也會(huì)認(rèn)為是F12,所以要根據(jù)四個(gè)字符的到達(dá)的時(shí)間判斷是一次輸入還是多次輸入的~
        {
            printk("%ld \t %ld \n",j,now);
            break;
        }
            
            judge*=-1;
            continue;
        }
        else
            f1=f2=f3=0;
//添加代碼結(jié)束
        if (c==13)
            if (I_CRNL(tty))
                c=10;
            else if (I_NOCR(tty))
                continue;
            else ;
        else if (c==10 && I_NLCR(tty))
            c=13;
        if (I_UCLC(tty))
            c=tolower(c);
        if (L_CANON(tty)) {
            if (c==KILL_CHAR(tty)) {
                /* deal with killing the input line */
                while(!(EMPTY(tty->secondary) ||
                        (c=LAST(tty->secondary))==10 ||
                        c==EOF_CHAR(tty))) {
                    if (L_ECHO(tty)) {
                        if (c<32)
                            PUTCH(127,tty->write_q);
                        PUTCH(127,tty->write_q);
                        tty->write(tty);
                    }
                    DEC(tty->secondary.head);
                }
                continue;
            }
            if (c==ERASE_CHAR(tty)) {
                if (EMPTY(tty->secondary) ||
                   (c=LAST(tty->secondary))==10 ||
                   c==EOF_CHAR(tty))
                    continue;
                if (L_ECHO(tty)) {
                    if (c<32)
                        PUTCH(127,tty->write_q);
                    PUTCH(127,tty->write_q);
                    tty->write(tty);
                }
                DEC(tty->secondary.head);
                continue;
            }
            if (c==STOP_CHAR(tty)) {
                tty->stopped=1;
                continue;
            }
            if (c==START_CHAR(tty)) {
                tty->stopped=0;
                continue;
            }
        }
        if (L_ISIG(tty)) {
            if (c==INTR_CHAR(tty)) {
                tty_intr(tty,INTMASK);
                continue;
            }
            if (c==QUIT_CHAR(tty)) {
                tty_intr(tty,QUITMASK);
                continue;
            }
        }
        if (c==10 || c==EOF_CHAR(tty))
            tty->secondary.data++;
        if (L_ECHO(tty)) {
            if (c==10) {
                PUTCH(10,tty->write_q);
                PUTCH(13,tty->write_q);
            } else if (c<32) {
                if (L_ECHOCTL(tty)) {
                    PUTCH('^',tty->write_q);
                    PUTCH(c+64,tty->write_q);
                }
            } else
                PUTCH(c,tty->write_q);
            tty->write(tty);
        }
        PUTCH(c,tty->secondary);
    }
    wake_up(&tty->secondary.proc_list);
}

修改后的tty_io.c文件

/*
 *  linux/kernel/tty_io.c
 *
 *  (C) 1991  Linus Torvalds
 */

/*
 * 'tty_io.c' gives an orthogonal feeling to tty's, be they consoles
 * or rs-channels. It also implements echoing, cooked mode etc.
 *
 * Kill-line thanks to John T Kohl.
 */
#include <ctype.h>
#include <errno.h>
#include <signal.h>

#define ALRMMASK (1<<(SIGALRM-1))
#define KILLMASK (1<<(SIGKILL-1))
#define INTMASK (1<<(SIGINT-1))
#define QUITMASK (1<<(SIGQUIT-1))
#define TSTPMASK (1<<(SIGTSTP-1))

#include <linux/sched.h>
#include <linux/tty.h>
#include <asm/segment.h>
#include <asm/system.h>

#define _L_FLAG(tty,f)  ((tty)->termios.c_lflag & f)
#define _I_FLAG(tty,f)  ((tty)->termios.c_iflag & f)
#define _O_FLAG(tty,f)  ((tty)->termios.c_oflag & f)

#define L_CANON(tty)    _L_FLAG((tty),ICANON)
#define L_ISIG(tty) _L_FLAG((tty),ISIG)
#define L_ECHO(tty) _L_FLAG((tty),ECHO)
#define L_ECHOE(tty)    _L_FLAG((tty),ECHOE)
#define L_ECHOK(tty)    _L_FLAG((tty),ECHOK)
#define L_ECHOCTL(tty)  _L_FLAG((tty),ECHOCTL)
#define L_ECHOKE(tty)   _L_FLAG((tty),ECHOKE)

#define I_UCLC(tty) _I_FLAG((tty),IUCLC)
#define I_NLCR(tty) _I_FLAG((tty),INLCR)
#define I_CRNL(tty) _I_FLAG((tty),ICRNL)
#define I_NOCR(tty) _I_FLAG((tty),IGNCR)

#define O_POST(tty) _O_FLAG((tty),OPOST)
#define O_NLCR(tty) _O_FLAG((tty),ONLCR)
#define O_CRNL(tty) _O_FLAG((tty),OCRNL)
#define O_NLRET(tty)    _O_FLAG((tty),ONLRET)
#define O_LCUC(tty) _O_FLAG((tty),OLCUC)
long j;
struct tty_struct tty_table[] = {
    {
        {ICRNL,     /* change incoming CR to NL */
        OPOST|ONLCR,    /* change outgoing NL to CRNL */
        0,
        ISIG | ICANON | ECHO | ECHOCTL | ECHOKE,
        0,      /* console termio */
        INIT_C_CC},
        0,          /* initial pgrp */
        0,          /* initial stopped */
        con_write,
        {0,0,0,0,""},       /* console read-queue */
        {0,0,0,0,""},       /* console write-queue */
        {0,0,0,0,""}        /* console secondary queue */
    },{
        {0, /* no translation */
        0,  /* no translation */
        B2400 | CS8,
        0,
        0,
        INIT_C_CC},
        0,
        0,
        rs_write,
        {0x3f8,0,0,0,""},       /* rs 1 */
        {0x3f8,0,0,0,""},
        {0,0,0,0,""}
    },{
        {0, /* no translation */
        0,  /* no translation */
        B2400 | CS8,
        0,
        0,
        INIT_C_CC},
        0,
        0,
        rs_write,
        {0x2f8,0,0,0,""},       /* rs 2 */
        {0x2f8,0,0,0,""},
        {0,0,0,0,""}
    }
};

/*
 * these are the tables used by the machine code handlers.
 * you can implement pseudo-tty's or something by changing
 * them. Currently not done.
 */
struct tty_queue * table_list[]={
    &tty_table[0].read_q, &tty_table[0].write_q,
    &tty_table[1].read_q, &tty_table[1].write_q,
    &tty_table[2].read_q, &tty_table[2].write_q
    };

void tty_init(void)
{
    rs_init();
    con_init();
}

void tty_intr(struct tty_struct * tty, int mask)
{
    int i;

    if (tty->pgrp <= 0)
        return;
    for (i=0;i<NR_TASKS;i++)
        if (task[i] && task[i]->pgrp==tty->pgrp)
            task[i]->signal |= mask;
}

static void sleep_if_empty(struct tty_queue * queue)
{
    cli();
    while (!current->signal && EMPTY(*queue))
        interruptible_sleep_on(&queue->proc_list);
    sti();
}

static void sleep_if_full(struct tty_queue * queue)
{
    if (!FULL(*queue))
        return;
    cli();
    while (!current->signal && LEFT(*queue)<128)
        interruptible_sleep_on(&queue->proc_list);
    sti();
}

void wait_for_keypress(void)
{
    sleep_if_empty(&tty_table[0].secondary);
}

int judge=-1;
int f1=0,f2=0,f3=0;

void copy_to_cooked(struct tty_struct * tty)
{
    signed char c;
    long now;
     
    while (!EMPTY(tty->read_q) && !FULL(tty->secondary)) {
        GETCH(tty->read_q,c);
        if(c==27)
    {   
        f1=1;
        j=jiffies;
    }
            
        else if(f1==1&&f2==0&&c==91)
            f2=1;
        else if(f1==1&&f2==1&&c==91)
            f3=1;
        else if(f1==1&&f2==1&&f3==1&&c==76)
        {
            now=jiffies;
            if((now-j)>10)
        {
            printk("%ld \t %ld \n",j,now);
            break;
        }
            
            judge*=-1;
            continue;
        }
        else
            f1=f2=f3=0;

        if (c==13)
            if (I_CRNL(tty))
                c=10;
            else if (I_NOCR(tty))
                continue;
            else ;
        else if (c==10 && I_NLCR(tty))
            c=13;
        if (I_UCLC(tty))
            c=tolower(c);
        if (L_CANON(tty)) {
            if (c==KILL_CHAR(tty)) {
                /* deal with killing the input line */
                while(!(EMPTY(tty->secondary) ||
                        (c=LAST(tty->secondary))==10 ||
                        c==EOF_CHAR(tty))) {
                    if (L_ECHO(tty)) {
                        if (c<32)
                            PUTCH(127,tty->write_q);
                        PUTCH(127,tty->write_q);
                        tty->write(tty);
                    }
                    DEC(tty->secondary.head);
                }
                continue;
            }
            if (c==ERASE_CHAR(tty)) {
                if (EMPTY(tty->secondary) ||
                   (c=LAST(tty->secondary))==10 ||
                   c==EOF_CHAR(tty))
                    continue;
                if (L_ECHO(tty)) {
                    if (c<32)
                        PUTCH(127,tty->write_q);
                    PUTCH(127,tty->write_q);
                    tty->write(tty);
                }
                DEC(tty->secondary.head);
                continue;
            }
            if (c==STOP_CHAR(tty)) {
                tty->stopped=1;
                continue;
            }
            if (c==START_CHAR(tty)) {
                tty->stopped=0;
                continue;
            }
        }
        if (L_ISIG(tty)) {
            if (c==INTR_CHAR(tty)) {
                tty_intr(tty,INTMASK);
                continue;
            }
            if (c==QUIT_CHAR(tty)) {
                tty_intr(tty,QUITMASK);
                continue;
            }
        }
        if (c==10 || c==EOF_CHAR(tty))
            tty->secondary.data++;
        if (L_ECHO(tty)) {
            if (c==10) {
                PUTCH(10,tty->write_q);
                PUTCH(13,tty->write_q);
            } else if (c<32) {
                if (L_ECHOCTL(tty)) {
                    PUTCH('^',tty->write_q);
                    PUTCH(c+64,tty->write_q);
                }
            } else
                PUTCH(c,tty->write_q);
            tty->write(tty);
        }
        PUTCH(c,tty->secondary);
    }
    wake_up(&tty->secondary.proc_list);
}

int tty_read(unsigned channel, char * buf, int nr)
{
    struct tty_struct * tty;
    char c, * b=buf;
    int minimum,time,flag=0;
    long oldalarm;

    if (channel>2 || nr<0) return -1;
    tty = &tty_table[channel];
    oldalarm = current->alarm;
    time = 10L*tty->termios.c_cc[VTIME];
    minimum = tty->termios.c_cc[VMIN];
    if (time && !minimum) {
        minimum=1;
        if ((flag=(!oldalarm || time+jiffies<oldalarm)))
            current->alarm = time+jiffies;
    }
    if (minimum>nr)
        minimum=nr;
    while (nr>0) {
        if (flag && (current->signal & ALRMMASK)) {
            current->signal &= ~ALRMMASK;
            break;
        }
        if (current->signal)
            break;
        if (EMPTY(tty->secondary) || (L_CANON(tty) &&
        !tty->secondary.data && LEFT(tty->secondary)>20)) {
            sleep_if_empty(&tty->secondary);
            continue;
        }
        do {
            GETCH(tty->secondary,c);
            if (c==EOF_CHAR(tty) || c==10)
                tty->secondary.data--;
            if (c==EOF_CHAR(tty) && L_CANON(tty))
                return (b-buf);
            else {
                put_fs_byte(c,b++);
                if (!--nr)
                    break;
            }
        } while (nr>0 && !EMPTY(tty->secondary));
        if (time && !L_CANON(tty)) {
            if ((flag=(!oldalarm || time+jiffies<oldalarm)))
                current->alarm = time+jiffies;
            else
                current->alarm = oldalarm;
        }
        if (L_CANON(tty)) {
            if (b-buf)
                break;
        } else if (b-buf >= minimum)
            break;
    }
    current->alarm = oldalarm;
    if (current->signal && !(b-buf))
        return -EINTR;
    return (b-buf);
}

int tty_write(unsigned channel, char * buf, int nr)
{
    static int cr_flag=0;
    struct tty_struct * tty;
    char c, *b=buf;

    if (channel>2 || nr<0) return -1;
    tty = channel + tty_table;
    while (nr>0) {
        sleep_if_full(&tty->write_q);
        if (current->signal)
            break;
        while (nr>0 && !FULL(tty->write_q)) {
            c=get_fs_byte(b);
            if (O_POST(tty)) {
                if (c=='\r' && O_CRNL(tty))
                    c='\n';
                else if (c=='\n' && O_NLRET(tty))
                    c='\r';
                if (c=='\n' && !cr_flag && O_NLCR(tty)) {
                    cr_flag = 1;
                    PUTCH(13,tty->write_q);
                    continue;
                }
                if (O_LCUC(tty))
                    c=toupper(c);
            }
            b++; nr--;
            cr_flag = 0;
            PUTCH(c,tty->write_q);
        }
        tty->write(tty);
        if (nr>0)
            schedule();
    }
    return (b-buf);
}

/*
 * Jeh, sometimes I really like the 386.
 * This routine is called from an interrupt,
 * and there should be absolutely no problem
 * with sleeping even in an interrupt (I hope).
 * Of course, if somebody proves me wrong, I'll
 * hate intel for all time :-). We'll have to
 * be careful and see to reinstating the interrupt
 * chips before calling this, though.
 *
 * I don't think we sleep here under normal circumstances
 * anyway, which is good, as the task sleeping might be
 * totally innocent.
 */
void do_tty_interrupt(int tty)
{
    copy_to_cooked(tty_table+tty);
}

void chr_dev_init(void)
{
}

(三)修改linux-0.11/kernel/chr_drv/console.c

tty_io.c文件只是捕捉到了按下f12的狀態(tài)
我們需要在控制程序中添加 改變輸出的代碼,最簡(jiǎn)單的方法是只要按下F12就把所有的字符都變成"*"號(hào)輸出就行了
我們只要在con_write()函數(shù)中添加一行代碼:

extern int judge;//引用代碼tty_io.c中的judge變量
if(judge==1)
    c='*';

con_write函數(shù):

extern int judge;

void con_write(struct tty_struct * tty)
{
    int nr;
    char c;

    nr = CHARS(tty->write_q);
    while (nr--) {
        GETCH(tty->write_q,c);
        switch(state) {
            case 0:
                if (c>31 && c<127) {
                    if (x>=video_num_columns) {
                        x -= video_num_columns;
                        pos -= video_size_row;
                        lf();
                    }
                    if(judge==1)
                            c='*';
                    __asm__("movb attr,%%ah\n\t"
                        "movw %%ax,%1\n\t"
                        ::"a" (c),"m" (*(short *)pos)
                        );
                    pos += 2;
                    x++;
                } else if (c==27)
                    state=1;
                else if (c==10 || c==11 || c==12)
                    lf();
                else if (c==13)
                    cr();
                else if (c==ERASE_CHAR(tty))
                    del();
                else if (c==8) {
                    if (x) {
                        x--;
                        pos -= 2;
                    }
                } else if (c==9) {
                    c=8-(x&7);
                    x += c;
                    pos += c<<1;
                    if (x>video_num_columns) {
                        x -= video_num_columns;
                        pos -= video_size_row;
                        lf();
                    }
                    c=9;
                } else if (c==7)
                    sysbeep();
                break;
            case 1:
                state=0;
                if (c=='[')
                    state=2;
                else if (c=='E')
                    gotoxy(0,y+1);
                else if (c=='M')
                    ri();
                else if (c=='D')
                    lf();
                else if (c=='Z')
                    respond(tty);
                else if (x=='7')
                    save_cur();
                else if (x=='8')
                    restore_cur();
                break;
            case 2:
                for(npar=0;npar<NPAR;npar++)
                    par[npar]=0;
                npar=0;
                state=3;
                if ((ques=(c=='?')))
                    break;
            case 3:
                if (c==';' && npar<NPAR-1) {
                    npar++;
                    break;
                } else if (c>='0' && c<='9') {
                    par[npar]=10*par[npar]+c-'0';
                    break;
                } else state=4;
            case 4:
                state=0;
                switch(c) {
                    case 'G': case '`':
                        if (par[0]) par[0]--;
                        gotoxy(par[0],y);
                        break;
                    case 'A':
                        if (!par[0]) par[0]++;
                        gotoxy(x,y-par[0]);
                        break;
                    case 'B': case 'e':
                        if (!par[0]) par[0]++;
                        gotoxy(x,y+par[0]);
                        break;
                    case 'C': case 'a':
                        if (!par[0]) par[0]++;
                        gotoxy(x+par[0],y);
                        break;
                    case 'D':
                        if (!par[0]) par[0]++;
                        gotoxy(x-par[0],y);
                        break;
                    case 'E':
                        if (!par[0]) par[0]++;
                        gotoxy(0,y+par[0]);
                        break;
                    case 'F':
                        if (!par[0]) par[0]++;
                        gotoxy(0,y-par[0]);
                        break;
                    case 'd':
                        if (par[0]) par[0]--;
                        gotoxy(x,par[0]);
                        break;
                    case 'H': case 'f':
                        if (par[0]) par[0]--;
                        if (par[1]) par[1]--;
                        gotoxy(par[1],par[0]);
                        break;
                    case 'J':
                        csi_J(par[0]);
                        break;
                    case 'K':
                        csi_K(par[0]);
                        break;
                    case 'L':
                        csi_L(par[0]);
                        break;
                    case 'M':
                        csi_M(par[0]);
                        break;
                    case 'P':
                        csi_P(par[0]);
                        break;
                    case '@':
                        csi_at(par[0]);
                        break;
                    case 'm':
                        csi_m();
                        break;
                    case 'r':
                        if (par[0]) par[0]--;
                        if (!par[1]) par[1] = video_num_lines;
                        if (par[0] < par[1] &&
                            par[1] <= video_num_lines) {
                            top=par[0];
                            bottom=par[1];
                        }
                        break;
                    case 's':
                        save_cur();
                        break;
                    case 'u':
                        restore_cur();
                        break;
                }
        }
    }
    set_cursor();
}

(四)大功告成,編譯運(yùn)行把~

報(bào)告:

(1)在原始代碼中棕诵,按下F12,中斷響應(yīng)后凿将,中斷服務(wù)程序會(huì)調(diào)用func校套?它實(shí)現(xiàn)的是什么功能?
將F12轉(zhuǎn)義成轉(zhuǎn)義字符序列 [ [ L , 對(duì)F1-F12處理類似 [ [ A -> [ [ L

(2) 在你的實(shí)現(xiàn)中牧抵,是否把向文件輸出的字符也過(guò)濾了笛匙?如果是侨把,那么怎么能只過(guò)濾向終端輸出的字符?如果不是妹孙,那么怎么能把向文件輸出的字符也一并進(jìn)行過(guò)濾秋柄?

實(shí)現(xiàn)中并沒有把向文件輸出的字符也過(guò)濾,在copy_to_cooked函數(shù)處理中并不是將字符放到write_q蠢正,然后調(diào)用con_write來(lái)顯示到控制臺(tái)骇笔。
而是shell通過(guò)上層的sys_write系統(tǒng)調(diào)用將tty->secondary隊(duì)列中的字符顯示出來(lái)的。而在sys_write的實(shí)現(xiàn)過(guò)程中調(diào)用了tty_write函數(shù)嚣崭。
所以只修改tty_write后笨触,按鍵回顯當(dāng)然也變成’*’,第二次按的時(shí)候回復(fù)原來(lái)的樣子;

因此要想將向文件輸出的字符一并進(jìn)行過(guò)濾,需要修改file_write函數(shù)雹舀。設(shè)置Flag芦劣,如果為F12按下狀態(tài),將從內(nèi)核態(tài)讀出的數(shù)據(jù)轉(zhuǎn)為‘*’賦給用戶空間即可

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末说榆,一起剝皮案震驚了整個(gè)濱河市媒惕,隨后出現(xiàn)的幾起案子猎荠,更是在濱河造成了極大的恐慌吉挣,老刑警劉巖井濒,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件废麻,死亡現(xiàn)場(chǎng)離奇詭異荠卷,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)烛愧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門油宜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人怜姿,你說(shuō)我怎么就攤上這事慎冤。” “怎么了沧卢?”我有些...
    開封第一講書人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵蚁堤,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我但狭,道長(zhǎng)披诗,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任立磁,我火速辦了婚禮呈队,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘唱歧。我一直安慰自己宪摧,他們只是感情好粒竖,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著几于,像睡著了一般蕊苗。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上孩革,一...
    開封第一講書人閱讀 51,598評(píng)論 1 305
  • 那天岁歉,我揣著相機(jī)與錄音,去河邊找鬼膝蜈。 笑死锅移,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的饱搏。 我是一名探鬼主播非剃,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼推沸!你這毒婦竟也來(lái)了备绽?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤鬓催,失蹤者是張志新(化名)和其女友劉穎肺素,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宇驾,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡倍靡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了课舍。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片塌西。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖筝尾,靈堂內(nèi)的尸體忽然破棺而出捡需,到底是詐尸還是另有隱情,我是刑警寧澤筹淫,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布站辉,位于F島的核電站,受9級(jí)特大地震影響损姜,放射性物質(zhì)發(fā)生泄漏庵寞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一薛匪、第九天 我趴在偏房一處隱蔽的房頂上張望捐川。 院中可真熱鬧,春花似錦逸尖、人聲如沸古沥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)岩齿。三九已至太颤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間盹沈,已是汗流浹背龄章。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留乞封,地道東北人做裙。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像肃晚,于是被迫代替她去往敵國(guó)和親锚贱。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355

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