日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > windows >内容正文

windows

java开发操作系统:启动任意多控制台窗口

發(fā)布時(shí)間:2024/3/13 windows 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java开发操作系统:启动任意多控制台窗口 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

當(dāng)前我們的系統(tǒng)已經(jīng)能夠?qū)崿F(xiàn)多個(gè)控制臺(tái)窗口,要想生成兩個(gè)以上的控制臺(tái)窗口,只需在窗口生成時(shí)的for循環(huán)處,增加循環(huán)次數(shù)即可?,F(xiàn)在我們系統(tǒng)啟動(dòng)時(shí),一下子會(huì)看到兩個(gè)控制臺(tái)窗口,這看起來太詭異了。

對(duì)于windows來說,我們完全可以在一個(gè)控制臺(tái)窗口中運(yùn)行命令start cmd.exe來啟動(dòng)一個(gè)新的控制臺(tái)窗口,本節(jié)我們將模仿該功能,使得我們能在一個(gè)控制臺(tái)窗口中,通過命令來啟動(dòng)新的控制臺(tái)窗口。

在完成這個(gè)復(fù)雜的功能前,我們先實(shí)現(xiàn)一個(gè)稍微簡單點(diǎn)的功能練練手。我們先實(shí)現(xiàn)通過按鍵shift+w 來啟動(dòng)一個(gè)新的控制臺(tái)窗口。先在kernel.asm中增加段選擇子的數(shù)目:

[SECTION .gdt]; 段基址 段界限 屬性 LABEL_GDT:.... %rep 30 Descriptor 0, 0, 0 %endrep

然后在CMain主入口函數(shù)中添加如下代碼:

void CMain(void) {....struct SHEET *sht_cons[2];int console_count = 0;sht_cons[0] = launch_console(0);console_count++;//sheet_slide(shtctl, sht_cons[1], 156, 176);sheet_slide(shtctl, sht_cons[0], 8, 2);// sheet_updown(shtctl, sht_cons[1], 1);sheet_updown(shtctl, sht_cons[0], 2);first_task_cons_selector = task_cons[0]->sel; ....for(;;) {if (fifo8_status(&keyinfo) + fifo8_status(&mouseinfo) +fifo8_status(&timerinfo) == 0) {io_sti();} else if(fifo8_status(&keyinfo) != 0){io_sti();data = fifo8_get(&keyinfo);....if (key_shift != 0 && data == 0x11) {sht_cons[console_count] = launch_console(console_count);sheet_slide(shtctl, sht_cons[console_count], 156, 176);sheet_updown(shtctl, sht_cons[console_count], 1);console_count++;}} }.... }

此外我們?cè)赾md_hlt函數(shù)中再做一些修改:

void cmd_hlt() {....int code_seg = 21 + task->sel - first_task_cons_selector;int mem_seg = 30 + task->sel - first_task_cons_selector;.... }

first_task_cons_selector 是第一個(gè)控制臺(tái)進(jìn)程對(duì)應(yīng)的段選擇子,做上面的修改后,在不同的控制臺(tái)中執(zhí)行hlt命令啟動(dòng)用戶程序時(shí),不同的用戶程序的代碼段和數(shù)據(jù)段就會(huì)指向不同的段,這樣當(dāng)我們后面實(shí)現(xiàn)多控制臺(tái)功能后,通過不同控制臺(tái)啟動(dòng)的用戶程序就不會(huì)發(fā)送段沖突。上面代碼完成后,加載內(nèi)核,系統(tǒng)啟動(dòng)后,同時(shí)按下shift鍵和w鍵,可以看到有一個(gè)新的控制臺(tái)出現(xiàn)在界面上:

接下來,我們要擴(kuò)展該功能,使得系統(tǒng)能夠生成任意多個(gè)控制臺(tái)進(jìn)程。當(dāng)控制臺(tái)進(jìn)程可以無限多時(shí),我們?cè)瓉碛糜诖鎯?chǔ)進(jìn)程的數(shù)組和控制臺(tái)圖層窗口的數(shù)組就沒有用了,因此代碼要做相應(yīng)改動(dòng),在write_vga_desktop.c中,去掉task_cons數(shù)組,換成一個(gè)執(zhí)行控制臺(tái)進(jìn)程的指針:

//static struct TASK *task_cons[2]; int first_task_cons_selector = 0; static struct TASK *task_main = 0, *current_console_task;

我們會(huì)生成多個(gè)控制臺(tái)進(jìn)程,而在任何時(shí)候只會(huì)有一個(gè)控制臺(tái)進(jìn)程處于激活狀態(tài),這個(gè)被激活的進(jìn)程將會(huì)用current_console_task這個(gè)指針變量來代替。當(dāng)我們點(diǎn)擊tab鍵時(shí),要實(shí)現(xiàn)主進(jìn)程和激活控制臺(tái)進(jìn)程的切換,而且當(dāng)有按鍵信息輸入時(shí),按鍵內(nèi)容要傳遞給當(dāng)前正在處于激活狀態(tài)的控制臺(tái)進(jìn)程,因此相關(guān)代碼的修改如下:

