切换虚拟终端简介40484.docx
切换虚拟终端概述linux使用用虚拟终端,这这些虚拟终端端对应/dev/tty1/dev/tty8,它们由系统统初始化时打打开。这个过过程也在键盘盘的中断服务务程序中完成成。用户用ALT+11.8或ALT+箭头来切换换终端。每个个虚拟终端对对应一个tty_sstructt和一个termiios结构。Termiios结构存储输输入输出及控控制模式,一一些底层参数数。Tty_sstructt 和终端的关关系如同task_struuct 和进程的关关系。一个tty被打开,就就对应一个tty_sstractt,对终端的一一切处理都围围绕tty_sstrct 进行。Termiios也被tty_sttruct的一个指针针指向。当然然,tty_sstructt 和 termmios 结构相对独独立,tty被完全关闭闭时,tty_sstructt也就不在存存在,而termiios 依然存在。另:1与虚拟终端相相对的是实终终端。它对应应/dev/tty0 或/dev/consoole 二者设备号号均为4,0(2035)系统初始时tty的初始化分分早期和晚期期。早期初始始化支持实终终端,晚期初始化支支持虚拟终端端。此时/dev/ttty0 或/dev/consoole 对应当前终终端。2 伪终端正如如其名,与控控制台终端除除了最高层的的输入输出功功能类似外,底底层的实现大大相径庭。终端切换的流程程:Keyboard_interruptKey_handler(do_cons)Set_conslewant_coonsolee = nrr;mark_bbh(CONNSOLE_BH);Console_bhChange_consolecomplete_change_consoleUpdate_screenstatic void keybooard_iinterrrupt(iint irrq, vooid *ddev_idd, strruct ppt_reggs *regs)handdle_sccancodde(scaancodee);(*key_hhandleertyppe)(kkeysymm & 0xxff, uup_flaag);k_hand key_hhandleerkeyboarrd.c键盘特殊输入的的特殊处理函函数数组。static k_hannd keyy_handdler116 = do_sellf, doo_fn, do_sppec, ddo_padd, do_dead, do_ccons, do_cuur, doo_shifft,do_metta, doo_asciii, do_loock, ddo_lowwercasse, doo_slocck,do_ignnore, do_iggnore, do_iignoree;do_conss()改变终端的最上上层函数keyboarrd.cstatic void do_coons(unnsigneed chaar vallue, cchar uup_flaag)if (upp_flagg)returrn;set_coonsolee(valuue);set_connsole()设置want_consoole 为欲切换到到的终端。设设置consoole的bottom hhalf 标志。kbd_kerrn.hextern inlinne voiid sett_conssole(iint nrr)want_cconsolle = nnr;mark_bbh(CONNSOLE_BH);consolee_bh()consolee.cstatic void consoole_bhh(voidd)是否要切换coonsoleeif (waant_coonsolee >= 00) if (wwant_cconsolle != fg_coonsolee) channge_coonsolee(want_consoole);/* wwe onlly chaanged when the cconsolle hadd alreeady bbeen aallocaated - a neew connsole is noot creeated iin an interrrupt routiine */want_consoole = -1;if (doo_pokee_blannked_cconsolle) /* doo not unblaank foor a LLED chhange */do_pooke_bllankedd_conssole = 0;poke_blankked_coonsolee();change_consoole()tty_io.c切换终端的实际际动作。void chhange_consoole(unnsigneed intt new_consoole)if (new_consoole = fg_cconsolle) | (vt_dont_switcch) rreturnn; if (!vc_ccons_aallocaated(nnew_coonsolee)returrn;/*If thiss vt iis in proceess moode, tthen wwe neeed to handsshake with什什么模式?在此模式下下,不能直接接切换,要等等待! * thatt proccess bbeforee swittchingg. Esssentiaally, we sttore wwhere that * vt wantss to sswitchh to aand waait foor it to teell uss whenn it'ss donee * (viia VT_RELDIISP iooctl). * * We also checkk to ssee iff the contrrollinng proocess stilll exissts. 控制进程 * If it dooesn'tt, we resett thiss vt tto autto modde andd conttinue. 什么模式? * Thiis is a cheeap waay to trackk proccess ccontrool. Thhe worrst thhing * thaat cann happeen is: we ssend aa signnal too a prrocesss, it dies, and * thee swittch geets "llost" waitiing foor a rresponnse; hhopefuully, the * useer willl tryy agaiin, wee'll ddetectt the proceess iss gonee (unlless * thee userr waitts jusst thee righht amoount oof timme :-) and reverrt thee * vt to auuto coontroll. */VT_PROCCESS模式式的处理。在在此模式下,不不能直接切换换,要等待!if (vtt_conssfg_cconsolle->vvt_modde.modde = VT_PRROCESSS)/* * Seend thhe siggnal aas priivilegged - kill_proc() willl * teell uss if tthe prrocesss has gone or soomethiing ellse * iss awryy */if (kkill_pproc(vvt_connsfg_consoole->>vt_piid, vt_consfg_coonsolee->vtt_modee.relssig, 1) = 0)/* * IIt worrked. Mark the vvt to switcch to and * rreturnn. Thee proccess nneeds to seend uss a * VVT_RELLDISP ioctll to ccompleete thhe swiitch. */vt_cconsffg_connsole->vt_newvtt = neew_connsole;retuurn;/* * Thhe conntrollling pprocesss hass diedd, so we reevert back to * noormal operaation. In tthis ccase, we'lll alsoo channge baack * too KD_TTEXT mmode. I'm nnot suure iff thiss is sstricttly coorrectt * buut it savess the agonyy whenn the X serrver ddies aand thhe scrreen * reemainss blannked ddue too KD_GGRAPHIICS! IIt wouuld bee nicee to ddo * thhis ouutsidee of VVT_PROOCESS but tthere is noo singgle prrocesss * too accoount ffor annd traackingg tty countt may be unndesirrable. */reset_vc(fgg_conssole);/* * Faall thhroughh to nnormall (VT_AUTO) handdling of thhe swiitch. */在KD_GRAAPHICSS+VT_AAUTO模式式下忽略所有有终端切换。if (vtt_conssfg_cconsolle->vvc_modde = KD_GRRAPHICCS)returrn;compleete_chhange_consoole(neew_connsole);相关函数与变量量判断新的虚拟拟终端是否存存在。int vc_cons_alloccated(unsiggned iint i)/connsole.creturrn (i < MAXX_NR_CCONSOLLES &&& vc_cconsii.d);重设新的虚拟拟终端的vc_daate结构。void reeset_vvc(unssignedd int new_cconsolle)/ttty_ioo.cvt_connsneww_conssole->vc_mmode = KD_TTEXT;kbd_taablennew_coonsolee.kbddmode = VC_XLATEE;vt_connsneww_conssole->vt_mmode.mmode = VT_AAUTO;vt_connsneww_conssole->vt_mmode.wwaitv = 0;vt_connsneww_conssole->vt_mmode.rrelsigg = 0;vt_connsneww_conssole->vt_mmode.aacqsigg = 0;vt_connsneww_conssole->vt_mmode.ffrsig = 0;vt_connsneww_conssole->vt_ppid = -1;vt_connsneww_conssole->vt_nnewvt = -1;reset_palettte (nnew_coonsolee) ;complette_chaange_cconsolle()切换终端的实际际动作。tty_io.cvoid coomplette_chaange_cconsolle(unssignedd int new_cconsolle)unsignned chhar olld_vc_mode; if (new_consoole = fg_cconsolle) | (vt_dont_switcch) rreturnn; if (!vc_ccons_aallocaated(nnew_coonsolee) rreturnn;last_cconsolle = ffg_connsole;/* * If we'ree swittchingg, we couldd be ggoing from KD_GRRAPHICCS to * KD_TEXT mode or viice veersa, whichh meanns we need to bllank oor * unbblank the sscreenn lateer. */old_vcc_modee = vtt_conssfg_cconsolle->vvc_modde;根据new_cconsolle重设显示器器。updatee_screeen(neew_connsole);/* * If this new cconsolle is underr proccess ccontrool, seend itt a siignal * tellling it thhat itt has acquiired. Also checkk if iit hass diedd and * cleean upp (simmilar to loogic eemployyed inn channge_coonsolee() */if (vtt_conssnew_consoole->>vt_moode.moode = VT_PPROCESSS)/* * Seend thhe siggnal aas priivilegged - kill_proc() willl * teell uss if tthe prrocesss has gone or soomethiing ellse * iss awryy */if (kkill_pproc(vvt_connsneww_conssole->vt_ppid, vt_consnew_cconsolle->vvt_modde.acqqsig, 1) != 0)/* * Thhe conntrollling pprocesss hass diedd, so we reevert back to * noormal operaation. In tthis ccase, we'lll alsoo channge baack * too KD_TTEXT mmode. I'm nnot suure iff thiss is sstricttly coorrectt * buut it savess the agonyy whenn the X serrver ddies aand thhe scrreen * reemainss blannked ddue too KD_GGRAPHIICS! IIt wouuld bee nicee to ddo * thhis ouutsidee of VVT_PROOCESS but tthere is noo singgle prrocesss * too accoount ffor annd traackingg tty countt may be unndesirrable. */ reeset_vvc(neww_conssole);/* * We do thhis heere beecausee the contrrollinng proocess abovee may have * gonne, annd so theree is nnow a new vvc_modde */if (olld_vc_mode != vtt_conssnew_consoole->>vc_moode)if (vvt_connsneww_conssole->vc_mmode = KD_TEXT)文本模式do_uunblannk_scrreen();else 图形模式do_bblank_screeen(1);/* Sett the colouur pallette for tthis VVT */if (vtt_conssnew_consoole->>vc_moode = KD_TTEXT)set_ppalettte() ;/* * Wakke anyyone wwaitinng forr theiir VT to acctivatte */vt_wakke_waiitactiive();returnn;相关函数与变量量#definee vt_wwake_wwaitacctive() wakke_up(&vt_aactivaate_quueue)update_screeen()consolee.c重设屏幕。void uppdate_screeen(intt new_consoole)staticc int lock = 0;lock保证该该函数不会被被重入。if (neew_connsole = fgg_conssole | locck)returrn;if (!vvc_conns_alllocateed(neww_conssole) /* sttrangee . */printtk("uppdate_screeen: ttty %d not aallocaated ?n", new_consoole+1);returrn;lock = 1;清除屏幕被选择择部分。clear_selecction();if (!cconsolle_blaanked)get_sscrmemm(fg_cconsolle);elseconsoole_bllankedd = -11; /* no llongerr of tthe foorm coonsolee+1 */fg_connsole = neww_conssole; /* thhis iss the only (nonzzero) assiggnmentt to ffg_connsole */ /* connsequeently, fg_cconsolle willl alwways bbe alllocateed */set_sccrmem(fg_coonsolee, 0); /vvga.cset_orrigin(fg_coonsolee);set_cuursor(fg_coonsolee);set_leeds(); recommpute k_dowwn aand shhift_sstate from key_ddown */computte_shiiftstaate(); / liinux/ddriverrs/chaar/keyyboardd.clock = 0;相关函数与变量量clear_sselecttion(vvoid) /seelectiion.chighllight_pointter(-11); /* hidee the pointter */if (seel_staart != -1) highhlightt(sel_startt, sell_end);sel_startt = -11; innt connsole_blankked = 0; /consoole.c