第七章 程序g分析和增加控制台和吐槽

一、程序g分析

其在第六章基础上增加的内容

 

1. 一个内核进程ring1,三个用户进程ring3

include\proc.h

#define NR_TASKS             1               

#define NR_PROCS           3

 

2. 四个进程的定义

kernel\global.c文件

PUBLIC     PROCESS  proc_table[NR_TASKS + NR_PROCS];

PUBLIC     TASK          task_table[NR_TASKS] = {{task_tty,STACK_SIZE_TTY, "tty"}};

PUBLIC     TASK          user_proc_table[NR_PROCS] = {     {TestA, STACK_SIZE_TESTA,"TestA"},

                                                        {TestB,STACK_SIZE_TESTB, "TestB"},

                                                        {TestC,STACK_SIZE_TESTC, "TestC"}};

3.进程的激活

kernel\main.c

 

4.关键点

4.1关注内核ring1进程task_tty,进程触发会调用函数task_tty(),此函数初始化键盘和初始化tty,设置屏幕,然后while循环tty_do_readtty_do_write

结构TTY

/* TTY */

typedef struct s_tty

{

         t_32 in_buf[TTY_IN_BYTES];   /* TTY 输入缓冲区 */

         t_32*        p_inbuf_head;          /* 指向缓冲区中下一个空闲位置 */

         t_32*        p_inbuf_tail;              /* 指向键盘任务应处理的键值 */

         int    inbuf_count;              /*缓冲区中已经填充了多少 */

 

         structs_console *   p_console;

}TTY;

 

kernel/tty.c

#define TTY_FIRST            (tty_table)                                             //extern  TTY            tty_table[];

#define TTY_END              (tty_table + NR_CONSOLES)             // #define          NR_CONSOLES                  3

 

/*======================================================================*

                           task_tty

 *======================================================================*/

PUBLIC void task_tty()

{

         TTY*         p_tty;

         init_keyboard();                          //初始化键盘

         for(p_tty=TTY_FIRST;p_tty<TTY_END;p_tty++)   

         {

                   init_tty(p_tty);

         }

         select_console(0);           //kernel/console.c

         while(1) {

                   for(p_tty=TTY_FIRST;p_tty<TTY_END;p_tty++) {

                            tty_do_read(p_tty);

                            tty_do_write(p_tty);

                   }

         }

}

4.2   init_keyboard初始化键盘中断,设置led灯和设置键盘中断处理程序,当按键时就会触发函数keyboard_handler执行,此函数每次执行都会读取一个字节内容丢到KB_INPUT结构体

kernel/keyboard.c

typedef struct s_kb {

         char*        p_head;                      /*指向缓冲区中下一个空闲位置 */

         char*        p_tail;                         /*指向键盘任务应处理的字节 */

         int    count;                         /*缓冲区中共有多少字节 */

         char buf[KB_IN_BYTES];  /* 缓冲区 */

}KB_INPUT;

/*======================================================================*

                           init_keyboard

 *======================================================================*/

PUBLIC void init_keyboard()

{

         kb_in.count= 0;

         kb_in.p_head= kb_in.p_tail = kb_in.buf;

 

         caps_lock          = 0;

         num_lock = 1;

         scroll_lock        = 0;

 

         set_leds();                 //设置键盘的三个灯

 

         put_irq_handler(KEYBOARD_IRQ,keyboard_handler); /* 设定键盘中断处理程序,当按下键盘会执行函数keyboard_handler */

         enable_irq(KEYBOARD_IRQ);                              /* 开键盘中断 */

}

 

/*======================================================================*

                            keyboard_handler

 *======================================================================*/

PUBLIC void keyboard_handler(int irq)