void CMain(void) {....struct SHEET* sht_cons;//*sht_cons[2];int console_count = 0;sht_cons = launch_console(0);console_count++;//sheet_slide(shtctl, sht_cons[1], 156, 176);sheet_slide(shtctl, sht_cons, 8, 2);// sheet_updown(shtctl, sht_cons[1], 1);sheet_updown(shtctl, sht_cons, 2);// first_task_cons_selector = task_cons[0]->sel; ....for(;;) {....if (data == 0x0f) {int msg = -1;if (key_to == 0) {key_to = 1;if (current_console == 1) {current_console = 0;} else {current_console = 1;}make_wtitle8(shtctl, shtMsgBox,"task_a", 0);//change heremake_wtitle8(shtctl, current_console_task->sht, "console", 1);set_cursor(shtctl, shtMsgBox, cursor_x, 28 ,COL8_FFFFFF); msg = PROC_RESUME;} else {key_to = 0;make_wtitle8(shtctl, shtMsgBox, "task_a",1);make_wtitle8(shtctl, current_console_task->sht, "console", 0);msg = PROC_PAUSE;} sheet_refresh(shtctl, shtMsgBox, 0, 0, shtMsgBox->bxsize, 21);//change heresheet_refresh(shtctl, current_console_task->sht, 0, 0, current_console_task->sht->bxsize, 21);//send_message(task_a, task_cons[current_console], msg);}if (key_to == 0) {if (transferScanCode(data) != 0 && cursor_x < 144) {set_cursor(shtctl, shtMsgBox, cursor_x,28 ,COL8_FFFFFF);char c = transferScanCode(data);char buf[2] = {c, 0};showString(shtctl, shtMsgBox, cursor_x, 28, COL8_000000, buf);cursor_x += 8;stop_task_A = 1;set_cursor(shtctl, shtMsgBox, cursor_x, 28, cursor_c);} } else if (isSpecialKey(data) == 0) {//change herefifo8_put(&(current_console_task->fifo), data);if (fifo8_status(&keyinfo) == 0) { task_sleep(task_a);}}}....} }

我們修改主入口處代碼,讓系統(tǒng)啟動(dòng)時(shí)只創(chuàng)建一個(gè)控制臺(tái)進(jìn)程,同時(shí)當(dāng)用戶按下tab鍵時(shí),讓主進(jìn)程與當(dāng)前正處于激活狀態(tài)的控制臺(tái)窗口進(jìn)行切換,并且當(dāng)用戶點(diǎn)擊鍵盤時(shí),鍵盤信息會(huì)被主進(jìn)程先拿到,然后主進(jìn)程再把按鍵消息通過指針current_console_task,傳遞給當(dāng)前活躍的控制臺(tái)進(jìn)程。

現(xiàn)在問題是,當(dāng)如果系統(tǒng)上有多個(gè)控制臺(tái)進(jìn)程時(shí),我們?nèi)绾螞Q定哪一個(gè)是激活的呢,由于控制臺(tái)窗口可能會(huì)有多個(gè),因此我們不能像以前一樣根據(jù)tab按鍵來固定的切換不同進(jìn)程,這次我們修改為,用戶用鼠標(biāo)點(diǎn)擊哪個(gè)控制臺(tái)窗口,那么它就轉(zhuǎn)換為激活的控制臺(tái)進(jìn)程,控制鼠標(biāo)動(dòng)作的函數(shù)是show_mouse_info,因此我們要對(duì)它的代碼加以修改:

