设计 任务书 文档 开题 答辩 说明书 格式 模板 外文 翻译 范文 资料 作品 文献 课程 实习 指导 调研 下载 网络教育 计算机 网站 网页 小程序 商城 购物 订餐 电影 安卓 Android Html Html5 SSM SSH Python 爬虫 大数据 管理系统 图书 校园网 考试 选题 网络安全 推荐系统 机械 模具 夹具 自动化 数控 车床 汽车 故障 诊断 电机 建模 机械手 去壳机 千斤顶 变速器 减速器 图纸 电气 变电站 电子 Stm32 单片机 物联网 监控 密码锁 Plc 组态 控制 智能 Matlab 土木 建筑 结构 框架 教学楼 住宅楼 造价 施工 办公楼 给水 排水 桥梁 刚构桥 水利 重力坝 水库 采矿 环境 化工 固废 工厂 视觉传达 室内设计 产品设计 电子商务 物流 盈利 案例 分析 评估 报告 营销 报销 会计
 首 页 机械毕业设计 电子电气毕业设计 计算机毕业设计 土木工程毕业设计 视觉传达毕业设计 理工论文 文科论文 毕设资料 帮助中心 设计流程 
垫片
您现在所在的位置:首页 >>理工论文 >> 文章内容
                 
垫片
   我们提供全套毕业设计和毕业论文服务,联系微信号:biyezuopin QQ:2922748026   
基于Linux内核的键盘模拟实现
文章来源:www.biyezuopin.vip   发布者:毕业作品网站  

  关键词: 系统调用   勾子函数   键盘模拟

1  引言
    当前,由于Linux资源完全公开,使得Linux的发展日益广泛快速。基于Linux的各种应用已逐渐深入日常生活的方方面面,尤其是在嵌入式领域,由于内核可裁减定制,因此可随意地根据用户需求进行整个系统的定制与重构其中,我们可以通过对各种标准外部设备的驱动进行改造,从而实现用户对标准设备的特定需求,例如可以通过对键盘的模拟来实现操作的自动化,从而可以避免重复的键盘操作。http://www.16sheji8.cn/

2  Linux内核支持的外部调用接口
    由于Linux内核作为系统最深层次的核心,因此外部的开发人员并不能直接对内核进行操作。然而在一些应用程序的开发过程中,又不得不使用内核的某些功能,因此就提供了一些外部接口供开发人员直接与底层内核打交道。
2.1  中断
    在Linux 下,硬件中断叫做IRQ(Interrupt Requests)。有两种IRQ,短类型和长类型。短IRQ需要很短的时间,在此期间机器的其他部分被锁定,而且没有其他中断被处理。一个长IRQ需要较长的时间,在此期间可能发生其他中断(但不是发自同一个设备)。如果可能的话,最好把一个中段声明为长类型。如果CPU接到一个中断,它就会停止一切工作(除非它正在处理一个更重要的中断,在这种情况下要等到更重要的中断处理结束后才会处理这个中断),把相关的参数存储到栈里,然后调用中断处理程序。这意味着在中断处理程序本身中有些事情是不允许的,因为这时系统处在一个未知状态。解决这个问题的方法是让中断处理程序做需要马上做的事,通常是从硬件读取信息或给硬件发送信息,然后把对新信息的处理调度到以后去做。
    实现的方法是在接到相关的IRQ(在Intel平台上有16个IRQ)时调用中断处理程序。这个函数接到IRQ号码、函数名、标志、一个/proc/interrupts的名字和传给中断处理程序的一个参数。标志中可以包括 SA_SHIRQ来表明你希望和其他处理程序共享此IRQ(通常很多设备公用一个IRQ),或者一个SA_INTERRUPT表明这是一个紧急中断。这个函数仅在此IRQ没有其他处理程序或需要共享所有处理程序时才会成功运行。
2.2  系统调用
    系统调用发生在用户进程,通过一些特殊的函数来请求内核提供服务。这时,用户进程被挂起,内核验证用户请求,尝试执行并把结果反馈给用户进程,接着用户进程重新启动。一般当前系统的系统调用作为一张表sys_call_table进行定义的,是由指向实现各种系统调用的内核函数的函数指针组成的表。具体参数参见Linux内核源代码arch/i386/kernel/entry.S文件中:
ENTRY(sys_call_table)
l long SYMBOL_NAME(sys_ni_syscall)
/* 0 - old "setup()" system call*/
l long SYMBOL_NAME(sys_exit)

l long SYMBOL_NAME(sys_ni_syscall)
/* streams2 */
l long SYMBOL_NAME(sys_vfork)
/* 190 */ http://www.16sheji8.cn/
2.3  钩子函数
    钩子(HOOK)是Linux系统中非常重要的系统接口,用它可以截获并处理送给其他应用程序的消息,来完成普通应用程序难以实现的功能。钩子可以监视系统或进程中的各种事件消息,截获发往目标的消息并进行处理。这样就可以在系统中安装自定义的钩子,监视系统中特定事件的发生,完成特定的功能,比如截获键盘、鼠标的输入,屏幕取词,日志监视等等。可见,利用钩子可以实现许多特殊而有用的功能。

