当前位置: 首页 > news >正文

企业网站改版项目描述网站角色管理

企业网站改版项目描述,网站角色管理,查工程中标信息哪个网站,一个人做网站 没有人写文章怎么办前言 在 Linux 内核中#xff0c;字符设备主要包括控制终端设备和串行终端设备#xff0c;对这些设备的输入输出涉及控制台驱动程序,这包括键盘中断驱动程序 keyboard.S 和控制台显示驱动程序 console.c#xff0c;还有终端驱动程序与上层程序之间的接口部分。 终端驱动程序…前言 在 Linux 内核中字符设备主要包括控制终端设备和串行终端设备对这些设备的输入输出涉及控制台驱动程序,这包括键盘中断驱动程序 keyboard.S 和控制台显示驱动程序 console.c还有终端驱动程序与上层程序之间的接口部分。 终端驱动程序用于控制终端设备在终端设备和进程之间传输数据并对所传输的数据进行一定的处理。用户在键盘上键入的原始数据(Raw data)在通过终端程序处理后被传送给一个接收进程;而进程向终端发送的数据在终端程序处理后会被显示在终端屏幕上或者通过串行线路被发送到远程终端。根据终端程序对待输入或输出数据的方式可以把终端工作模式分成两种。一种是规范(canonical)模式,此时经过终端程序的数据将被进行变换处理,然后再送出。例如把 TAB 字符扩展为8个空格字符,用键入的删除字符(backspace)控制删除前面键入的字符等。使用的处理函数一般称为行规则(linediscipline)或行规程模块。另一种是非规范(non-canonical)模式或称原始(raw)模式。在这种模式下行规则程序仅在终端与进程之间传送数据而不对数据进行规范模式的变换处理。 键盘中断 按下键盘后会触发中断CPU 收到你的键盘中断后根据中断号寻找由操作系统写好的键盘中断处理程序。 内核的初始化如下 void main(void) {...trap_init();... }void trap_init(void) {int i;set_trap_gate(0,divide_error);set_trap_gate(1,debug);set_trap_gate(2,nmi);set_system_gate(3,int3);   /* int3-5 can be called from all */set_system_gate(4,overflow);set_system_gate(5,bounds);set_trap_gate(6,invalid_op);set_trap_gate(7,device_not_available);set_trap_gate(8,double_fault);set_trap_gate(9,coprocessor_segment_overrun);set_trap_gate(10,invalid_TSS);set_trap_gate(11,segment_not_present);set_trap_gate(12,stack_segment);set_trap_gate(13,general_protection);set_trap_gate(14,page_fault);set_trap_gate(15,reserved);set_trap_gate(16,coprocessor_error);for (i17;i48;i)set_trap_gate(i,reserved);set_trap_gate(45,irq13);set_trap_gate(39,parallel_interrupt); } 上面的代码主要划分为 // set 了一堆 trap_gate set_trap_gate(0, divide_error); ...  // 又 set 了一堆 system_gate set_system_gate(45, bounds); ... // 又又批量 set 了一堆 trap_gate for (i17;i48;i)set_trap_gate(i, reserved); 涉及内联汇编的set_trap_gate 和 set_system_gate其作用是在中断描述符表中插入了一个中断描述符 #define _set_gate(gate_addr,type,dpl,addr) \ __asm__ (movw %%dx,%%ax\n\t \movw %0,%%dx\n\t \movl %%eax,%1\n\t \movl %%edx,%2 \: \: i ((short) (0x8000(dpl13)(type8))), \o (*((char *) (gate_addr))), \o (*(4(char *) (gate_addr))), \d ((char *) (addr)),a (0x00080000))#define set_trap_gate(n,addr) \_set_gate(idt[n],15,0,addr)#define set_system_gate(n,addr) \_set_gate(idt[n],15,3,addr) 往这个 idt 表里一项一项地写东西其对应的中断号就是第一个参数中断处理程序就是第二个参数。之后如果来一个中断后CPU 根据其中断号就可以到这个中断描述符表 idt 中找到对应的中断处理程序了。 set_trap_gate(0,divide_error); set_system_gate(5,overflow); 设置 0 号中断对应的中断处理程序是 divide_error。设置 5 号中断对应的中断处理程序是 overflow是边界出错中断。而divide_error当 CPU 执行了一条除零指令的时候会从硬件层面发起一个 0 号异常中断然后执行由我们操作系统定义的 divide_error 也就是除法异常处理程序执行完之后再返回。 其中trap 与 system 的区别仅仅在于设置的中断描述符的特权级不同前者是 0内核态后者是 3用户态这块展开将会是非常严谨的、绕口的、复杂的特权级相关的知识可以理解为都是设置一个中断号和中断处理程序的存在优先级的对应关系就好了。 for (i17;i48;i)set_trap_gate(i,reserved); 17 到 48 号中断都批量设置为了 reserved 函数这是暂时的后面各个硬件初始化时要重新设置好这些中断把暂时的这个给覆盖掉。  最终内存中那个 idt 此时如下图(低端1M虚拟地址与物理地址是相同的) 键盘产生的中断的中断号是 0x21此时这个中断号还仅仅对应着一个临时的中断处理程序 reserved。 void main(void) {...trap_init();...tty_init();...sti();... }void tty_init(void) {rs_init();con_init(); }void con_init(void) {...set_trap_gate(0x21,keyboard_interrupt);... } tty_init (终端是一种字符型设备,它有多种类型。通常使用 tty来简称各种类型的终端设备。tty是 Teletype的缩写它是一种由 Teletype 公司生产的最早出现的终端设备样子很象电传打字机。)最后根据调用链会调用到一行添加 0x21 号中断处理程序的代码set_trap_gate。 而后面的 keyboard_interrupt 就是键盘的中断处理程序 从这一行代码开始键盘中断生效了 现在的中断处于禁用状态不论是键盘中断还是其他中断sti 最终会对应一个同名的汇编指令 sti表示允许中断。所以这行代码之后键盘中断才真正开始生效 串口中断的开启以及设置对应的中断处理程序 void rs_init(void) {set_intr_gate(0x24,rs1_interrupt);set_intr_gate(0x23,rs2_interrupt);init(tty_table[1].read_q.data);init(tty_table[2].read_q.data);outb(inb_p(0x21)0xE7,0x21); } 控制台显示 这些 if else 是为了应对不同的显示模式来分配不同的变量值。 void con_init(void) {...if (ORIG_VIDEO_MODE  7) {...if ((ORIG_VIDEO_EGA_BX  0xff) ! 0x10) {...}else {...}} else {...if ((ORIG_VIDEO_EGA_BX  0xff) ! 0x10) {...}else {...}}... } 当可以随意操作内存和 CPU 等设备内存中有这样一部分区域是和显存映射的。就是你往这些内存区域中写数据相当于写在了显存中。而往显存中写数据就相当于在屏幕上输出文本了。 mov [0xB8000],h //h 相当于汇编编辑器帮我们转换成 ASCII 码的二进制数值当然我们也可以直接写。 mov [0xB8000],0x68 //往内存中 0xB8000 这个位置写了一个值只要一写屏幕左上角则显示一个h 具体说来这片内存是每两个字节表示一个显示在屏幕上的字符第一个是字符的编码第二个是字符的颜色 //当先忽略颜色屏幕左上角会出现hello mov [0xB8000],h mov [0xB8002],e mov [0xB8004],l mov [0xB8006],l mov [0xB8008],o 假设显示模式是文本模式那条件分支就可以去掉很多简化成如下 #define ORIG_X          (*(unsigned char *)0x90000) #define ORIG_Y          (*(unsigned char *)0x90001) void con_init(void) {register unsigned char a;// 第一部分 获取显示模式相关信息video_num_columns  (((*(unsigned short *)0x90006)  0xff00)  8);video_size_row  video_num_columns * 2;video_num_lines  25;video_page  (*(unsigned short *)0x90004);video_erase_char  0x0720;// 第二部分 显存映射的内存区域 video_mem_start  0xb8000;video_port_reg   0x3d4;video_port_val   0x3d5;video_mem_end  0xba000;// 第三部分 滚动屏幕操作时的信息origin   video_mem_start;scr_end  video_mem_start  video_num_lines * video_size_row;top  0;bottom   video_num_lines;// 第四部分 定位光标并开启键盘中断gotoxy(ORIG_X, ORIG_Y);set_trap_gate(0x21,keyboard_interrupt);outb_p(inb_p(0x21)0xfd,0x21);ainb_p(0x61);outb_p(a|0x80,0x61);outb(a,0x61); } 对照内存数据表 所以第一部分获取 0x90006 地址处的数据就是获取显示模式等相关信息。 第二部分就是显存映射的内存地址范围现在假设是 CGA 类型的文本模式所以映射的内存是从 0xB8000 到 0xBA000。 第三部分是设置一些滚动屏幕时需要的参数定义顶行和底行是哪里这里顶行就是第一行底行就是最后一行很合理。 第四部分是把光标定位到之前保存的光标位置处取内存地址 0x90000 处的数据然后设置并开启键盘中断。 开启键盘中断后键盘上敲击一个按键后就会触发中断中断程序就会读键盘码转换成 ASCII 码然后写到光标处的内存地址也就相当于往显存写于是这个键盘敲击的字符就显示在了屏幕上。 gotoxy函数定位当前光标 #define ORIG_X          (*(unsigned char *)0x90000) #define ORIG_Y          (*(unsigned char *)0x90001) void con_init(void) {...// 第四部分 定位光标并开启键盘中断gotoxy(ORIG_X, ORIG_Y);... }static inline void gotoxy(unsigned int new_x,unsigned int new_y) {...x new_x;y new_y;pos origin  y*video_size_row  (x1); } (给 x y pos 这三个参数赋值。) 其中 x 表示光标在哪一列y 表示光标在哪一行pos 表示根据列号和行号计算出来的内存指针也就是往这个 pos 指向的地址处写数据就相当于往控制台的 x 列 y 行处写入字符了然后当你按下键盘后触发键盘中断之后的程序调用链是这样的。 _keyboard_interrupt:...call _do_tty_interrupt...void do_tty_interrupt(int tty) {copy_to_cooked(tty_tabletty); }void copy_to_cooked(struct tty_struct * tty) {...tty-write(tty);... }// 控制台时 tty 的 write 为 con_write 函数 void con_write(struct tty_struct * tty) {...__asm__(movb _attr,%%ah\n\tmovw %%ax,%1\n\t::a (c),m (*(short *)pos):ax);pos  2;x;... } con_write 函数 其中 __asm__ 内联汇编就是把键盘输入的字符 c 写入 pos 指针指向的内存相当于往屏幕输出了。之后两行 pos2 和 x就是调整所谓的光标。 写入一个字符最底层其实就是往内存的某处写个数据然后顺便调整一下光标。 (光标的本质其实就是 x y pos 这三变量而已。) 换行效果 当发现光标位置处于某一行的结尾时知道屏幕上一共有几行几列了就把光标计算出一个新值让其处于下一行的开头。 判断列号 x 是否大于了总列数 void con_write(struct tty_struct * tty) {...if (xvideo_num_columns) {x - video_num_columns;pos - video_size_row;lf();}... }static void lf(void) {if (y1bottom) {y;pos  video_size_row;return;}... } 滚屏的效果无非就是当检测到光标已经出现在最后一行最后一列了那就把每一行的字符都复制到它上一行本质就是算好哪些内存地址上的值拷贝到哪些内存地址即可。 具体而言滚屏操作是指将指定开始行和结束行的一块文本内容向上移动(向上卷动 scroll up)或向下移动(向下卷动 scroll down)。如果将屏幕看作是显示内存上对应屏幕内容的一个窗口的话那么将屏幕内容向上移即是将窗口沿显示内存向下移动;将屏幕内容向下移动即是将窗口向上移动。在程序中就是重新设置显示控制器中显示内存的起始位置 origin 以及调整程序中相应的变量。对于这两种操作各自都有两种情况。 对于向上卷动当屏幕对应的显示内存窗口在向下移动后仍然在显示内存范围之内的情况也即对应当前屏幕的内存块位置始终在显示内存起始位置(video_mem_start)和末端位置 video_mem_end 之间那么只需要调整显示控制器中起始显示内存位置即可。但是当对应屏幕的内存块位置在向下移动时超出了实际显示内存的末端(video_mem_end)这种情况就需要移动对应显示内存中的数据以保证所有当前屏幕数据都落在显示内存范围内。在这第二中情况程序中是将屏幕对应的内存数据移动到实际显示内存的开始位置处(video_mem_ start)。 程序中实际的处理过程分三步进行。首先调整屏幕显示起始位置 origin;然后判断对应屏幕内存数据是否超出显示内存下界(video_mem_end),如果超出就将屏幕对应的内存数据移动到实际显示内存的开始位置处(video_mem_start);最后对移动后屏幕上出现的新行用空格字符填满。 向下卷动屏幕的操作与向上卷屏相似也会遇到这两种类似情况。只是由于屏幕窗口上移因此会在屏幕上方出现一空行并且在屏幕内容所对应的内存超出显示内存范围时需要将屏幕数据内存块往下移动到显示内存的末端位置。 见惯不怪的控制台回车、换行、删除、滚屏、清屏等操作其实底层都有实现相应的代码的。 其中 console.c 中的其他方法就是做这个事的。 // 定位光标的 static inline void gotoxy(unsigned int new_x, unsigned int new_y){} // 滚屏即内容向上滚动一行 static void scrup(void){} // 光标同列位置下移一行 static void lf(int currcons){} // 光标回到第一列 static void cr(void){} ... // 删除一行 static void delete_line(void){} console.c 这个文件可是整个内核中代码量最大的文件但是功能特别单一也都很简单主要是处理键盘各种不同的按键需要写好多 switch case 等语句。其中的所有子程序都是为了实现终端屏幕写函数 con_write()以及进行终端屏幕显示的控制操作。 当往一个控制台设备执行写操作时就会调用 con_write()函数。这个函数管理着所有控制字符和换码字符序列,这些字符给应用程序提供全部的屏幕管理操作。所实现的换码序列采用 vt102 终端的规格,这意味着当你使用 telnet 连接到一台非 Linux 主机时你的环境变量应该有TERMvt102。然而对于本地操作最佳的选择是设置 TERMconsole因为 Limux 控制台提供了一个 vt102 功能的超集。 函数 con_write()主要由转换语句组成用于每次处理一个字符的有限长状态自动转义序列的解释。在正常方式下显示字符会使用当前属性直接写到显示内存中。该函数会从终端 tty_struct数据结构的写缓冲队列 write_q 中取出字符或字符序列然后根据字符的性质(是普通字符、控制字符、转义序列还是控制序列)把字符显示在终端屏幕上或进行一些光标移动、字符除等屏幕控制操作。 终端屏幕初始化函数 con_init()会根据系统启动初始化时获得的系统信息,设置有关屏幕的一些基本参数值用于 con_write()函数的操作。(有关终端设备字符缓冲队列的说明可参见 include/linux/tty.h 头文件。其中给出了字符缓冲队列的数据结构 tty_queue、终端的数据结构 tty_struct 和一些控制字符的值。另外其中还有一些对缓冲队列进行操作的宏定义。)          在此之后内核代码就可以用它来方便地在控制台输出字符这在之后内核想要在启动过程中告诉用户一些信息以及后面内核完全建立起来之后由用户用 shell 进行操作时手动输入命令都是可以用到这里的代码的
http://www.hkea.cn/news/14461876/