{

         t_8scan_code = in_byte(KB_DATA);  //读取一个字节

 

         if(kb_in.count < KB_IN_BYTES)// PRIVATE      KB_INPUT         kb_in;

          {

                   *(kb_in.p_head)= scan_code;

                   kb_in.p_head++;

                   if(kb_in.p_head == kb_in.buf + KB_IN_BYTES) {

                            kb_in.p_head= kb_in.buf;

                   }

                   kb_in.count++;

         }

}

 

4.3 init_tty()函数初始化TTY

kernel/tty.c

PRIVATEvoid init_tty(TTY* p_tty)

{

         p_tty->inbuf_count = 0;

         p_tty->p_inbuf_head =p_tty->p_inbuf_tail = p_tty->in_buf;

 

         init_screen(p_tty);                     //初始化屏幕kernel/console.c

}

4.4tty_do_read循环读

kernel/tty.c

/*======================================================================*

                              tty_do_read

*======================================================================*/

PRIVATEvoid tty_do_read(TTY* p_tty)

{

         if(is_current_console(p_tty->p_console)) {

                   keyboard_read(p_tty);              //调用键盘读内容

         }

}

 

 

kernel/keyboard.c

/*======================================================================*

                           keyboard_read

 *======================================================================*/

PUBLIC void keyboard_read(TTY* p_tty)

