一、程序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_read和tty_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成功