相关文章:

  • 朔州海外网络推广成都市seo网站公司
  • 商丘做网站推广的公司找项目网
  • 网站开发哪种专业外贸公司网站如何做推广
  • 长沙网站优化外包公司做网站的费用记什么会计科目
  • 做网站的公司 洛阳越南外贸平台
  • 长春网站排名优化友情链接交易平台源码
  • 磁力离心泵做网站求人做网站
  • 网站链接分析湛江有没有做网站的
  • 衡阳网站建设公司专业的佛山网站设计
  • 江门做公司网站荆州网站开发好招人吗
  • 贵阳手机网站开发江干网站建设
  • 网站网站制作wordpress主题哥
  • 福州网站制作官网昆山网络公司哪家比较好
  • 食品包装设计网站商城网站的搜索记录代码怎么做
  • 如何来建设网站游戏网站建设内容
  • 网站怎么做透明导航东莞优秀网站建设
  • 怎么制作网站布局摄影展示网站源码
  • 制作钓鱼网站教程源码网站制作多久
  • 衡水建设局网站首页移动和生活app下载安装最新版
  • 怎么样创办一个网站凡客生活
  • 网站建设公司哪个好点价格便宜的网站建设
  • 做第三方网站注意什么wordpress 重置密码链接
  • 网站的规划与建设课程设计班级网站设计wordpress
  • 招聘网站开发费用网站浮动条
  • 成都网站建设哪家公司好网站快速收录提交
  • 自助网站搭建系统上海企业网站设计公司电话
  • 西部数码里面如何建设自己的网站长沙网站制作合作商
  • 深圳市住房建设局网站怎么打不开网页制作如何新建站点
  • 花都 网站建设网站备案安全承诺书
  • 网站做第三方登录网站怎么加背景音乐