void show_mouse_info(struct SHTCTL *shtctl, struct SHEET *sht_back,struct SHEET *sht_mouse) {....if (0 <= x && x < sht->bxsize && 0 <= y && y < sht->bysize) {if (sht->buf[y * sht->bxsize + x] != sht->col_inv) {//change heremake_wtitle8(shtctl, current_console_task->sht, "console", 0);sheet_refresh(shtctl,current_console_task->sht, 0, 0, sht->bxsize, sht->bysize);current_console_task = sht->task;make_wtitle8(shtctl, current_console_task->sht, "console", 1);sheet_refresh(shtctl, sht, 0, 0, sht->bxsize, sht->bysize);}....}

當(dāng)鼠標(biāo)挪動(dòng)并點(diǎn)擊時(shí),上面的代碼會(huì)被調(diào)用。代碼先查詢當(dāng)前鼠標(biāo)落入哪個(gè)窗口中,它先把上一個(gè)幾乎窗口的標(biāo)題欄由藍(lán)色轉(zhuǎn)換為灰色,接著把當(dāng)前鼠標(biāo)點(diǎn)擊的窗口標(biāo)題欄設(shè)置成藍(lán)色,并把current_console_task指針指向當(dāng)前圖層所對(duì)應(yīng)的進(jìn)程對(duì)象。要完成上面的代碼,我們需要修改一下TASK和SHEET這兩個(gè)結(jié)構(gòu)體的設(shè)置,一是在TASK結(jié)構(gòu)體中增加一個(gè)圖層對(duì)象,二是在SHEET結(jié)構(gòu)體中增加一個(gè)TASK對(duì)象,打開multi_task.h和win_sheet.h做如下修改:

struct TASK {int sel, flags;int priority;int level;struct FIFO8 fifo;struct TSS32 tss;struct CONSOLE console;struct Buffer *pTaskBuffer;//change herestruct SHEET *sht; };struct SHEET {unsigned char *buf;int bxsize, bysize, vx0, vy0, col_inv, height, flags;struct TASK *task; };

我們?cè)趩?dòng)控制臺(tái)進(jìn)程時(shí),也要做相應(yīng)修改,當(dāng)內(nèi)核創(chuàng)建一個(gè)控制臺(tái)進(jìn)程時(shí),它會(huì)調(diào)用launch_console函數(shù),這個(gè)函數(shù)執(zhí)行時(shí),不但要像原來一樣啟動(dòng)一個(gè)新的控制臺(tái)進(jìn)程,還需要把current_console_task指向它,并且把原來的活躍進(jìn)程設(shè)置成非激活狀態(tài),代碼修改如下:

struct SHEET* launch_console(int i) {....//change hereif (i > 0) {make_window8(shtctl, sht_cons, "console", 1);} else {make_window8(shtctl, sht_cons, "console", 0);}//change heretask_console->sht = sht_cons;sht_cons->task = task_console;//inactive last console windowif (current_console_task != 0) {make_wtitle8(shtctl, current_console_task->sht, "console", 0);sheet_refresh(shtctl, current_console_task->sht, 0, 0, current_console_task->sht->bxsize, current_console_task->sht->bysize);}current_console_task = task_console;....// task_cons[i] = task_console;.... }

如果創(chuàng)建新的控制臺(tái)進(jìn)程時(shí),current_console_task不為空,那表明當(dāng)前進(jìn)程并非第一個(gè),因此它會(huì)把原來激活的進(jìn)程設(shè)置成非激活狀態(tài),并把當(dāng)前新建進(jìn)程設(shè)置成激活狀態(tài)。

由于當(dāng)前控制臺(tái)進(jìn)程變多,在控制臺(tái)中啟動(dòng)用戶進(jìn)程時(shí),需要做相應(yīng)修改:

void cmd_hlt() { .... //change here select is multiply of 8, divided by 8 get the original valueint code_seg = 21 + (task->sel - first_task_cons_selector) / 8;int mem_seg = 30 + (task->sel - first_task_cons_selector) / 8;//22;.... }

啟動(dòng)用戶進(jìn)程時(shí),需要為其分配代碼段和內(nèi)存段描述符,不同控制臺(tái)啟動(dòng)的用戶進(jìn)程,必須對(duì)應(yīng)不同的描述符,我們用當(dāng)前進(jìn)程的段描述符減去第一個(gè)進(jìn)程的段描述符,然后分別加上21和30后得到的結(jié)果作為代碼段描述符和內(nèi)存段描述符的下標(biāo)。其中除以8是因?yàn)?#xff0c;我們?cè)谥付枋龇聵?biāo)時(shí),需要左移3位,也就相當(dāng)于乘以8,因此求差值時(shí)要除以8,這樣才能得到當(dāng)前進(jìn)程與第一個(gè)控制臺(tái)進(jìn)程間的間隔。

上面代碼完成后,加載內(nèi)核,運(yùn)行效果如下:

系統(tǒng)每次通過shift+w創(chuàng)建一個(gè)新控制臺(tái)進(jìn)程時(shí),新窗口會(huì)自動(dòng)變?yōu)榧せ顮顟B(tài),你用鼠標(biāo)點(diǎn)擊其中某個(gè)控制臺(tái)窗口后,被點(diǎn)擊的控制臺(tái)會(huì)自動(dòng)轉(zhuǎn)換成激活態(tài)。雖然我們現(xiàn)在控制臺(tái)進(jìn)程的數(shù)量可以無限制增長,但我們?cè)趍ulti_task.h中定義了進(jìn)程的最大數(shù)量:

#define MAX_TASKS 10

也就是內(nèi)核當(dāng)前支持的進(jìn)程數(shù)量最大是10個(gè)。

當(dāng)控制臺(tái)窗口可以一次生成多個(gè)后,如何把他們關(guān)閉就變得很有必要。接下來我們實(shí)現(xiàn)把控制臺(tái)窗口關(guān)閉的功能,現(xiàn)在global_define.h中修改一下CONSOLE結(jié)構(gòu)體的定義:

struct CONSOLE {struct SHEET *sht;int cur_x, cur_y, cur_c;char s[2];struct TIMER *timer;//change herechar *cmdline; };

增加cmdline指針的目的是,在窗口關(guān)閉后能把它對(duì)應(yīng)的內(nèi)存給釋放掉。接著我們?cè)黾訋讉€(gè)關(guān)于結(jié)構(gòu)體關(guān)閉及相關(guān)內(nèi)存釋放的功能:

//change here add console closing function void close_constask(struct TASK *task) {task_sleep(task);//problemmemman_free_4k(memman, task->cons_stack, 64 * 1024);memman_free(memman, (int)task->fifo.buf, 128);memman_free(memman, (int)task->console.cmdline, 30);task->flags = 0;current_console_task = 0; }void close_console(struct SHEET *sht) {struct TASK *task = sht->task;timer_free(task->console.timer);memman_free_4k(memman, (int)sht->buf, 256 * 165);sheet_free(shtctl, sht);close_constask(task); }void cmd_exit(struct TASK *cons_task) {io_cli();//send msg to keyboad queue of main processfifo8_put(&keyinfo, 255);io_sti(); }

我們要實(shí)現(xiàn)的功能之一是,在控制臺(tái)輸入命令”exit”時(shí),控制臺(tái)能自我關(guān)閉,當(dāng)控制臺(tái)執(zhí)行命令exit時(shí),它會(huì)調(diào)用函數(shù)cmd_exit, 在該函數(shù)的實(shí)現(xiàn)中,它向主進(jìn)程發(fā)送了一個(gè)特別的命令255,這個(gè)數(shù)值告訴主進(jìn)程把當(dāng)前激活的控制臺(tái)進(jìn)程給關(guān)閉掉,于是主進(jìn)程受到這個(gè)消息后,會(huì)調(diào)用close_console把對(duì)應(yīng)的控制臺(tái)進(jìn)程給關(guān)閉,之所以要繞個(gè)彎,發(fā)消息給主進(jìn)程來關(guān)閉激活的控制臺(tái)進(jìn)程,是因?yàn)樵赾lose_constask實(shí)現(xiàn)中調(diào)用了task_sleep函數(shù),如果由控制臺(tái)進(jìn)程來調(diào)用close_constask的話,因?yàn)樗约喊炎约航o休眠了,那么后面的代碼就無法執(zhí)行了,因此我們對(duì)主進(jìn)程的代碼也做相應(yīng)修改:

