linux/input.h 中有定义,这个文件还定义了标准
按键的编码等 struct input_event { struct timeval time//按键时间 __u16 type//类型,在下面有定义 __u16 code//要模拟成什么按键 __s32 value//是按下还是释放 }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 的正数值和负数值分别代表两个不同方向的值. /* * Event types */ #define EV_SYN 0x00 #define EV_KEY 0x01 //按键 #define EV_REL 0x02 //相对坐标(轨迹球) #define EV_ABS 0x03 //绝对坐标 #define EV_MSC 0x04 //其他 #define EV_SW 0x05 #define EV_LED 0x11 //LED #define EV_SND 0x12//声音 #define EV_REP 0x14//repeat #define EV_FF 0x15 #define EV_PWR 0x16 #define EV_FF_STATUS 0x17 #define EV_MAX 0x1f #define EV_CNT (EV_MAX+1) 1。模拟按键输入 //其中0 表示释放,1 按键按下,2 表示一直按下 //0 for EV_KEY for release, 1 for keypress and 2 for autorepeat. void simulate_key(int fd,int value) { struct input_event eventevent.type = EV_KEY//event.code = KEY_0//要模拟成什么按键 event.value = value//是按下还是释放按键或者重复 gettimeofday(&event.time,0)if(write(fd,&event,sizeof(event)) <0){ dprintk("simulate key error~~~\n")return } } 2。模拟鼠标输入(轨迹球) void simulate_mouse(int fd,char buf[4]) { int rel_x,rel_ystatic struct input_event event,ev//buf[0],buf[2],小于0 则为左移,大于0 则为右移 //buf[1],buf[3],小于0 则为下移,大于0 则为上移 dprintk("MOUSE TOUCH: x1=%d,y1=%d,x2=%d,y2=%d\n",buf[0],buf[1],buf[2],buf[3])rel_x = (buf[0] + buf[2]) /2rel_y = -(buf[1] + buf[3]) /2//和我们的鼠标是相反的方向,所以取反 event.type = EV_RELevent.code = REL_Xevent.value = rel_xgettimeofday(&event.time,0)if( write(fd,&event,sizeof(event))!=sizeof(event)) dprintk("rel_x error~~~:%s\n",strerror(errno))event.code = REL_Yevent.value = rel_ygettimeofday(&event.time,0)if( write(fd,&event,sizeof(event))!=sizeof(event)) dprintk("rel_y error~~~:%s\n",strerror(errno))//一定要刷新空的 write(fd,&ev,sizeof(ev))} 鼠标和键盘文件打开方法: int fd_kbd// /dev/input/event1 int fd_mouse//dev/input/mouse2 fd_kbd = open("/dev/input/event1",O_RDWR)if(fd_kbdkey.window = window->window//一定要设置为主窗口 event->key.keyval = keyval//FIXME:一定要加上这个,要不然容易出错 g_object_ref(event->key.window)gdk_threads_enter()//FIXME: 记得用这个来发送事件 gtk_main_do_event(event)gdk_threads_leave()gdk_event_free(event)} kernel 里input 模块 input_dev 结构: struct input_dev { void *privateconst char *nameconst char *physconst char *uniqstruct input_id id/* * 根据各种输入
信号的类型来建立类型为unsigned long 的数组, * 数组的每1bit 代表一种信号类型, * 内核中会对其进行置位或清位 *** 作来表示时间的发生和被处理. */ unsigned long evbit[NBITS(EV_MAX)]unsigned long keybit[NBITS(KEY_MAX)]unsigned long relbit[NBITS(REL_MAX)]unsigned long absbit[NBITS(ABS_MAX)]unsigned long mscbit[NBITS(MSC_MAX)]unsigned long ledbit[NBITS(LED_MAX)]unsigned long sndbit[NBITS(SND_MAX)]unsigned long ffbit[NBITS(FF_MAX)]unsigned long swbit[NBITS(SW_MAX)]......................................... }/** * input_set_capability - mark device as capable of a certain event * @dev: device that is capable of emitting or accepting event * @type: type of the event (EV_KEY, EV_REL, etc...) * @code: event code * * In addition to setting up corresponding bit in appropriate capability * bitmap the function also adjusts dev->evbit. */ /* 记录本设备对于哪些事件感兴趣(对其进行处理)*/ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code) { switch (type) { case EV_KEY: __set_bit(code, dev->keybit)//比如按键,应该对哪些键值的按键进行处理(对于其它按键不予理睬) breakcase EV_REL: __set_bit(code, dev->relbit)breakcase EV_ABS: __set_bit(code, dev->absbit)breakcase EV_MSC: __set_bit(code, dev->mscbit)breakcase EV_SW: __set_bit(code, dev->swbit)breakcase EV_LED: __set_bit(code, dev->ledbit)breakcase EV_SND: __set_bit(code, dev->sndbit)breakcase EV_FF: __set_bit(code, dev->ffbit)breakdefault: printk(KERN_ERR "input_set_capability: unknown type %u (code %u)\n", type, code)dump_stack()return} __set_bit(type, dev->evbit)//感觉和前面重复了(前面一经配置过一次了) } EXPORT_SYMBOL(input_set_capability)static irqreturn_t gpio_keys_isr(int irq, void *dev_id) { int istruct platform_device *pdev = dev_idstruct gpio_keys_platform_data *pdata = pdev->dev.platform_datastruct input_dev *input = platform_get_drvdata(pdev)for (i = 0i <pdata->nbuttonsi++) { struct gpio_keys_button *button = &pdata->buttons[i]int gpio = button->gpioif (irq == gpio_to_irq(gpio)) {//判断哪个键被按了? unsigned int type = button->type ?: EV_KEYint state = (gpio_get_value(gpio) ? 1 : 0) ^ button->active_low//记录按键状态 input_event(input, type, button->code, !!state)//汇报输入事件 input_sync(input)//等待输入事件处理完成 } } return IRQ_HANDLED} /* * input_event() - report new input event * @dev: device that generated the event * @type: type of the event * @code: event code * @value: value of the event * * This function should be used by drivers implementing various input devices * See also input_inject_event() */ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { struct input_handle *handleif (type >EV_MAX || !test_bit(type, dev->evbit))//首先判断该事件类型是否有效且为该设备所接受 returnadd_input_randomness(type, code, value)switch (type) { case EV_SYN: switch (code) { case SYN_CONFIG: if (dev->event) dev->event(dev, type, code, value)breakcase SYN_REPORT: if (dev->sync) returndev->sync = 1break} breakcase EV_KEY: /* * 这里需要满足几个条件: * 1: 键值有效(不超出定义的键值的有效范围) * 2: 键值为设备所能接受(属于该设备所拥有的键值范围) * 3: 按键状态改变了 */ if (code >KEY_MAX || !test_bit(code, dev->keybit) || !!test_bit(code, dev->key) == value) returnif (value == 2) breakchange_bit(code, dev->key)//改变对应按键的状态 /* 如果你希望按键未释放的时候不断汇报按键事件的话需要以下这个(在简单的gpio_keys 驱动中不需要这个,暂时不去分析) */ if (test_bit(EV_REP, dev->evbit) &&dev->rep[REP_PERIOD] &&dev->rep[REP_DELAY] &&dev->timer.data &&value) { dev->repeat_key = codemod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]))} break........................................................ if (type != EV_SYN) dev->sync = 0if (dev->grab) dev->grab->handler->event(dev->grab, type, code, value)else /* * 循环调用所有处理该设备的handle(event,mouse,ts,joy 等), * 如果有进程打开了这些handle(进行读写),则调用其对应的event 接口向气汇报该输入事件. */ list_for_each_entry(handle, &dev->h_list, d_node) if (handle->open) handle->handler->event(handle, type, code, value)} EXPORT_SYMBOL(input_event)event 层对于input 层报告的这个键盘输入事件的处理: drivers/input/evdev.c: static struct input_handler evdev_handler = { .event = evdev_event, .connect = evdev_connect, .disconnect = evdev_disconnect, .fops = &evdev_fops, .minor = EVDEV_MINOR_BASE, .name = "evdev", .id_table = evdev_ids, }Linux 有自己的 input 子系统,可以统一管理鼠标和键盘事件。 基于输入子系统 实现的 uinput 可以方便的在用户空间模拟鼠标和键盘事件。 当然,也可以自己造轮子, 做一个字符设备接收用户输入,根据输入,投递 input 事件。 还有一种方式就是直接 往 evnent 里写入数据, 都可以达到控制鼠标键盘的功能。 本篇文章就是演示直接写入 event 的方法。 linux/input.h 中有定义,这个文件还定义了标准按键的编码等 struct input_event { struct timeval time//按键时间 __u16 type//类型,在下面有定义 __u16 code//要模拟成什么按键 __s32 value//是按下还是释放 }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 的正数值和负数值分别代表两个不同方向的值. /* * Event types */ #define EV_SYN 0x00 #define EV_KEY 0x01 //按键 #define EV_REL 0x02 //相对坐标(轨迹球) #define EV_ABS 0x03 //绝对坐标 #define EV_MSC 0x04 //其他 #define EV_SW 0x05 #define EV_LED 0x11 //LED #define EV_SND 0x12//声音 #define EV_REP 0x14//repeat #define EV_FF 0x15 #define EV_PWR 0x16 #define EV_FF_STATUS 0x17 #define EV_MAX 0x1f #define EV_CNT (EV_MAX+1) 下面是一个模拟鼠标和键盘输入的例子: #include #include #include #include #include #include #include #include #include #include #include void simulate_key(int fd,int kval) { struct input_event eventevent.type = EV_KEYevent.value = 1event.code = kvalgettimeofday(&event.time,0)write(fd,&event,sizeof(event)) event.type = EV_SYNevent.code = SYN_REPORTevent.value = 0write(fd, &event, sizeof(event))memset(&event, 0, sizeof(event))gettimeofday(&event.time, NULL)event.type = EV_KEYevent.code = kvalevent.value = 0write(fd, &event, sizeof(event))event.type = EV_SYNevent.code = SYN_REPORTevent.value = 0write(fd, &event, sizeof(event))} void simulate_mouse(int fd) { struct input_event eventmemset(&event, 0, sizeof(event))gettimeofday(&event.time, NULL)event.type = EV_RELevent.code = REL_Xevent.value = 10write(fd, &event, sizeof(event))event.type = EV_RELevent.code = REL_Yevent.value = 10write(fd, &event, sizeof(event))event.type = EV_SYNevent.code = SYN_REPORTevent.value = 0write(fd, &event, sizeof(event))} int main() { int fd_kbdint fd_mousefd_kbd = open("/dev/input/event1",O_RDWR)if(fd_kbd
ubuntu下,也就是linux下,通常会用kill -事件编号实现。 你查一下LINUX下的事件就明白了。
kill 进程号 实现上是发了一个信号给指定的进程。 在python里,也可以加载事件处理模块,处理来自其它程序发过来的信号, 当然你可以用KILL工具发信号过来。
ctrl+d也是一个信号,ctrl+c也是一个。具体信号编码我不记得了。不过以前我做多进程管理时就是使用这个方法。 好象信号还可以带参数过来。
你打开python的帮助。看看signal这个模块。我把它的例子拿过来。对你有用不
import signal, os
def handler(signum, frame):
print 'Signal handler called with signal', signum
raise IOError("Couldn't open device!")
# Set the signal handler and a 5-second alarm
signal.signal(signal.SIGALRM, handler)
signal.alarm(5)
# This open() may hang indefinitely
fd = os.open('/dev/ttyS0', os.O_RDWR)
signal.alarm(0) # Disable the alarm
下面是我找到的一些资料。也许有用。
信号的概念
信号(signal)-- 进程之间通讯的方式,是一种软件中断。一个进程一旦接收到信号就会打断原来的程序执行流程来处理信号。
几个常用信号:
SIGINT 终止进程 中断进程 (control+c)
SIGTERM 终止进程 软件终止信号
SIGKILL 终止进程 杀死进程
SIGALRM 闹钟信号
进程结束信号 SIGTERM和SIGKILL的区别
SIGTERM比较友好,进程能捕捉这个信号,根据您的需要来关闭程序。在关闭程序之前,您可以结束打开的记录文件和完成正在做的任务。在某些情况下,假如进程正在进行作业而且不能中断,那么进程可以忽略这个SIGTERM信号。
对于SIGKILL信号,进程是不能忽略的。这是一个 “我不管您在做什么,立刻停止”的信号。假如您发送SIGKILL信号给进程,Linux就将进程停止在那里。
发送信号一般有两种原因:
1(被动式) 内核检测到一个系统事件.例如子进程退出会像父进程发送SIGCHLD信号.键盘按下control+c会发送SIGINT信号
2(主动式) 通过系统调用kill来向指定进程发送信号
linux *** 作系统提供的信号
[100003@oss235 myppt]$ kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL
5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE
9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2
13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT
17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU
25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH
29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN
35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4
39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12
47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14
51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10
55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6
59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
Python提供的信号
Python 2.4.3 (#1, Jun 11 2009, 14:09:58)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-44)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>import signal
>>>dir(signal)
['NSIG', 'SIGABRT', 'SIGALRM', 'SIGBUS', 'SIGCHLD', 'SIGCLD',
'SIGCONT', 'SIGFPE', 'SIGHUP', 'SIGILL', 'SIGINT', 'SIGIO', 'SIGIOT',
'SIGKILL', 'SIGPIPE', 'SIGPOLL', 'SIGPROF', 'SIGPWR', 'SIGQUIT',
'SIGRTMAX', 'SIGRTMIN', 'SIGSEGV', 'SIGSTOP', 'SIGSYS', 'SIGTERM',
'SIGTRAP', 'SIGTSTP', 'SIGTTIN', 'SIGTTOU', 'SIGURG', 'SIGUSR1',
'SIGUSR2', 'SIGVTALRM', 'SIGWINCH', 'SIGXCPU', 'SIGXFSZ', 'SIG_DFL',
'SIG_IGN', '__doc__', '__name__', 'alarm', 'default_int_handler',
'getsignal', 'pause', 'signal']
*** 作系统规定了进程收到信号以后的默认行为
但是,我们可以通过绑定信号处理函数来修改进程收到信号以后的行为
有两个信号是不可更改的SIGTOP和SIGKILL
绑定信号处理函数
import os
import signal
from time import sleep
def onsignal_term(a,b):
print '收到SIGTERM信号'
#这里是绑定信号处理函数,将SIGTERM绑定在函数onsignal_term上面
signal.signal(signal.SIGTERM,onsignal_term)
def onsignal_usr1(a,b):
print '收到SIGUSR1信号'
#这里是绑定信号处理函数,将SIGUSR1绑定在函数onsignal_term上面
signal.signal(signal.SIGUSR1,onsignal_usr1)
while 1:
print '我的进程id是',os.getpid()
sleep(10)
运行该程序。然后通过另外一个进程来发送信号。
发送信号
发送信号的代码如下:
import os
import signal
#发送信号,16175是前面那个绑定信号处理函数的pid,需要自行修改
os.kill(16175,signal.SIGTERM)
#发送信号,16175是前面那个绑定信号处理函数的pid,需要自行修改
os.kill(16175,signal.SIGUSR1)
用 yes 命令
如 yes 123 可以不停的输出 123,你可以用 yes 123 | head -3 输出三次。
然后你要是要对某个程序做输入,你用输入重定向。
如果你说的是应答,那就用 expect,具体的用法就复杂了,自己搜教程系统地学习吧。
评论列表(0条)