3  键盘工作机理
    CPU对外部设备的管理是通过中断程序进行的,键盘也是一种外部设备,因此,CPU对键盘的管理也是通过中断进行的。当你击打键盘的时候,键盘控制器会向CPU提出中断申请,CPU响应此中断进行处理,这就完成了一次很简单与人之间通过键盘进行的交互。
首先,当输入一个键盘值的时候,键盘将会发送相应的scancodes给键盘驱动。一个独立的击键可以产生一个六个scancodes的队列。键盘驱动中的 handle_ scancode()函数解析scancodes流并通过kdb_translate()函数里的转换表(translation-table)将击键事件和键的释放事件(key release events)转换成连续的keycode。例如,'a'的keycode是30。击键'a'的时候便会产生keycode 30。释放a键的时候会产生keycode 158(128+30)。
    然后,这些keycode通过对keymap的查询被转换成相应key符号。获得的字符被送入raw tty队列—tty_flip_buffer。receive_buf()函数周期性的从tty_flip_buffer中获得字符,然后把这些字符送入 tty read队列。
当用户进程需要得到用户的输入的时候,它会在进程的标准输入(stdin)调用read()函数。sys_read()函数调用定义在相应的tty设备(如/dev/tty0)的file_operations结构中指向tty_read的read()函数来读取字符并且返回给用户进程。

4  键盘模拟的实现
    通常情况下,对键盘模拟的实现一般是通过写一个自己的键盘中断句柄来实现,但这种方法容易导致系统崩溃。因此,在这种方法的基础上可以利用勾子函数来实现。
如附图所示,这里主要用到的勾子函数包括handle_ scancode(),put_queue(),receive_buf(),tty_read()和sys_read()等函数。
 
附图     键盘驱动原理图


4.1  handle_scancode函数
    handle_scancode函数是键盘驱动程序中的一个入口函数(参见文件/usr/src/linux/drives/char/keyboard.c):
    void handle_scancode(unsigned char scancode, int down);
    这里通过替换原始的handle_scancode()函数来实现纪录所有的scancode。即将原始的值保存,把新的值注册进去,从而实现所需要的功能,最后再调用回到原始值的情况下。当此新的功能函数完成后,我们就可以记录下键盘上的正确的击键行为了(其中可以包括一些特殊的key,如ctrl, alt,shift,print screen等等)。
4.2  put_queue函数
handle_scancode()函数会调用put_queue函数,用来将字符放入tty_queue。
put_queue函数在内核中定义如下:
void put_queue(int ch)
{
wake_up(&keypress_wait);
if (tty) {
tty_insert_flip_char(tty, ch, 0);
con_schedule_flip(tty);    }}
4.3  receive_buf函数
底层tty驱动调用receive_buf()这个函数用来发送硬件设备接收处理的字符。参见/usr/src/linux/drivers/char/n_tty.c:
static void n_tty_receive_buf(struct tty_struct *tty, const
unsigned char *cp, char *fp, int count)
参数cp是一个指向设备接收的输入字符的buffer的指针。参数fp是一个指向一个标记字节指针的指针。在具体的实现中,先保存原始的tty receive_buf()函数,然后重置ldisc.receive_buf到自定义的new_receive_buf()函数来记录用户的输入。
例如:要记录在终端tty1设备上的输入。
int fd = open("/dev/tty1", O_RDONLY, 0);
struct file *file = fget(fd);
struct tty_struct *tty = file->private_data;
//保存原始的receive_buf()函数
old_receive_buf = tty->ldisc.receive_buf;
//替换成新的new_receive_buf函数
tty->ldisc.receive_buf = new_receive_buf;   
//新的new_receive_buf函数
void new_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
{    http://www.16sheji8.cn/
logging(tty, cp, count);    
//纪录用户击键
/* 调用回原来的receive_buf */
(*old_receive_buf)(tty, cp, fp, count);
}
4.4  tty_read函数
当一个进程需要通过sys_read()函数来读取一个tty终端的输入字符时,tty_read函数就会被调用。参见文件/usr/src/linux/drives/char/tty_io.c:http://www.16sheji8.cn/
static ssize_t tty_read(struct file * file, char * buf, size_t count,
loff_t *ppos)

5  结束语
    目前,利用勾子函数实现基于Linux内核的键盘模拟的这种方法使用非常灵活,同时也可以跨平台进行移植,可通过tty和pts来记录下本地和远程会话的所有击键动作,并且也支持一些特殊的按键。当然,要使键盘模拟更灵活,下一步还需要更多的改进,例如增加多种不同日志记录模式的支持等。

  全套毕业设计论文现成成品资料请咨询微信号:biyezuopin QQ:2922748026     返回首页 如转载请注明来源于www.biyezuopin.vip  

                 

打印本页 | 关闭窗口
本类最新文章
苗系统虚拟机 混合动力汽车电池文献检索摘要及英 行星齿轮变速箱的分析方法
移动应用开发实训指导书 板材的的等径角挤压 悬架的机械设计对动态加载过程的影
| 关于我们 | 友情链接 | 毕业设计招聘 |

Email:biyeshejiba@163.com 微信号:biyezuopin QQ:2922748026  
本站毕业设计毕业论文资料均属原创者所有,仅供学习交流之用,请勿转载并做其他非法用途.如有侵犯您的版权有损您的利益,请联系我们会立即改正或删除有关内容!