else if(fifo8_status(&keyinfo) != 0){....//when receive data > 768, it should be a console closing messageif (data == 255) {close_console(current_console_task->sht );continue;} .... }

同時(shí)系統(tǒng)支持通過鼠標(biāo)點(diǎn)擊控制臺(tái)窗口右上角的x按鈕把進(jìn)程關(guān)閉,于是在show_mouse_info函數(shù)中也要做代碼修改:

void show_mouse_info(struct SHTCTL *shtctl, struct SHEET *sht_back,struct SHEET *sht_mouse) {....if (sht->bxsize - 21 <= x && x < sht->bxsize - 5 && 5 <= y && y < 19 && sht->task != 0) {//change here/*io_cli();sheet_free(shtctl, sht);int addr_code32 = get_code32_addr();sht->task->tss.eip = (int)kill_process - addr_code32;io_sti();*/cmd_exit(sht->task);}break;.... }

接著修改控制臺(tái)進(jìn)程的主函數(shù),讓他能執(zhí)行exit命令,這個(gè)修改比較簡單:

void console_task(struct SHEET *sheet, int memtotal) {....//change hereelse if ( strcmp(cmdline, "exit") == 1) {cmd_exit(task);}.... }

完成上面代碼后,我們可以通過命令或點(diǎn)擊控制臺(tái)右上角x按鈕的方式把打開的控制臺(tái)進(jìn)程全部關(guān)閉:

更詳細(xì)的講解和代碼調(diào)試演示過程,請(qǐng)參看視頻
Linux kernel Hacker, 從零構(gòu)建自己的內(nèi)核

更多技術(shù)信息,包括操作系統(tǒng),編譯器,面試算法,機(jī)器學(xué)習(xí),人工智能,請(qǐng)關(guān)照我的公眾號(hào):

總結(jié)

以上是生活随笔為你收集整理的java开发操作系统:启动任意多控制台窗口的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。