{

       t_8  scan_code;

       t_bool    make;    /*TRUE : make  */

                     /*FALSE: break */

       t_32       key = 0;/* 用一个整型来表示一个键。 */

                     /*比如,如果 Home 被按下,则 key 值将为定义在 keyboard.h 中的 'HOME'。*/

       t_32*     keyrow;  /*指向 keymap[] 的某一行 */

 

       if(kb_in.count> 0){

              code_with_E0= FALSE;

              scan_code= get_byte_from_kb_buf();

 

              /* 下面开始解析扫描码 */

              if(scan_code == 0xE1) {

                     inti;

                     t_8pausebreak_scan_code[] = {0xE1, 0x1D, 0x45, 0xE1, 0x9D, 0xC5};

                     t_boolis_pausebreak = TRUE;

                     for(i=1;i<6;i++){

                            if(get_byte_from_kb_buf() != pausebreak_scan_code[i]) {

                                   is_pausebreak= FALSE;

                                   break;

                            }

                     }

                     if(is_pausebreak) {

                            key= PAUSEBREAK;

                     }

              }

              elseif (scan_code == 0xE0) {

                     code_with_E0= TRUE;

                     scan_code= get_byte_from_kb_buf();

 

                     /*PrintScreen 被按下 */

                     if(scan_code == 0x2A) {

                            code_with_E0= FALSE;

                            if((scan_code = get_byte_from_kb_buf()) == 0xE0) {

                                   code_with_E0= TRUE;

                                   if((scan_code = get_byte_from_kb_buf()) == 0x37) {

                                          key= PRINTSCREEN;

                                          make= TRUE;

                                   }

                            }

                     }

                     /*PrintScreen 被释放 */

                     elseif (scan_code == 0xB7) {

                            code_with_E0= FALSE;

                            if((scan_code = get_byte_from_kb_buf()) == 0xE0) {

                                   code_with_E0= TRUE;

                                   if((scan_code = get_byte_from_kb_buf()) == 0xAA) {

                                          key= PRINTSCREEN;

                                          make= FALSE;

                                   }

                            }

                     }

              } /* 如果不是 PrintScreen。则此时 scan_code 为 0xE0 紧跟的那个值。 */

              if((key != PAUSEBREAK) && (key != PRINTSCREEN)) {

                     /*首先判断Make Code 还是 Break Code */

                     make= (scan_code & FLAG_BREAK ? FALSE : TRUE);

                    

                     /*先定位到 keymap 中的行 */

                     keyrow= &keymap[(scan_code & 0x7F) * MAP_COLS];

 

                     column= 0;

 

                     t_boolcaps = shift_l || shift_r;

                     if(caps_lock) {

                            if((keyrow[0] >= 'a') && (keyrow[0] <= 'z')){

                                   caps= !caps;

                            }

                     }

                     if(caps) {

                            column= 1;

                     }

 

                     if(code_with_E0) {

                            column= 2;

                     }

 

                     key= keyrow[column];

 

                     switch(key){

                     caseSHIFT_L:

                            shift_l    = make;

                            break;

                     caseSHIFT_R:

                            shift_r    = make;

                            break;

                     caseCTRL_L:

                            ctrl_l      = make;

                            break;

                     caseCTRL_R:

                            ctrl_r     = make;

                            break;

                     caseALT_L:

                            alt_l       = make;

                            break;

                     caseALT_R:

                            alt_l       = make;

                            break;

                     caseCAPS_LOCK:

                            if(make) {

                                   caps_lock   = !caps_lock;

                                   set_leds();

                            }

                            break;

                     caseNUM_LOCK:

                            if(make) {

                                   num_lock    = !num_lock;

                                   set_leds();

                            }

                            break;

                     caseSCROLL_LOCK:

                            if(make) {

                                   scroll_lock= !scroll_lock;

                                   set_leds();

                            }

                            break;

                     default:

                            break;

                     }

              }

 

              if(make){/* 忽略 Break Code */

                     t_boolpad = FALSE;

 

                     /*首先处理小键盘 */

                     if((key >= PAD_SLASH) && (key <= PAD_9)) {

                            pad= TRUE;

                            switch(key){ /* '/', '*', '-', '+', and 'Enter' innum pad  */

                            casePAD_SLASH:

                                   key= '/';

                                   break;

                            casePAD_STAR:

                                   key= '*';

                                   break;

                            casePAD_MINUS:

                                   key= '-';

                                   break;

                            casePAD_PLUS:

                                   key= '+';

                                   break;

                            casePAD_ENTER:

                                   key= ENTER;

                                   break;

                            default:  /* keys whose value depends on the NumLock */

                                   if(num_lock) {    /* '0' ~ '9' and '.' innum pad */

                                          if((key >= PAD_0) && (key <= PAD_9)) {

                                                 key= key - PAD_0 + '0';

                                          }

                                          elseif (key == PAD_DOT) {

                                                 key= '.';

                                          }

                                   }

                                   else{

                                          switch(key){

                                          casePAD_HOME:

                                                 key= HOME;

                                                 break;

                                          casePAD_END:

                                                 key= END;

                                                 break;

                                          casePAD_PAGEUP:

                                                 key= PAGEUP;

                                                 break;

                                          casePAD_PAGEDOWN:

                                                 key= PAGEDOWN;

                                                 break;

                                          casePAD_INS:

                                                 key= INSERT;

                                                 break;

                                          casePAD_UP:

                                                 key= UP;

                                                 break;

                                          casePAD_DOWN:

                                                 key= DOWN;

                                                 break;

                                          casePAD_LEFT:

                                                 key= LEFT;

                                                 break;

                                          casePAD_RIGHT:

                                                 key= RIGHT;

                                                 break;

                                          casePAD_DOT:

                                                 key= DELETE;

                                                 break;

                                          default:

                                                 break;

                                          }

                                   }

                                   break;

                            }

                     }

                     key|= shift_l       ? FLAG_SHIFT_L  : 0;

                     key|= shift_r       ? FLAG_SHIFT_R  : 0;

                     key|= ctrl_l  ? FLAG_CTRL_L   : 0;

                     key|= ctrl_r ? FLAG_CTRL_R   : 0;

                     key|= alt_l   ? FLAG_ALT_L      : 0;

                     key|= alt_r  ? FLAG_ALT_R     : 0;

                     key|= pad    ? FLAG_PAD  : 0;

 

                     in_process(p_tty, key);

              }

       }

}

kernel/tty.c

/*======================================================================*

                          in_process

 *======================================================================*/

PUBLIC void in_process(TTY* p_tty, t_32 key)

