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

电商网站开发团队北京千锋教育

电商网站开发团队,北京千锋教育,网站模板兼容手机,网站结构构图frameworks 之getEvent指令 指令解析源码追溯源码解析1.解析参数2.初始化ufds数组3.添加到poll 并做对应处理 通过 getEvent 可以识别按键基本命令和里面的关键信息 涉及到的类如下 system/core/toolbox/toolbox.csystem/core/toolbox/tools.hsystem/core/toolbox/getevent.c … frameworks 之getEvent指令 指令解析源码追溯源码解析1.解析参数2.初始化ufds数组3.添加到poll 并做对应处理 通过 getEvent 可以识别按键基本命令和里面的关键信息 涉及到的类如下 system/core/toolbox/toolbox.csystem/core/toolbox/tools.hsystem/core/toolbox/getevent.c 指令解析 通过 getEvent -h 可打印出相关的指令帮助对应的指令注释如下。输出的数字都为16进制。 houji:/ $ getevent -help Usage: getevent [-t] [-n] [-s switchmask] [-S] [-v [mask]] [-d] [-p] [-i] [-l] [-q] [-c count] [-r] [device]-t: show time stamps // 打印时间戳-n: dont print newlines // 不换行-s: print switch states for given bits // 打印指定位的开关状态-S: print all switch states // 打印所有开关状态-v: verbosity mask (errs1, dev2, name4, info8, vers16, pos. events32, props64) // 根据 mask 值显示相关信息执行后会一直显示上报数据详细掩码错误1dev2名称4信息8错误16位置事件32道具64默认显示 dev| name| info| vers 30-d: show HID descriptor, if available // 如果设备可用显示设备隐藏的描述信息-p: show possible events (errs, dev, name, pos. events) // 显示设备支持的事件类型和编码方式-i: show all device info and possible events // 显示设备的所有信息和支持的事件比 -p 显示更多信息-l: label event types and names in plain text // 以文本形式输出事件类型和名称比 -t 更清楚直观-q: quiet (clear verbosity mask) // 以文本形式输出事件类型和名称比 -t 更清楚直观-c: print given number of events then exit // 打印固定数量的事件并退出-r: print rate events are received // 显示事件上报速率其中 -v 打印输入设备的详细信息默认为 默认显示 dev| name| info| vers 30。 emulator_x86_64:/ # getevent -v add device 1: /dev/input/event0bus: 0019vendor 0000product 0001version 0000name: Power Buttonlocation: LNXPWRBN/button/input0id: version: 1.0.1-l 打印的信息 分别对应 type code value。 emulator_x86_64:/ # getevent -l /dev/input/event3: EV_ABS ABS_MT_TRACKING_ID 00000000 /dev/input/event3: EV_ABS ABS_MT_POSITION_X 000031af /dev/input/event3: EV_ABS ABS_MT_POSITION_Y 00004447 参数可以组合使用一次性查看需要的触摸屏信息常用的命令组合为 getevent -ltr emulator_x86_64:/ # getevent -ltr [ 1384.965200] /dev/input/event3: EV_ABS ABS_MT_TRACKING_ID 00000000 源码追溯 可以执行 则表示 system/bin 有对应的脚本。所以可以通过执行对应的打印 查看文件。通过命令 ls -l | grep event 过滤对应的关键字可以看到 该事件通过 软链接前面开头为l开头即为软链接。链接到 toolbox。 emulator_x86_64:/system/bin # ls -l | grep event lrwxr-xr-x 1 root shell 7 2024-08-17 22:51 getevent - toolbox -rwxr-xr-x 1 root shell 3925 2024-03-18 00:26 mm_events lrwxr-xr-x 1 root shell 6 2024-08-17 22:51 sendevent - toybox lrwxr-xr-x 1 root shell 4 2024-08-17 22:51 ueventd - init 回到源码文件一般工具类 在 system 目录下可以先通过该目录查找。执行 find -name toolbox。可以看到在该**./core/toolbox** 文件夹下。 跳转到该文件夹下查看对应的文件打印查看对应的Bp文件。包含以下文件可以看出入口为 toolbox.c 文件夹。 cc_defaults {...srcs: [toolbox.c,getevent.c,getprop.cpp,modprobe.cpp,setprop.cpp,start.cpp,],... }对应的 main 入口如下该方法通过读取参数遍历数组 然后判断名称和命令是否相等相等就执行对应的 func 方法。对应 tools[] 数组 在文件前面定义定义了名词和执行的方法。 会根据 name 拼接对应的执行方法。如 getEvent 拼接完为 getevent_main。相关数组定义在 tools.h 头文件里面。 // system/core/toolbox/tools.c #define TOOL(name) int name##_main(int, char**); // 拼接对应的执行方法名称 #include tools.h #undef TOOL // 定义对应的数组数组内容来自 tools.h定义 static struct {const char* name;int (*func)(int, char**); } tools[] { #define TOOL(name) { #name, name##_main }, #include tools.h #undef TOOL{ 0, 0 }, };int main(int argc, char** argv) {// Lets assume that none of this code handles broken pipes. At least ls,// ps, and top were broken (though Id previously added this fix locally// to top). We exit rather than use SIG_IGN because tools like top will// just keep on writing to nowhere forever if we dont stop them.signal(SIGPIPE, SIGPIPE_handler);// 获取第一个参数遍历数组判断是否和名称相等相等执行对应的方法。char* cmd strrchr(argv[0], /);char* name cmd ? (cmd 1) : argv[0];for (size_t i 0; tools[i].name; i) {if (!strcmp(tools[i].name, name)) {return tools[i].func(argc, argv);}}printf(%s: no such tool\n, argv[0]);return 127; }头文件定义 // system/core/toolbox/tools.h TOOL(getevent) TOOL(getprop) TOOL(modprobe) TOOL(setprop) TOOL(start) TOOL(stop) TOOL(toolbox)所以运行脚本 执行的方法 在 getevent.c 下的 getevent_main方法下。 源码解析 1.解析参数 查看对应的方法 main 方法可以看到 第一步 通过 getopt 解析对应的参数 部分参数通过 或 记录到 print_flags 中。 opterr 0;do {c getopt(argc, argv, tns:Sv::dpilqc:rh); // 解析对应的参数if (c EOF)break;switch (c) {case t:get_time 1;break;case n:newline ;break;case s:get_switch strtoul(optarg, NULL, 0);if(dont_block -1)dont_block 1;break;case S:get_switch ~0;if(dont_block -1)dont_block 1;break;case v:if(optarg)print_flags | strtoul(optarg, NULL, 0);elseprint_flags | PRINT_DEVICE | PRINT_DEVICE_NAME | PRINT_DEVICE_INFO | PRINT_VERSION;print_flags_set 1;break;case d:print_flags | PRINT_HID_DESCRIPTOR;break;case p:print_flags | PRINT_DEVICE_ERRORS | PRINT_DEVICE| PRINT_DEVICE_NAME | PRINT_POSSIBLE_EVENTS | PRINT_INPUT_PROPS;print_flags_set 1;if(dont_block -1)dont_block 1;break;case i:print_flags | PRINT_ALL_INFO;print_flags_set 1;if(dont_block -1)dont_block 1;break;case l:print_flags | PRINT_LABELS;break;case q:print_flags_set 1;break;case c:event_count atoi(optarg); //解析对应参数值dont_block 0;break;case r:sync_rate 1;break;case ?:fprintf(stderr, %s: invalid option -%c\n,argv[0], optopt);case h:usage(argv[0]); // 打印帮助exit(1);}} while (1);if(dont_block -1)dont_block 0;if (optind 1 argc) {device argv[optind];optind;}if (optind ! argc) {usage(argv[0]);exit(1);}2.初始化ufds数组 第二步会通过 device 判断是否 观察单个或者全部 。如如果我们 执行的命令后面加了对应的设备则只会观察对应的设备 如 getevent -ltr /dev/input/event1。其中 inotify_init 获取了 dev/input 文件夹对应的监听。 然后通过 inotify_add_watch。进行删除和添加的监听。 nfds 1;ufds calloc(1, sizeof(ufds[0]));ufds[0].fd inotify_init();ufds[0].events POLLIN;// 打印单个设备对应信息if(device) {if(!print_flags_set)print_flags | PRINT_DEVICE_ERRORS;// 通过 open 方法打开对应的驱动并通过 ioctl 获取对应的信息,并放到对应的 ufds 数组res open_device(device, print_flags);if(res 0) {return 1;}} else { // 打印全部if(!print_flags_set)print_flags | PRINT_DEVICE_ERRORS | PRINT_DEVICE | PRINT_DEVICE_NAME;print_device 1;// 添加删除和添加对应文件夹的监听res inotify_add_watch(ufds[0].fd, device_path, IN_DELETE | IN_CREATE);if(res 0) {fprintf(stderr, could not add watch for %s, %s\n, device_path, strerror(errno));return 1;}// 遍历该文件夹 dev/input 文件夹下所有的res scan_dir(device_path, print_flags);if(res 0) {fprintf(stderr, scan dir failed for %s\n, device_path);return 1;}}没指定对应的设备的会 将所有添加到数组中通过 scan_dir 方法。遍历文件夹下。先通过 opendir打开文件夹然后 通过 readdir进行遍历。遍历到符合的 在通过 open_device 将fd 添加到 数组中。 static int scan_dir(const char *dirname, int print_flags) {char devname[PATH_MAX];char *filename;DIR *dir;struct dirent *de;// // 打开对应的文件夹dir opendir(dirname);if(dir NULL)return -1;strcpy(devname, dirname);filename devname strlen(devname);*filename /;while((de readdir(dir))) {if(de-d_name[0] . (de-d_name[1] \0 ||(de-d_name[1] . de-d_name[2] \0)))continue;strcpy(filename, de-d_name);// 将fd 添加到 数组open_device(devname, print_flags);}closedir(dir);return 0; }最终都是通过 open_device 添加到数组查看对应的方法可以看到该方法通过 open 打开对应的节点在通过 ioctl 获取对应的信息并根据 设置的 print_flags 按需打印对应信息。最终在存放到 ufds 数组中。 static int open_device(const char *device, int print_flags) {int version;int fd;int clkid CLOCK_MONOTONIC;struct pollfd *new_ufds;char **new_device_names;char name[80];char location[80];char idstr[80];struct input_id id;// 打开这个节点fd open(device, O_RDONLY | O_CLOEXEC);if(fd 0) {if(print_flags PRINT_DEVICE_ERRORS)fprintf(stderr, could not open %s, %s\n, device, strerror(errno));return -1;}// 获取相关的信息if(ioctl(fd, EVIOCGVERSION, version)) {if(print_flags PRINT_DEVICE_ERRORS)fprintf(stderr, could not get driver version for %s, %s\n, device, strerror(errno));return -1;}if(ioctl(fd, EVIOCGID, id)) {if(print_flags PRINT_DEVICE_ERRORS)fprintf(stderr, could not get driver id for %s, %s\n, device, strerror(errno));return -1;}name[sizeof(name) - 1] \0;location[sizeof(location) - 1] \0;idstr[sizeof(idstr) - 1] \0;if(ioctl(fd, EVIOCGNAME(sizeof(name) - 1), name) 1) {//fprintf(stderr, could not get device name for %s, %s\n, device, strerror(errno));name[0] \0;}if(ioctl(fd, EVIOCGPHYS(sizeof(location) - 1), location) 1) {//fprintf(stderr, could not get location for %s, %s\n, device, strerror(errno));location[0] \0;}if(ioctl(fd, EVIOCGUNIQ(sizeof(idstr) - 1), idstr) 1) {//fprintf(stderr, could not get idstring for %s, %s\n, device, strerror(errno));idstr[0] \0;}if (ioctl(fd, EVIOCSCLOCKID, clkid) ! 0) {fprintf(stderr, Cant enable monotonic clock reporting: %s\n, strerror(errno));// a non-fatal error}new_ufds realloc(ufds, sizeof(ufds[0]) * (nfds 1));if(new_ufds NULL) {fprintf(stderr, out of memory\n);return -1;}ufds new_ufds;new_device_names realloc(device_names, sizeof(device_names[0]) * (nfds 1));if(new_device_names NULL) {fprintf(stderr, out of memory\n);return -1;}device_names new_device_names;if(print_flags PRINT_DEVICE)printf(add device %d: %s\n, nfds, device);if(print_flags PRINT_DEVICE_INFO)printf( bus: %04x\n vendor %04x\n product %04x\n version %04x\n,id.bustype, id.vendor, id.product, id.version);if(print_flags PRINT_DEVICE_NAME)printf( name: \%s\\n, name);if(print_flags PRINT_DEVICE_INFO)printf( location: \%s\\n id: \%s\\n, location, idstr);if(print_flags PRINT_VERSION)printf( version: %d.%d.%d\n,version 16, (version 8) 0xff, version 0xff);if(print_flags PRINT_POSSIBLE_EVENTS) {print_possible_events(fd, print_flags);}if(print_flags PRINT_INPUT_PROPS) {print_input_props(fd);}if(print_flags PRINT_HID_DESCRIPTOR) {print_hid_descriptor(id.bustype, id.vendor, id.product);}// 将 fd 存放到ufds 数组中 ufds[nfds].fd fd;ufds[nfds].events POLLIN;// 放到 device_names 数组中device_names[nfds] strdup(device);nfds;return 0; }3.添加到poll 并做对应处理 添加完数组后通过 poll 等待消息的监听。poll 和 epoll 是一样的。但是 epoll 更加高效。因为 epoll 是监听到消息 塞到 events 数组并返回 数量。后续遍历变化的即可。但是 poll 是无论如何都要遍历全部数组 找到对应的变化没 epoll 高效。 当有新消息来后则做对应的处理。数组第一个为文件夹 所以对文件夹做单独的处理。 通过 read_notify 方法。添加对应添加和删除添加则调用 open_device删除则调用 close_device 移除对应的监听。 因为第0个已处理所以下面的遍历从下标1开始。遍历到变化时候 通过 read 读取对应信息到 变量 event 中input_event最后根据设置的 falg 打印相对于的信息格式。 while(1) {//int pollres // 通过 poll 等待消息的监听poll(ufds, nfds, -1);//printf(poll %d, returned %d\n, nfds, pollres);// 第1个是文件夹的变化对文件夹内容的监听做单独的处理if(ufds[0].revents POLLIN) {read_notify(device_path, ufds[0].fd, print_flags);}// 因为第0个已处理所以下面的遍历从下标1开始for(i 1; i nfds; i) {if(ufds[i].revents) {// 判断到有变化if(ufds[i].revents POLLIN) {// 读取对应的内容到变量 event中为 input_event 结构体res read(ufds[i].fd, event, sizeof(event));if(res (int)sizeof(event)) {fprintf(stderr, could not get event\n);return 1;}if(get_time) {printf([%8ld.%06ld] , event.time.tv_sec, event.time.tv_usec);}if(print_device)printf(%s: , device_names[i]);// 传进去 值根据 对应的 print_flags 做打印print_event(event.type, event.code, event.value, print_flags);if(sync_rate event.type 0 event.code 0) {int64_t now event.time.tv_sec * 1000000LL event.time.tv_usec;if(last_sync_time)printf( rate %lld, 1000000LL / (now - last_sync_time));last_sync_time now;}printf(%s, newline);if(event_count --event_count 0)return 0;}}}}
http://www.dnsts.com.cn/news/63719.html

