• 模拟实现Linux命令-wc

    2018-02-27 17:18:13
    模拟实现linux下一个小命令:wc #include #include #include int main(int argc,char *argv[]) { int c=0; int l=0; int w=0; int len=0; int i=0; int status=0; i

    模拟实现linux下一个小命令:wc
    这里写图片描述

    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    int main(int argc,char *argv[])
    {
        int c=0;
        int l=0;
        int w=0;
        int len=0;
        int i=0;
        int status=0;
    
        if(argc!=2)
        {
            fprintf(stderr,"usage:./a.out test.c");
            exit(0);
        }
    
        FILE *fp=fopen("test.c","r");
        if(fp==NULL)
        {
            fprintf(stderr,"can't open!");
            exit(1);
        }
    
        fseek(fp,0,SEEK_END);
         len=ftell(fp);
        rewind(fp);
    
        char *buf=(char *)malloc(len+1);
        fread(buf,len,1,fp);
    
        for( i=0;buf[i];i++)
        {
            c++;
            if(buf[i]=='\n')
            {
                l++;
            }   
            if( !isspace(buf[i]) && status==0)
            {
                w++;
                status=1;
            }
            else if( isspace(buf[i]) )
            {
                status=0;
            }
        }
    
        printf("c=%d l=%d w=%d\n",c,l,w);
    
    
        free(buf);
        fclose(fp);
        fp=NULL;
    
        return 0;
    }
    
    
    展开全文
  • 对于希望学习 ARM 汇编的同学而言, 购买 ARM 开发板进行板上实测无疑是一个有效的方法,不过购买 ARM 开发板需要一笔费用,而且每次测试都需要连接开发板,比较麻烦。这里介绍一个 ARM 模拟器——SkyEye,通过 ...

      对于希望学习 ARM 汇编的同学而言, 购买 ARM 开发板进行板上实测无疑是一个有效的方法,不过购买 ARM 开发板需要一笔费用,而且每次测试都需要连接开发板,比较麻烦。这里介绍一个 ARM 模拟器——SkyEye,通过 SkyEye 我们可以直接在一台 PC 上完成 ARM 汇编程序的开发和调试了,摆脱了 ARM 开发板的限制,真是不错!

      下面介绍如何使用:

      1、下载 SkyEye 的最新版(https://sourceforge.net/projects/skyeye/),本文用的是 skyeye-1.3.4_rc1.tar.gz,同时为了后面的实验,还要下载 testsuite,它是 skyeye 的测试文件,这里的版本是 skyeye-testsuite-1.3.4,里面有 ArmLinux。

      2、安装 SkyEye。

    $ tar zxvf skyeye-1.3.4_rc1.tar.gz
    $ cd skyeye

      根据 INSTALL 文件里说的步骤:

    ./configure
    make lib
    make
    sudo make install
    sudo make install_lib

      注意,在 make 时可能会缺各种文件,apt-get install 就可以了,比如我们这里所遇到的两个问题是:python-dev 和 llvm 没有安装。解决方法很简单:

    $ sudo apt-get install python-dev
    $ sudo apt-get install llvm

      这样 SkyEye 就算安装好了。

    3、添加环境变量。

      默认 SkyEye 是安装在 /opt/ 下的,因此为了方便,我们在环境变量里把它的路径加入,我们写到 .bashrc 文件中,打开它:

    $ vi ~/.bashrc

      输入:

    #SkyEye 1.3.4
    export PATH=/opt/skyeye/bin:$PATH

      之后注销再登录或执行 source .bashrc 就可以使环境变量生效了。

    4、运行 arm_hello 测试程序。

      SkyEye 安装好后会在 /opt/skyeye/testsuite 下有一个 arm_hello 的测试程序,按如下方式运行:

    $ cd /opt/skyeye/testsuite/arm_hello
    $ skyeye -e arm_hello

      注意:skyeye 要运行一个程序时必须要在这个程序的目录里,因为 skyeye 要读取这个程序的 skyeye.conf 配置文件,所以第一步我们要切换到 /opt/skyeye/testsuite/arm_hello 目录下。

      这时我们会进入 skyeye 命令模式,输入 start 让 arm_hello 程序开始运行,会弹出一个“connecting to Ubuntu:xxx”的字样的窗口。

    5、确保 arm_hello 正常运行。

      在 skyeye 命令行输入 run 开始运行,这时窗口会不停的输出“helloworld”,说明 arm_hello 已经成功运行了!

    6、arm_hello 的其他命令。

      在 skyeye 命令行输入 stop 停止运行;输入 quit 退出skyeye;输入 help 查看帮助。


      显然,上面只是安装好了 SkyEye,我们的目的是在 SysEye 中模拟 ARM Linux。那么,下面就来介绍如何在 SkyEye 上启动 Linux,就和在真实的 ARM 开发板上一样。

    1、解压 testsuite 测试文件。

    $ tar zxvf skyeye-testsuite-1.3.4_rc1.tar.gz

      其中的 linux 目录就是我们要移植到板子上的 amrlinux,依次进入:s3c2410 –>s3c2410x-2.6.36,有三个文件,vmlinux 是 Linux 内核镜像,skyeye.conf 是配置文件,initrd.img 是临时根文件系统。我们在 /opt/skyeye/testsuite 下新建一个目录,然后 copy 过来:

    $ sudo mkdir /opt/skyeye/testsuite/armlinux
    $ cd linux/s3c2410/s3c2410x-2.6.36
    $ sudo copy * /opt/skyeye/testsuite/armlinux

    2、运行 vmlinux 。

    $ cd /opt/skyeye/testsuite/armlinux
    $ skyeye -e vmlinux

      进入 skyeye 命令模式,输入 start 打开串口窗口。
      (我在执行这一步时出错:failed to setup_module (name:net, type:cs8900a),我把 skyeye.conf 里的 net 那一行注释掉了,就行了。)
      如果窗口没有打开,则修改 uart:mod=stdiouart:mod=term,然后再试试。

    3、启动 Linux 。

      在 skyeye 命令行输入 run 启动Linux,屏幕随即会输出串口信息,不过速度很慢!

    附几张图:

    这里写图片描述


      上面我们简单介绍了如何使用 SkyEye,并且成功运行了既有的 arm_hello 程序,不过这个是针对 arm7 的,现在我们要用 SkyEye 模拟 s3c2410(arm920T)。下面我们开始 SkyEye 的第二部分。

    1、首先在 /opt/skyeye/testsuite 下建立 myhello 目录。

    $ mkdir /opt/skyeye/testsuite/myhello

    2、添加 myhello.c 文件。

    $ cd /opt/skyeye/testsuite/myhello
    $ vi myhello.c

      输入如下内容:

    #define INTERVAL 100000 
    void myhello(void) 
    {     
      long * addr = (long *)0x50000020; 
      int timeout = 0; 
    
      while(1) { 
        timeout = 0; 
        while(++timeout <= INTERVAL); 
    
        *addr = 'a'; 
      } 
    }

      地址 0x50000020 就是 UART 的通道 0(UTXH0)的发送缓冲,把数据写入这个地址就会自动发送出去,当然在模拟器中,发送的目标地址就是我们的屏幕啦。

    3、准备启动代码。

      myhello.c 写好了之后,我们还要准备一段 s3c2410 的启动代码,这段代码在 s3c2410 一上电之后就开始执行,在这段启动代码中,回跳转到我们写的 myhello.c 函数。打开 start.S 文件:

    $ vi start.S

      输入如下内容:

    .text 
        .align 4 
        .global _start 
    
    _start: 
        ldr sp, =1024*4 
        bl  myhello 
    
    halt: 
        b halt

      上面这段很简单,就是声明了一个 _start 标记,这个标记在下面会用到,作为程序的入口地址。汇编和 C 链接的唯一必须的一步就是设置堆栈,这里我们把 sp 指向 4k 顶部,然后跳转到我们的 c 函数myhello 。

    4、编写链接脚本。

      链接的顺序就是先 start.S 后 myhello.c,打开 myhello.lds 文件:

    $ vi myhello.lds

      输入如下内容:

    OUTPUT_ARCH(arm) 
    ENTRY(_start) 
    SECTIONS 
    { 
      . = 0x00000000; 
      .text :   
      { 
        start.o 
        myhello.o 
        *(.rodata) 
      } 
    
      . = ALIGN(8192); 
    
      .data : {*(.data)} 
    
      .bss : {*(.bss)} 
    }

      表示输出 arm 格式,第二句表示入口点是 _start 标记,就是第3步的那个 _start 标记,然后在 0x00000000 处先插入 start.o,然后插入 myhello.o 。

    5、编写 Makefile 文件。

    $ vi Makefile

      输入如下内容:

    CC=arm-linux-gcc 
    LD=arm-linux-ld 
    CFLAGS= -c -g -march=armv6 -mtune=arm920t   
    LDFLAGS= -N -p -X -Thello.lds 
    
    myhello: start.o myhello.o 
        $(LD) $(LDFLAGS)  start.o myhello.o -o myhello 
        arm-linux-objdump -xS myhello > myhello.s 
        arm-linux-readelf -a myhello > myhello.r 
        arm-linux-nm myhello > myhello.n 
    
    start.o: start.S 
        $(CC) $(CFLAGS) start.S   
    
    myhello.o: myhello.c 
        $(CC) $(CFLAGS) myhello.c 
    
    clean: 
        rm -rf *.o myhello *.r *.n *.s
    arm-linux-objdump -xS myhello > myhello.s
    
    arm-linux-readelf -a myhello > myhello.r
    
    arm-linux-nm myhello > myhello.n

    6、最后我们还需要一个 skyeye 配置文件。

    $ vi skyeye.conf

      输入如下内容:

    #skyeye config file 
    arch:arm 
    cpu: arm920t 
    mach: s3c2410x 
    
    # boot  
    mem_bank: map=M, type=RW, addr=0x00000000, size=0x04000000, boot=yes 
    
    # physical memory  
    mem_bank: map=M, type=RW, addr=0x30000000, size=0x02000000 
    
    # all peripherals I/O mapping area  
    mem_bank: map=I, type=RW, addr=0x48000000, size=0x20000000 
    
    uart:mod=term 
    #log: logon=0, logfile=./sk1.log, start=0, end=200000

    7、编译。

    $ cd /opt/skyeye/testsuite/myhello
    $ make

    8、测试。

    $ cd /opt/skyeye/testsuite/myhello
    $ skyeye -e myhello

      在 skyeye 命令模式下输入:

    start
    run

      我们会发现连续输出了字符“a”,完成!

    【PS:网友建议】源码中有两处值得商榷的地方:

    1) Makefile 第3、4行, 建议为:

    CFLAGS= -c -g -march=armv4 -mtune=arm920t
    LDFLAGS= -N -p -X -Tmyhello.lds

    2) skyeye.config 第15行, 建议为:

    uart:mod=stdio
    展开全文
  • 前文手工处理了int3中断,实现了监控Linux系统键盘输入的效果: https://blog.csdn.net/dog250/article/details/106481123 但是还是太复杂了。在这篇文章中,我深深地知道, int3替换了原来的单字节指令push %rbp,...

    前文手工处理了int3中断,实现了监控Linux系统键盘输入的效果:
    https://blog.csdn.net/dog250/article/details/106481123

    但是还是太复杂了。在这篇文章中,我深深地知道, int3替换了原来的单字节指令push %rbp,所以int3的处理中要想办法恢复原始指令执行。

    于是,我在int3的处理中改变了RIP,将执行流拉入了一个stub函数,执行完push %rbp之后,再return回原始路径。

    这无可厚非,但是不雅。

    不就是一条push %rbp指令嘛,int3中断处理中直接模拟这条指令的效果不就好了嘛:

    • RSP递减一个long型长度:RSP -= 8
    • RBP的值塞入RSP指向的位置:*RSP = RBP

    这还不简单:

    #include <linux/module.h>
    #include <linux/kdebug.h>
    #include <linux/kallsyms.h>
    #include <linux/tty.h>
    
    #define DIE_INT3	2
    
    unsigned long orig;
    int int3_notify(struct notifier_block *self,
    					   unsigned long val,void* data)
    {
    	struct die_args *args = data;
    	struct pt_regs *regs = args->regs;
    	int ret = NOTIFY_DONE;
    
    	switch(val){
    	case DIE_INT3:
    	{
    		unsigned long *rsp;
    		struct tty_struct *tty;
    		char c;
    
    		// 三言两语完成push %rbp操作
    		rsp = (unsigned long *)regs->sp;
    		rsp --;
    		regs->sp = (unsigned long)rsp;
    		*rsp = regs->bp;
    
    		tty = (struct tty_struct *)regs->di;
    		c = regs->si;
    		printk("raw %c  %s\n", c, tty->name);
    		ret = NOTIFY_STOP;
    		break;
    	}
    	default:
    		break;
    	}
    
    	return ret;
    }
    
    static struct notifier_block int3_nb = {
    	.notifier_call = int3_notify,
    	.priority =0x7fffffff,
    };
    
    unsigned char *p, old;
    unsigned long cr0;
    static int __init int3hook_init(void)
    {
        int ret;
    
    	ret = register_die_notifier(&int3_nb);
    	if (ret) {
    		printk("register_die_notifier failed %d\n", ret);
    		return ret;
        }
    
    	orig = (unsigned long)kallsyms_lookup_name("n_tty_receive_char");
    
    	p = (unsigned char *)orig;
    	old = *p;
    	cr0 = read_cr0();
    	clear_bit(16, &cr0);
    	memset(p, 0xcc, 1);
    	set_bit(16, &cr0);
    	write_cr0(cr0);
    
    	return 0;
    }
    
    // exit函数也可以不提供
    static void __exit int3hook_exit(void)
    {
    	cr0 = read_cr0();
    	clear_bit(16, &cr0);
    	memset(p, old, 1);
    	set_bit(16, &cr0);
    	write_cr0(cr0);
    	unregister_die_notifier(&int3_nb);
    }
    
    module_init(int3hook_init)
    module_exit(int3hook_exit)
    MODULE_LICENSE("GPL");
    

    你看,没有了stub函数,是不是清爽了很多呢?

    看看效果:

    [root@localhost probe]# insmod ./2int3hook.ko
    [root@localhost probe]# dmesg
    [  528.960858] raw d  pts0
    [  529.080784] raw m  pts0
    [  529.217513] raw e  pts0
    [  529.392473] raw s  pts0
    [  529.593502] raw 	  pts0
      pts0.104994] raw
    

    dmesg和回车被记录了下来。


    浙江温州皮鞋湿,下雨进水不会胖。

    展开全文
  • 原地址:... driver: linux下如何模拟按键输入和模拟鼠标 2013-09-04 09:02:18 分类: LINUX 概述: 查看/dev/input/eventX是什么类型的事件, cat /proc/bus/input/devices 设备有着自
    原地址:http://blog.chinaunix.net/uid-23381466-id-3883164.html


    driver: linux下如何模拟按键输入和模拟鼠标 2013-09-04 09:02:18

    分类: LINUX

    概述:
    查看/dev/input/eventX是什么类型的事件, cat /proc/bus/input/devices


    设备有着自己特殊的按键键码,我需要将一些标准的按键,比如0-9,X-Z等模拟成标准按键,比如KEY_0,KEY-Z等,所以需要用到按键模拟,具体方法就是操作/dev/input/event1文件,向它写入个input_event结构体就可以模拟按键的输入了。

    input_event 说明:
    linux/input.h中有定义,这个文件还定义了标准按键的编码等

    点击(此处)折叠或打开

    1. struct input_event {

    2. struct timeval time; //按键时间

    3. __u16 type; //类型,在下面有定义

    4. __u16 code; //要模拟成什么按键

    5. __s32 value;//是按下还是释放

    6. };

    code:
    事件的代码.如果事件的类型代码是EV_KEY,该代码code为设备键盘代码.代码植0~127为键盘上的按键代码,0x110~0x116 为鼠标上按键代码,其中0x110(BTN_LEFT)为鼠标左键,0x111(BTN_RIGHT)为鼠标右键,0x112(BTN_ MIDDLE)为鼠标中键.其它代码含义请参看include/linux/input.h文件. 如果事件的类型代码是EV_REL,code值表示轨迹的类型.如指示鼠标的X轴方向REL_X(代码为0x00),指示鼠标的Y轴方向REL_Y(代码为0x01),指示鼠标中轮子方向REL_WHEEL(代码为0x08).

    type:
    EV_KEY,键盘
    EV_REL,相对坐标
    EV_ABS,绝对坐标

    value:
    事件的值.如果事件的类型代码是EV_KEY,当按键按下时值为1,松开时值为0; 如果事件的类型代码是EV_ REL,value的正数值和负数值分别代表两个不同方向的值.

    /*
    * Eventtypes
    */
    #defineEV_SYN 0x00
    #define EV_KEY 0x01 //按键
    #defineEV_REL 0x02 //相对坐标(轨迹球)
    #defineEV_ABS 0x03 //绝对坐标
    #defineEV_MSC 0x04 //其他
    #defineEV_SW 0x05
    #defineEV_LED 0x11 //LED
    #define EV_SND0x12//声音
    #defineEV_REP 0x14//repeat
    #defineEV_FF 0x15
    #defineEV_PWR 0x16
    #define EV_FF_STATUS 0x17
    #define EV_MAX 0x1f
    #define EV_CNT (EV_MAX+1)

    kernel里input模

    点击(此处)折叠或打开

    1. //input_dev结构:
    2. struct input_dev
    3. {
    4.     void *private;

    5.     const char *name;
    6.     const char *phys;
    7.     const char *uniq;
    8.     struct input_id id;

    9.     /*
    10.     * 根据各种输入信号的类型来建立类型为unsigned long 的数组,
    11.     * 数组的每1bit代表一种信号类型,
    12.     * 内核中会对其进行置位或清位操作来表示时间的发生和被处理.
    13.     */

    14.     unsigned long evbit[NBITS(EV_MAX)];
    15.     unsigned long keybit[NBITS(KEY_MAX)];
    16.     unsigned long relbit[NBITS(REL_MAX)];
    17.     unsigned long absbit[NBITS(ABS_MAX)];
    18.     unsigned long mscbit[NBITS(MSC_MAX)];
    19.     unsigned long ledbit[NBITS(LED_MAX)];
    20.     unsigned long sndbit[NBITS(SND_MAX)];
    21.     unsigned long ffbit[NBITS(FF_MAX)];
    22.     unsigned long swbit[NBITS(SW_MAX)];

    23.     .........................................
    24. };

    25. /**
    26. * input_set_capability - mark device as capable of a certain event
    27. * @dev: device that is capable of emitting or accepting event
    28. * @type: type of the event (EV_KEY, EV_REL, etc...)
    29. * @code: event code
    30. *
    31. * In addition to setting up corresponding bit in appropriate capability
    32. * bitmap the function also adjusts dev->evbit.
    33. */

    34. /* 记录本设备对于哪些事件感兴趣(对其进行处理)*/
    35. void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code)
    36. {
    37.     switch (type)
    38.     {
    39.     case EV_KEY:
    40.         __set_bit(code, dev->keybit);//比如按键,应该对哪些键值的按键进行处理(对于其它按键不予理睬)
    41.         break;

    42.     case EV_REL:
    43.         __set_bit(code, dev->relbit);
    44.         break;

    45.     case EV_ABS:
    46.         __set_bit(code, dev->absbit);
    47.         break;

    48.     case EV_MSC:
    49.         __set_bit(code, dev->mscbit);
    50.         break;

    51.     case EV_SW:
    52.         __set_bit(code, dev->swbit);
    53.         break;

    54.     case EV_LED:
    55.         __set_bit(code, dev->ledbit);
    56.         break;

    57.     case EV_SND:
    58.         __set_bit(code, dev->sndbit);
    59.         break;

    60.     case EV_FF:
    61.         __set_bit(code, dev->ffbit);
    62.         break;

    63.     default:
    64.         printk(KERN_ERR
    65.                "input_set_capability: unknown type %u (code %u)\n",
    66.                type, code);
    67.         dump_stack();
    68.         return;
    69.     }

    70.     __set_bit(type, dev->evbit);//感觉和前面重复了(前面一经配置过一次了)
    71. }
    72. EXPORT_SYMBOL(input_set_capability);

    73. static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
    74. {
    75.     int i;
    76.     struct platform_device *pdev = dev_id;
    77.     struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
    78.     struct input_dev *input = platform_get_drvdata(pdev);

    79.     for (= 0; i < pdata->nbuttons; i++)
    80.     {
    81.         struct gpio_keys_button *button = &pdata->buttons[i];
    82.         int gpio = button->gpio;

    83.         if (irq == gpio_to_irq(gpio)) //判断哪个键被按了?
    84.         {
    85.             unsigned int type = button->type ? : EV_KEY;
    86.             int state = (gpio_get_value(gpio) ? 1 : 0) ^ button->active_low;//记录按键状态

    87.             input_event(input, type, button->code, !!state);//汇报输入事件
    88.             input_sync(input);//等待输入事件处理完成
    89.         }
    90.     }

    91.     return IRQ_HANDLED;
    92. }


    93. /*
    94. * input_event() - report new input event
    95. * @dev: device that generated the event
    96. * @type: type of the event
    97. * @code: event code
    98. * @value: value of the event
    99. *
    100. * This function should be used by drivers implementing various input devices
    101. * See also input_inject_event()
    102. */
    103. void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
    104. {
    105.     struct input_handle *handle;

    106.     if (type > EV_MAX || !test_bit(type, dev->evbit))//首先判断该事件类型是否有效且为该设备所接受
    107.         return;

    108.     add_input_randomness(type, code, value);

    109.     switch (type)
    110.     {

    111.     case EV_SYN:
    112.         switch (code)
    113.         {
    114.         case SYN_CONFIG:
    115.             if (dev->event)
    116.                 dev->event(dev, type, code, value);
    117.             break;

    118.         case SYN_REPORT:
    119.             if (dev->sync)
    120.                 return;
    121.             dev->sync = 1;
    122.             break;
    123.         }
    124.         break;

    125.     case EV_KEY:
    126.         /*
    127.         * 这里需要满足几个条件:
    128.         * 1: 键值有效(不超出定义的键值的有效范围)
    129.         * 2: 键值为设备所能接受(属于该设备所拥有的键值范围)
    130.         * 3: 按键状态改变了
    131.         */

    132.         if (code > KEY_MAX || !test_bit(code, dev->keybit) || !!test_bit(code, dev->key) == value)
    133.             return;

    134.         if (value == 2)
    135.             break;

    136.         change_bit(code, dev->key);//改变对应按键的状态

    137.         /* 如果你希望按键未释放的时候不断汇报按键事件的话需要以下这个(在简单的gpio_keys驱动中不需要这个,暂时不去分析) */
    138.         if (test_bit(EV_REP, dev->evbit) && dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] && dev->timer.data && value)
    139.         {
    140.             dev->repeat_key = code;
    141.             mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]));
    142.         }

    143.         break;
    144.         ........................................................

    145.         if (type != EV_SYN)
    146.             dev->sync = 0;

    147.         if (dev->grab)
    148.             dev->grab->handler->event(dev->grab, type, code, value);
    149.         else
    150.             /*
    151.             * 循环调用所有处理该设备的handle(event,mouse,ts,joy等),
    152.             * 如果有进程打开了这些handle(进行读写),则调用其对应的event接口向气汇报该输入事件.
    153.             */
    154.             list_for_each_entry(handle, &dev->h_list, d_node)
    155.             if (handle->open)
    156.                 handle->handler->event(handle, type, code, value);
    157.     }
    158. }
    159. EXPORT_SYMBOL(input_event);


    160. //event层对于input层报告的这个键盘输入事件的处理:
    161. //drivers / input / evdev.c:

    162. static struct input_handler evdev_handler =
    163. {
    164.     .event = evdev_event,
    165.     .connect = evdev_connect,
    166.     .disconnect = evdev_disconnect,
    167.     .fops = &evdev_fops,
    168.     .minor = EVDEV_MINOR_BASE,
    169.     .name = "evdev",
    170.     .id_table = evdev_ids,
    171. };


    Linux 有自己的 input 子系统,可以统一管理鼠标和键盘事件。基于输入子系统 实现的 uinput 可以方便的在用户空间模拟鼠标和键盘事件。
    当然,也可以自己造轮子, 做一个字符设备接收用户输入,根据输入,投递 input 事件。
    还有一种方式就是直接 往 evnent 里写入数据, 都可以达到控制鼠标键盘的功能。

    本篇文章就是演示直接写入 event 的方法。 


    1。模拟按键输

    点击(此处)折叠或打开

    1. //其中0表示释放,1按键按下,2表示一直按下
    2. //0 for EV_KEY for release, 1 for keypress and 2 for autorepeat.

    3. void simulate_key(int fd, int value)
    4. {
    5.     struct input_event event;
    6.     event.type = EV_KEY;
    7. //event.code = KEY_0;//要模拟成什么按键
    8.     event.value = value;//是按下还是释放按键或者重复
    9.     gettimeofday(&event.time, 0);
    10.     if(write(fd, &event, sizeof(event)) < 0)
    11.     {
    12.         dprintk("simulate key error~~~\n");
    13.         return ;
    14.     }
    15. }

    2。模拟鼠标输入(轨迹球

    点击(此处)折叠或打开

    1. void simulate_mouse(int fd, char buf[4])
    2. {
    3.     int rel_x, rel_y;
    4.     static struct input_event event, ev;

    5.     //buf[0],buf[2],小于0则为左移,大于0则为右移
    6.     //buf[1],buf[3],小于0则为下移,大于0则为上移
    7.     
    8.     dprintk("MOUSE TOUCH: x1=%d,y1=%d,x2=%d,y2=%d\n", buf[0], buf[1], buf[2], buf[3]);
    9.     rel_x = (buf[0] + buf[2]) / 2;
    10.     rel_y = -(buf[1] + buf[3]) / 2; //和我们的鼠标是相反的方向,所以取反
    11.     event.type = EV_REL;
    12.     event.code = REL_X;
    13.     event.value = rel_x;
    14.     gettimeofday(&event.time, 0);
    15.     if( write(fd, &event, sizeof(event)) != sizeof(event))
    16.         dprintk("rel_x error~~~:%s\n", strerror(errno));
    17.     event.code = REL_Y;
    18.     event.value = rel_y;
    19.     gettimeofday(&event.time, 0);
    20.     if( write(fd, &event, sizeof(event)) != sizeof(event))
    21.         dprintk("rel_y error~~~:%s\n", strerror(errno));

    22.     //一定要刷新空的
    23.     write(fd, &ev, sizeof(ev));
    24. }

    鼠标和键盘文件打开方法:

    点击(此处)折叠或打开

    1. int fd_kbd; // /dev/input/event1
    2. int fd_mouse; //dev/input/mouse2

    3. fd_kbd = open("/dev/input/event1", O_RDWR);

    4. if(fd_kbd <= 0)
    5. {
    6.     printf("error open keyboard:%s\n", strerror(errno));
    7.     return -1;
    8. }

    9. fd_mouse = open("/dev/input/event3", O_RDWR); //如果不行的话,那试试/dev/input/mice
    10. if(fd_mouse <= 0)
    11. {
    12.     printf("error open mouse:%s\n", strerror(errno));
    13.     return -2;
    14. }

    /dev/input/mice是鼠标的抽象,代表的是鼠标,也许是/dev/input/mouse,/dev/input/mouse1,或者空,这个文件一直会存在。这里你也许会问,我怎么知道/dev/input/eventX这些事件到底是什么事件阿,是鼠标还是键盘或者别的,eventX代表的是所有输入设备(input核心)的事件,比如按键按下,或者鼠标移动,或者游戏遥控器等等,在系统查看的方法是 cat /proc/bus/input/devices 就可以看到每个eventX是什么设备的事件了。

    下面是一个模拟鼠标和键盘输入的例子
    关于这里 open 哪个 event , 可以通过 cat /proc/bus/input/device


    点击(此处)折叠或打开

    1. #include <string.h>
    2. #include <stdio.h>
    3. #include <sys/types.h>
    4. #include <sys/stat.h>
    5. #include <fcntl.h>
    6. #include <linux/input.h>
    7. #include <linux/uinput.h>
    8. #include <stdio.h>
    9. #include <sys/time.h>
    10. #include <sys/types.h>
    11. #include <unistd.h>

    12. void simulate_key(int fd, int kval)
    13. {
    14.     struct input_event event;
    15.     event.type = EV_KEY;
    16.     event.value = 1;
    17.     event.code = kval;
    18.     gettimeofday(&event.time, 0);
    19.     write(fd, &event, sizeof(event)) ;
    20.     event.type = EV_SYN;
    21.     event.code = SYN_REPORT;
    22.     event.value = 0;
    23.     write(fd, &event, sizeof(event));

    24.     memset(&event, 0, sizeof(event));
    25.     gettimeofday(&event.time, NULL);
    26.     event.type = EV_KEY;
    27.     event.code = kval;
    28.     event.value = 0;
    29.     write(fd, &event, sizeof(event));
    30.     event.type = EV_SYN;
    31.     event.code = SYN_REPORT;
    32.     event.value = 0;
    33.     write(fd, &event, sizeof(event));
    34. }

    35. void simulate_mouse(int fd)
    36. {
    37.     struct input_event event;
    38.     memset(&event, 0, sizeof(event));
    39.     gettimeofday(&event.time, NULL);
    40.     event.type = EV_REL;
    41.     event.code = REL_X;
    42.     event.value = 10;
    43.     write(fd, &event, sizeof(event));
    44.     event.type = EV_REL;
    45.     event.code = REL_Y;
    46.     event.value = 10;
    47.     write(fd, &event, sizeof(event));
    48.     event.type = EV_SYN;
    49.     event.code = SYN_REPORT;
    50.     event.value = 0;
    51.     write(fd, &event, sizeof(event));
    52. }

    53. int main()
    54. {
    55.     int fd_kbd;
    56.     int fd_mouse;
    57.     fd_kbd = open("/dev/input/event1", O_RDWR);
    58.     if(fd_kbd <= 0)
    59.     {
    60.         printf("error open keyboard:\n");
    61.         return -1;
    62.     }
    63.     fd_mouse = open("/dev/input/event2", O_RDWR);
    64.     if(fd_mouse <= 0)
    65.     {
    66.         printf("error open mouse\n");
    67.         return -2;
    68.     }
    69.     int i = 0;
    70.     for(i = 0; i < 10; i++)
    71.     {
    72.         simulate_key(fd_kbd, KEY_A + i);
    73.         simulate_mouse(fd_mouse);
    74.         sleep(1);
    75.     }
    76.     close(fd_kbd);
    77. }


    下面是一个读取 鼠标和键盘事件的例子

    点击(此处)折叠或打开

    1. #include <stdio.h>
    2. #include <stdlib.h>
    3. #include <linux/input.h>
    4. #include <sys/types.h>
    5. #include <sys/stat.h>
    6. #include <fcntl.h>
    7. #include <unistd.h>
    8. #include <errno.h>

    9. static void show_event(struct input_event* event)
    10. {
    11.     printf("%d %d %d\n", event->type, event->code, event->value);
    12.     return;
    13. }

    14. int main(int argc, char* argv[])
    15. {
    16.     struct input_event event = {{0}, 0};
    17.     const char* file_name = argc == 2 ? argv[1] : "/dev/input/event2";
    18.     int fd = open(file_name, O_RDWR);

    19.     if(fd > 0)
    20.     {
    21.         while(1)
    22.         {
    23.             int ret = read(fd, &event, sizeof(event));
    24.             if(ret == sizeof(event))
    25.             {
    26.                 show_event(&event);
    27.             }
    28.             else
    29.             {
    30.                 break;
    31.             }
    32.         }
    33.         close(fd);
    34.     }
    35.     return 0;
    36. }



    很多人对于 如何模拟 CTRL + SPACE 感兴趣, 下面也给个例子,呵呵

    点击(此处)折叠或打开

    1. void simulate_ctrl_space(int fd)
    2. {
    3.     struct input_event event;
    4.     //先发送一个 CTRL 按下去的事件。
    5.     event.type = EV_KEY;
    6.     event.value = 1;
    7.     event.code = KEY_LEFTCTRL;
    8.     gettimeofday(&event.time, 0);
    9.     write(fd, &event, sizeof(event)) ;
    10.     event.type = EV_SYN;
    11.     event.code = SYN_REPORT;
    12.     event.value = 0;
    13.     write(fd, &event, sizeof(event));
    14.     //先发送一个 SPACE 按下去的事件。
    15.     event.type = EV_KEY;
    16.     event.value = 1;
    17.     event.code = KEY_SPACE;
    18.     gettimeofday(&event.time, 0);
    19.     write(fd, &event, sizeof(event)) ;
    20.     //发送一个 释放 SPACE 的事件
    21.     memset(&event, 0, sizeof(event));
    22.     gettimeofday(&event.time, NULL);
    23.     event.type = EV_KEY;
    24.     event.code = KEY_SPACE;
    25.     event.value = 0;
    26.     write(fd, &event, sizeof(event));
    27.     event.type = EV_SYN;
    28.     event.code = SYN_REPORT;
    29.     event.value = 0;
    30.     write(fd, &event, sizeof(event));

    31.     //发送一个 释放 CTRL 的事件
    32.     memset(&event, 0, sizeof(event));
    33.     gettimeofday(&event.time, NULL);
    34.     event.type = EV_KEY;
    35.     event.code = KEY_LEFTCTRL;
    36.     event.value = 0;
    37.     write(fd, &event, sizeof(event));

    38.     event.type = EV_SYN;
    39.     event.code = SYN_REPORT;
    40.     event.value = 0;
    41.     write(fd, &event, sizeof(event));
    42. } 



    浅析linux中鼠标数据读取

    点击(此处)折叠或打开

    1. //我们就是去读/dev/input/mice设备节点,源码如下:
    2. #include <stdio.h>
    3. #include <errno.h>
    4. #include <fcntl.h>
    5. #include <sys/select.h>
    6. #include <string.h>

    7. /* Mouse button bits*/
    8. #define WHEEL_UP 0x10
    9. #define WHEEL_DOWN 0x08

    10. #define BUTTON_L 0x04
    11. #define BUTTON_M 0x02
    12. #define BUTTON_R 0x01
    13. #define SCALE 3 /* default scaling factor for acceleration */
    14. #define THRESH 5 /* default threshhold for acceleration */

    15. static int xpos; /* current x position of mouse */
    16. static int ypos; /* current y position of mouse */
    17. static int minx; /* minimum allowed x position */
    18. static int maxx; /* maximum allowed x position */
    19. static int miny; /* minimum allowed y position */
    20. static int maxy; /* maximum allowed y position */
    21. static int buttons; /* current state of buttons */
    22. static int scale = SCALE; /* acceleration scale factor */
    23. static int thresh = THRESH;/* acceleration threshhold */

    24. static int mouse_update(int dx, int dy, int dz);
    25. static int IMPS2_Read (int *dx, int *dy, int *dz, int *bp);
    26. static void mouse_setposition (int newx, int newy);
    27. static void mouse_setrange (int newminx, int newminy, int newmaxx, int newmaxy);

    28. int mouse_fd;

    29. int main(void)
    30. {
    31.     int dx, dy, dz;
    32.     static unsigned char imps2_param [] = {243, 200, 243, 100, 243, 80}; //,242};
    33.     // 来自vnc4的xc/programs/Xserver/hw/xfree86/input/mouse/mouse.c==>PROT_IMPS2
    34.     const char *mdev = "/dev/input/mice";

    35.     mouse_fd = open (mdev, O_RDWR); // | O_NONBLOCK);
    36.     if (mouse_fd < 0)
    37.     {
    38.         printf("[luther.gliethttp]: RW error [please use root user]: %s\n", mdev);
    39.         mouse_fd = open (mdev, O_RDONLY); // | O_NONBLOCK);
    40.         if (mouse_fd < 0)
    41.             return -1;
    42.     }
    43.     else
    44.     {
    45.         write (mouse_fd, imps2_param, sizeof (imps2_param)); // 初始化序列, 这样可以读取4个字节数据
    46.         // 0x80用来表示滚轮向上还是向下滚动
    47.         // 0xa0表示滚轮向上滚动的同时中键按下
    48.         printf("[luther.gliethttp]: imps2_param ok!\n");
    49.     }

    50.     mouse_setrange(0, 0, 1024, 768);

    51.     for (;;)
    52.     {
    53.         IMPS2_Read(&dx, &dy, &dz, &buttons);
    54.         mouse_update(dx, dy, dz);
    55.         mouse_setposition(xpos, ypos);
    56.         printf("[%04d,%04d,0x%04x]\n", xpos, ypos, buttons);
    57.     }

    58.     return 0;
    59. }

    60. static int IMPS2_Read (int *dx, int *dy, int *dz, int *bp)
    61. {
    62.     static unsigned char buf[5];
    63.     static int buttons[7] = { 0, 1, 3, 0, 2, 0, 0}; // 1左键,2中键,3右键
    64.     static int nbytes;
    65.     int n;

    66.     while ((n = read (mouse_fd, &buf [nbytes], 4 - nbytes)))
    67.     {
    68.         if (n < 0)
    69.         {
    70.             if (errno == EINTR)
    71.                 continue;
    72.             else
    73.                 return -1;
    74.         }

    75.         nbytes += n;

    76.         if (nbytes == 4)
    77.         {
    78.             int wheel;
    79.             // printf("[luther.gliethttp]: %02x %02x %02x %02x\n", buf[0], buf[1], buf[2], buf[3]);
    80.             if ((buf[0] & 0xc0) != 0)
    81.             {
    82.                 buf[0] = buf[1];
    83.                 buf[1] = buf[2];
    84.                 buf[2] = buf[3];
    85.                 nbytes = 3;
    86.                 return -1;
    87.             }

    88.             /* FORM XFree86 4.0.1 */
    89.             *bp = buttons[(buf[0] & 0x07)];
    90.             *dx = (buf[0] & 0x10) ? buf[1] - 256 : buf[1];
    91.             *dy = (buf[0] & 0x20) ? -(buf[2] - 256) : -buf[2];

    92.             /* Is a wheel event? */
    93.             if ((wheel = buf[3]) != 0)
    94.             {
    95.                 if(wheel > 0x7f)
    96.                 {
    97.                     *bp |= WHEEL_UP;
    98.                 }
    99.                 else
    100.                 {
    101.                     *bp |= WHEEL_DOWN;
    102.                 }
    103.             }

    104.             *dz = 0;
    105.             nbytes = 0;
    106.             return 1;
    107.         }
    108.     }
    109.     return 0;
    110. }

    111. static int mouse_update(int dx, int dy, int dz)
    112. {
    113.     int r;
    114.     int sign;

    115.     sign = 1;
    116.     if (dx < 0)
    117.     {
    118.         sign = -1;
    119.         dx = -dx;
    120.     }
    121.     if (dx > thresh)
    122.         dx = thresh + (dx - thresh) * scale;
    123.     dx *= sign;
    124.     xpos += dx;
    125.     if( xpos < minx )
    126.         xpos = minx;
    127.     if( xpos > maxx )
    128.         xpos = maxx;

    129.     sign = 1;
    130.     if (dy < 0)
    131.     {
    132.         sign = -1;
    133.         dy = -dy;
    134.     }
    135.     if (dy > thresh)
    136.         dy = thresh + (dy - thresh) * scale;
    137.     dy *= sign;
    138.     ypos += dy;
    139.     if ( ypos < miny )
    140.         ypos = miny;
    141.     if ( ypos > maxy )
    142.         ypos = maxy;

    143.     return 1;
    144. }

    145. static void mouse_setposition (int newx, int newy)
    146. {
    147.     if (newx < minx)
    148.         newx = minx;
    149.     if (newx > maxx)
    150.         newx = maxx;
    151.     if (newy < miny)
    152.         newy = miny;
    153.     if (newy > maxy)
    154.         newy = maxy;
    155.     if (newx == xpos && newy == ypos)
    156.         return;
    157.     xpos = newx;
    158.     ypos = newy;
    159. }

    160. static void mouse_setrange (int newminx, int newminy, int newmaxx, int newmaxy)
    161. {
    162.     minx = newminx;
    163.     miny = newminy;
    164.     maxx = newmaxx;
    165.     maxy = newmaxy;
    166.     mouse_setposition ((newminx + newmaxx) / 2, (newminy + newmaxy) / 2);
    167. }

    168. static int mouse_getbutton (void)
    169. {
    170.     return buttons;
    171. }

    172. static void mouse_getxy (int* x, int* y)
    173. {
    174.     *x = xpos;
    175.     *y = ypos;
    176. }

     
    展开全文
  • Linux模拟按键输入

    2014-05-07 11:37:58
    Linux应用层,可以往/dev/input/event...写入数据来模拟按键输入,程序如下: #include #include #include #include #include #include #include /* struct input_event { struct timeval time; __u16 ...

    在Linux应用层,可以往/dev/input/event...写入数据来模拟按键输入,程序如下:

    #include <linux/input.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <stdint.h>
    #include <stdio.h>
    
    /*
    struct input_event {
    	struct timeval time;
    	__u16 type;
    	__u16 code;
    	__s32 value;
    };
    
    #define EV_KEY                  0x01
    */
    int reportkey(int fd, uint16_t type, uint16_t keycode, int32_t value)
    {
    	struct input_event event;
    
    	event.type = type;
    	event.code = keycode;
    	event.value = value;
    
    	gettimeofday(&event.time, 0);
    
    	if (write(fd, &event, sizeof(struct input_event)) < 0) {
    		printf("report key error!\n");
    		return -1;
    	}
    
    	return 0;
    }
    
    #define DEVNAME "/dev/input/event4"
    
    #define KEYDOWN	1
    #define KEYUP	0
    
    int main(int argc, char *argv[])
    {
    	uint16_t keycode;
    
    	int k_fd;
    
    	k_fd = open(DEVNAME, O_RDWR);
    
    	if (k_fd < 0) {
    		printf("open error!\n");
    		return k_fd;
    	}
    
    	keycode = KEY_A;
    	reportkey(k_fd, EV_KEY, keycode, KEYDOWN);
    	reportkey(k_fd, EV_KEY, keycode, KEYUP);
    
    	close(k_fd);
    
    	return 0;
    }


    展开全文
  • Linux/input.h中定义了以下结构体类型,用于标准按键的编码操作: Struct input_evnet{ Struct timeval time; //按键时间 _u16 type;//类型 _u16 code;//模拟成什么按键码 _u32 value;//...
  • 这段时间写了一个windows下远程监控linux的软件,其中一个最核心的问题就是按键的模拟 windows下发送按键信号,linux下接收后然后模拟标准键盘输入 linux下有一个文件夹 /dev/input ,包含了Linux下所有的输入...
  • java模拟linux命令grep

    2011-03-06 09:29:00
    在网上看到matlab模拟linux的grep命令,就想到用java也来模拟linux命令grep,算法非常简单,,这里直接上代码: /** * 模拟Unix命令grep操作,输出行号和行内容 * @param path 待查询的文件路径 * @param...
  • 大文件数据分为几个区域来模拟简单的文件系统 1.User:username and password 2.SuperBlock:blockSize,blockNum,inodeNum,blockFree 3.blockBitmap:the use state of block area 4.inodeBitmap:the use state of ...
  • linux gpio模拟i2c的使用

    2011-06-29 20:15:00
    linux kernel 中的i2c-gpio使用 在linux中,我们可以自己来使用gpio来模拟i2c,但是万能的linux中其实也已经有了i2c的东东了。 现在看看i2c-gpio.c文件中到底提供了哪些接口static void i2c_gpio_setsda_dir(void ...
  • 上一篇的学习中总结了GPIO的一些基本的概念,GPIO驱动在设备树中的写法,Linux系统下配置gpiolib的方法以及常用接口,本篇的学习总结会进行一次实战操作GPIO,将实现一个驱动可以对IO口进行输入输出以及外部中断的...
  • Linux环境下模拟实现命令解释器 一.程序概述 1. 进入系统概述 本次课程设计是在红帽Linux发行版(Red Hat Enterprise Linux AS release 4 (Nahant Update 4) ))环境下运行,内核为:Kernel 2.6.9-42.ELsmp ...
  • 模拟实现Unix/Linux外壳

    2016-09-13 16:01:35
    模拟实现Unix/Linux外壳注
  • 一、 概述 SPI是英文SerialPeripheral Interface的缩写,顾名思义就是串行外围设备接口。SPI是一种高速、全双工、同步通信总线,标准的SPI有4个引脚,常用于单片机和EEPROM、FLASH、实时时钟、数字信号处理等器件...
  • 一直好奇QQ的通讯过程是怎么实现的,刚学了点linux下的socket编程,所以也想试着模仿下。QQ登陆起初我是想用tcp有连接的方式i,但是发现QQ登陆时并不是一直和服务器连接这的,要不然太耗费服务器资源,应该是服务器每...
  • 1.查看/dev/input/eventX是什么类型的事件root@NanoPi2:~# cat /proc/bus/input/devices I: Bus=0003 Vendor=062a Product=4182 Version=0110 N: Name="MOSART Semi. 2.4G Keyboard Mouse" P: Phys=usb-nxp-ehci-...
  • Linux下如何模拟按键输入和模拟鼠标  查看/dev/input/eventX是什么类型的事件, cat /proc/bus/input/devices  设备有着自己特殊的按键键码,我需要将一些标准的按键,比如0-9,X-Z等模拟成标准...
  •  在linux中,常用的用户层和内核层通信方法有:系统调用(如copy_to_user/copy_from_user)、proc、ioctl和netlink。热插拔模式就是linux基于nelink实现的。netlink的讲解,可以看教程:...
  • 首先模拟鼠标键盘按下释放的动作,本人利用X11 这个库,所以要了解X11编程;其次,本身用c或者c++就可以实现了,但是由于本人是py 粉,所以总想把代码搬进python,所以本人就要实现python模块,本篇用的ctypes,...
  • 我们经常用linux中的system函数来执行命令, 下面, 我们简要模拟一下system函数的行为, 以便对system函数有更深入的理解, 代码如下: #include #include #include int mySystem(const char *cmdstring) { ...
1 2 3 4 5 ... 20
收藏数 49,650
精华内容 19,860
热门标签
关键字:

80模拟 int linux