{

       if (!(key& FLAG_EXT)) {

              put_key(p_tty,key);

       }

       else {

              intraw_code = key & MASK_RAW;

              switch(raw_code){

              caseENTER:

                     put_key(p_tty,'\n');

                     break;

              caseBACKSPACE:

                     put_key(p_tty,'\b');

                     break;

              caseUP:

                     if((key & FLAG_SHIFT_L) || (key & FLAG_SHIFT_R)) {      /* Shift + Up */

                            scroll_screen(p_tty->p_console,SCROLL_SCREEN_UP);

                     }

                     break;

              caseDOWN:

                     if((key & FLAG_SHIFT_L) || (key & FLAG_SHIFT_R)) {      /* Shift + Down */

                            scroll_screen(p_tty->p_console,SCROLL_SCREEN_DOWN);

                     }

                     break;

              caseF1:

              caseF2:

              caseF3:

              caseF4:

              caseF5:

              caseF6:

              caseF7:

              caseF8:

              caseF9:

              caseF10:

              caseF11:

              caseF12:

                     if((key & FLAG_ALT_L) || (key & FLAG_ALT_R)) {      /* Alt + F1~F12 */

                            select_console(raw_code - F1);

                     }

                     break;

              default:

                     break;

              }

       }

}

4.4tty_do_read循环写

/*======================================================================*

                              tty_do_write

*======================================================================*/

PRIVATEvoid tty_do_write(TTY* p_tty)

{

         if (p_tty->inbuf_count) {

                   char ch =*(p_tty->p_inbuf_tail);

                   p_tty->p_inbuf_tail++;

                   if (p_tty->p_inbuf_tail ==p_tty->in_buf + TTY_IN_BYTES) {

                            p_tty->p_inbuf_tail= p_tty->in_buf;

                   }

                   p_tty->inbuf_count--;

 

                   //disp_int(ch);

                   out_char(p_tty->p_console,ch);

         }

}

二、修改程序g

修改程序g然后增加一个控制台和多增加一个进程d

1. 一个内核进程ring1,三个用户进程ring3

include\proc.h

#define NR_TASKS             1

#define NR_PROCS           4                          //多加入一个进程

 

#define STACK_SIZE_TTY                   0x8000

#define STACK_SIZE_TESTA     0x8000

#define STACK_SIZE_TESTB     0x8000

#define STACK_SIZE_TESTC     0x8000

#define STACK_SIZE_TESTD     0x8000 //多加入一个进程

 

#define STACK_SIZE_TOTAL     (STACK_SIZE_TTY + \

                                     STACK_SIZE_TESTA+ \

                                     STACK_SIZE_TESTB+ \

                                     STACK_SIZE_TESTC+ \

                                     STACK_SIZE_TESTD)

 

2.kernel\global.c

 

PUBLIC     TASK          user_proc_table[NR_PROCS] = {     {TestA, STACK_SIZE_TESTA,"TestA"},

                                                        {TestB,STACK_SIZE_TESTB, "TestB"},

                                                        {TestC,STACK_SIZE_TESTC, "TestC"},

                                                        {TestD,STACK_SIZE_TESTD, "TestD"}};

 

3.include\const.h

#define     NR_CONSOLES                  4       /* consoles 多加入控制台*/

4.kernel\main.c

绑定控制台和进程和进程有限级别

PUBLIC int tinix_main()

{

         proc_table[4].ticks= proc_table[4].priority =  5;  //设置进程D的优先级别为5

         ..

         proc_table[4].nr_tty= 3;   //设置进程D绑定第四个控制台

}

 

多加入一个进程

/*======================================================================*

                               TestD

 *======================================================================*/

void TestD()

{

         inti = 0;

         while(1){

                   printf("snow");

                   milli_delay(200);

         }

}

 

5.加入TestD的定义

include\proto.h

PUBLIC void     TestD();

OK成功

 

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值