相关文章:

  • 建站自学深圳百度快照优化
  • 网站首图怎么做游戏软件开发需要学什么
  • 社区教育网站建设方案外贸家具网站
  • 西部数码网站核验单下载用糖做的网站
  • 网站设置怎么调wordpress企业模板下载
  • 网站开发有什么点子章丘网站建设公司
  • 成都网站建设 lkcms咸阳市城乡建设规划局网站
  • 建一个购物网站多少钱凡科网站官网登录入口
  • 越秀学校网站建设国际本科
  • ui下载高清素材的网站有哪些网站嵌入地图
  • 甘肃找人做网站多少钱网站页面前端基本设计
  • 视频网站开发者工具北京建设网官方网站
  • 网站被很多公司抄袭做新房什么网站好
  • 电子商务网站网络安全设计方案网站网站娱乐建设
  • 建网站维护需要多少钱黄山市住房城乡建设厅网站
  • 郑州网站建设 app开发深圳平台设计
  • 提供邯郸网站建设app网站建设源码
  • 网站数据库如何导入数据库文件网络推广公司哪里好
  • 网站开发工程师优势有没有人通过网站建设卖东西的
  • 山东省建设监理协会网站打不开编程自己做网站
  • 建设银行东四十条支行支行网站竞价推广平台
  • 详谈电商网站建设四大流程原创文章代写
  • 网站建设有利点婚纱网站设计图
  • 网站平台策划书郑州厉害的seo顾问
  • 有源代码如何做网站漂亮的网站建设中静态页
  • 湖南省建设银行网站官网wordpress 浏览缓慢
  • 蓝牙音箱东莞网站建设设计一个网页大概多少钱
  • 公司网站建设服务费怎么做账什么叫网络服务商
  • 工程师招聘网站淄博网站建设 很乱
  • 民治做网站的公司推荐几个安全没封的网站