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

做网站推广有啥活动南京模板网站建设企业

做网站推广有啥活动,南京模板网站建设企业,专业营销型网站建设费用,企业微网站与手机微信号一、异步通知 1. 异步通知简介 阻塞和非阻塞两种方式都是需要应用程序去主动查询设备的使用情况。 异步通知类似于驱动可以主动报告自己可以访问#xff0c;应用程序获取信号后会从驱动设备中读取或写入数据。 异步通知最核心的就是信号#xff1a; #define SIGHUP 1 /* 终…一、异步通知 1. 异步通知简介 阻塞和非阻塞两种方式都是需要应用程序去主动查询设备的使用情况。 异步通知类似于驱动可以主动报告自己可以访问应用程序获取信号后会从驱动设备中读取或写入数据。 异步通知最核心的就是信号 #define SIGHUP 1 /* 终端挂起或控制进程终止 */ #define SIGINT 2 /* 终端中断(CtrlC 组合键) */ #define SIGQUIT 3 /* 终端退出(Ctrl\组合键) */ #define SIGILL 4 /* 非法指令 */ #define SIGTRAP 5 /* debug 使用有断点指令产生 */ #define SIGABRT 6 /* 由 abort(3)发出的退出指令 */ #define SIGIOT 6 /* IOT 指令 */ #define SIGBUS 7 /* 总线错误 */ #define SIGFPE 8 /* 浮点运算错误 */ #define SIGKILL 9 /* 杀死、终止进程 */ #define SIGUSR1 10 /* 用户自定义信号 1 */ #define SIGSEGV 11 /* 段违例(无效的内存段) */ #define SIGUSR2 12 /* 用户自定义信号 2 */ #define SIGPIPE 13 /* 向非读管道写入数据 */ #define SIGALRM 14 /* 闹钟 */ #define SIGTERM 15 /* 软件终止 */ #define SIGSTKFLT 16 /* 栈异常 */ #define SIGCHLD 17 /* 子进程结束 */ #define SIGCONT 18 /* 进程继续 */ #define SIGSTOP 19 /* 停止进程的执行只是暂停 */ #define SIGTSTP 20 /* 停止进程的运行(CtrlZ 组合键) */ #define SIGTTIN 21 /* 后台进程需要从终端读取数据 */ #define SIGTTOU 22 /* 后台进程需要向终端写数据 */ #define SIGURG 23 /* 有紧急数据 */ #define SIGXCPU 24 /* 超过 CPU 资源限制 */ #define SIGXFSZ 25 /* 文件大小超额 */ #define SIGVTALRM 26 /* 虚拟时钟信号 */ #define SIGPROF 27 /* 时钟信号描述 */ #define SIGWINCH 28 /* 窗口大小改变 */ #define SIGIO 29 /* 可以进行输入/输出操作 */ #define SIGPOLL SIGIO #define SIGPWR 30 /* 断点重启 */ #define SIGSYS 31 /* 非法的系统调用 */ #define SIGUNUSED 31 /* 未使用信号 */ 其中 9 和 19 是不能被忽略的这些信号相当于中断号不同的中断号代表不同的中断不同的中断又可以实现不同的功能。 使用中断的时候需要设置中断处理函数那么应用程序中使用了信号也要有信号处理函数在应用程序中使用 signal 函数来设置信号的处理函数 /** description : 设置指定信号的处理函数* param - signum : 要设置处理函数的信号* param - handler : 信号的处理函数* return : 设置成功的话返回信号的前一个处理函数设置失败的话返回 SIG_ERR*/ sighandler_t signal(int signum, sighandler_t handler); 这里的信号处理原型为 typedef void (*sighandler_t)(int) 之前使用的 kill -9 PID就是指定进程发送  SIGKILL 这个信号。当我们按下 CTRL C 的时候会向当前正在占用终端的应用程序发送 SIGINT2信号最终中断终端。 在 linux/atk-mpl 文件夹下创建 signaltest.c并输入以下代码 #include stdlib.h #include stdio.h #include signal.h/* 信号处理函数 */ void signalint_handler(int num) {printf(\r\nSIGINT signal!\r\n);exit(0); }int main(void) {signal(SIGINT, signalint_handler);while(1);return 0; }/* 总体流程首先自己设置信号处理函数之后应用程序开启按下CTRLC向signaltest发送SIGINT信号以后signalint_handler函数就会执行此函数会先输出SIGINT signal!后exit函数会关闭signaltest的应用程序。*/ 输入命令编译 signaltest.c gcc signaltest.c -o signaltest 输入命令执行应用程序 signaltest ./signaltest 按下 CTRL C后可以看到 2. 驱动中的信号处理 ① fasync_struct 结构体 如果在驱动中使用信号首先先定义一个fasync_struct结构体变量一般将这个结构体放在 xxx_dev 结构体中例如 /* key设备结构体 */ struct key_dev{dev_t devid; /* 设备号 */struct cdev cdev; /* cdev */struct class *class; /* 类 */struct device *device; /* 设备 */struct device_node *nd; /* 设备节点 */int key_gpio; /* key所使用的GPIO编号 */struct timer_list timer; /* 按键值 */int irq_num; /* 中断号 */atomic_t status; /* 按键状态 */wait_queue_head_t r_wait; /* 读等待队列头 */struct fasync_struct *async_queue; /* fasync_struct结构体 */ }; ② fasync 函数 函数负责将用户空间应用程序的进程 ID 添加到驱动程序相应文件的异步通知队列中。 如果要使用异步通知需要在驱动程序里实现 file_operation 操作集中的 fasync函数 int (*fasync) (int fd, struct file *filp, int on) 驱动中的 fasync 函数示例如下 struct xxx_dev {......struct fasync_struct *async_queue; /* 异步相关结构体 */ };static int xxx_fasync(int fd, struct file *filp, int on) // fasync 函数 {struct xxx_dev *dev (xxx_dev)filp-private_data; // 私有数据if (fasync_helper(fd, filp, on, dev-async_queue) 0) // 这里的fasync_helper其实是被fasync调用的return -EIO;return 0; }static struct file_operations xxx_ops {.......fasync xxx_fasync, // 只要是 file_operations里的函数都要这样的形势走一遍...... }; 如果需要关闭驱动文件那么需要在 release 函数里面释放 fasync_struct示例如下 static int xxx_release(struct inode *inode, struct file *filp) {return xxx_fasync(-1, filp, 0); /* 删除异步通知 */ } static struct file_operations xxx_ops {.......release xxx_release, // 只要用到了file_operations就要这样 }; ③ kill_fasync 函数 /** description : 当设备可以访问的时候驱动程序需要向应用程序发出信号此函数负责发送指定的信号* param - fp : 要操作的 fasync_struct* param - sig : 要发送的信号* param - band : 可读时设置为 POLL_IN可写时设置为 POLL_OUT* return : 无*/ void kill_fasync(struct fasync_struct **fp, int sig, int band); 3. 应用程序对异步通知的处理 总共包含三步 ① 注册信号处理函数 这里的处理函数需要自己设置并且最后传给 signal 函数。 ② 将本应用程序的进程号告诉内核 使用 fcntl(fd, F_SETOWN, getpid())将本应用程序的进程号告诉给内核。  ③ 开启异步通知 flags fcntl(fd, F_GETFL); /* 获取当前的进程状态 */ fcntl(fd, F_SETFL, flags | FASYNC); /* 开启当前进程异步通知功能 */ 重点就是通过 fcntl 函数设置进程状态为 FASYNC经过这一步驱动程序中的 fasync 函数就会执行。  当用户空间应用程序调用 fcntl 系统调用并设置 F_SETFL 命令以及 FASYNC 标志时内核会调用驱动程序中的 fasync 函数。 二、程序编写 在 /linux/atk-mpl/Drivers 文件夹下创建 16_asynchronization 文件夹并创建 asynchronization.c 文件并输入以下代码 #include linux/types.h #include linux/kernel.h #include linux/delay.h #include linux/ide.h #include linux/init.h #include linux/module.h #include linux/errno.h #include linux/gpio.h #include linux/cdev.h #include linux/device.h #include linux/of.h #include linux/of_address.h #include linux/of_gpio.h #include linux/semaphore.h #include linux/of_irq.h #include linux/irq.h #include linux/wait.h #include linux/poll.h #include asm/mach/map.h #include asm/uaccess.h #include asm/io.h #include linux/fcntl.h#define KEY_CNT 1 /* 设备号个数 */ #define KEY_NAME key /* 名字 *//* 定义按键状态 */ enum key_status {KEY_PRESS 0, // 按键按下KEY_RELEASE, // 按键松开KEY_KEEP, // 按键状态保持 };/* key设备结构体 */ struct key_dev{dev_t devid; /* 设备号 */struct cdev cdev; /* cdev */struct class *class; /* 类 */struct device *device; /* 设备 */struct device_node *nd; /* 设备节点 */int key_gpio; /* key所使用的GPIO编号 */struct timer_list timer; /* 按键值 */int irq_num; /* 中断号 */ atomic_t status; /* 按键状态 */wait_queue_head_t r_wait; /* 读等待队列头 */struct fasync_struct *async_queue; /* fasync_struct结构体 */ };static struct key_dev key; /* 按键设备 */static irqreturn_t key_interrupt(int irq, void *dev_id) // 中断处理函数 {/* 按键防抖处理开启定时器延时15ms */mod_timer(key.timer, jiffies msecs_to_jiffies(15));return IRQ_HANDLED; }/** description : 初始化按键IOopen函数打开驱动的时候* 初始化按键所使用的GPIO引脚。* param : 无* return : 无*/ static int key_parse_dt(void) {int ret;const char *str;/* 设置LED所使用的GPIO *//* 1、获取设备节点key */key.nd of_find_node_by_path(/key);if(key.nd NULL) {printk(key node not find!\r\n);return -EINVAL;}/* 2.读取status属性 */ret of_property_read_string(key.nd, status, str);if(ret 0) return -EINVAL;if (strcmp(str, okay))return -EINVAL;/* 3、获取compatible属性值并进行匹配 */ret of_property_read_string(key.nd, compatible, str);if(ret 0) {printk(key: Failed to get compatible property\n);return -EINVAL;}if (strcmp(str, alientek,key)) {printk(key: Compatible match failed\n);return -EINVAL;}/* 4、 获取设备树中的gpio属性得到KEY0所使用的KYE编号 */key.key_gpio of_get_named_gpio(key.nd, key-gpio, 0);if(key.key_gpio 0) {printk(cant get key-gpio);return -EINVAL;}/* 5 、获取GPIO对应的中断号 */key.irq_num irq_of_parse_and_map(key.nd, 0);if(!key.irq_num){return -EINVAL;}printk(key-gpio num %d\r\n, key.key_gpio);return 0; }static int key_gpio_init(void) // gpio初始化 {int ret;unsigned long irq_flags;ret gpio_request(key.key_gpio, KEY0); // 申请gpioif (ret) {printk(KERN_ERR key: Failed to request key-gpio\n);return ret;} /* 将GPIO设置为输入模式 */gpio_direction_input(key.key_gpio);/* 获取设备树中指定的中断触发类型 */irq_flags irq_get_trigger_type(key.irq_num);if (IRQF_TRIGGER_NONE irq_flags)irq_flags IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING;/* 申请中断 */ret request_irq(key.irq_num, key_interrupt, irq_flags, Key0_IRQ, NULL);if (ret) {gpio_free(key.key_gpio);return ret;}return 0; }static void key_timer_function(struct timer_list *arg) // 定时器处理函数 {static int last_val 1;int current_val;/* 读取按键值并判断按键当前状态 */current_val gpio_get_value(key.key_gpio);if (0 current_val last_val){atomic_set(key.status, KEY_PRESS); // 按下wake_up_interruptible(key.r_wait); // 唤醒r_wait队列头中的所有队列if(key.async_queue)kill_fasync(key.async_queue, SIGIO, POLL_IN); // }else if (1 current_val !last_val) {atomic_set(key.status, KEY_RELEASE); // 松开wake_up_interruptible(key.r_wait); // 唤醒r_wait队列头中的所有队列if(key.async_queue)kill_fasync(key.async_queue, SIGIO, POLL_IN);}elseatomic_set(key.status, KEY_KEEP); // 状态保持last_val current_val; }/** description : 打开设备* param - inode : 传递给驱动的inode* param - filp : 设备文件file结构体有个叫做private_data的成员变量* 一般在open的时候将private_data指向设备结构体。* return : 0 成功;其他 失败*/ static int key_open(struct inode *inode, struct file *filp) {return 0; }/** description : 从设备读取数据 * param – filp : 要打开的设备文件(文件描述符)* param – buf : 返回给用户空间的数据缓冲区* param – cnt : 要读取的数据长度* param – offt : 相对于文件首地址的偏移* return : 读取的字节数如果为负值表示读取失败*/ static ssize_t key_read(struct file *filp, char __user *buf,size_t cnt, loff_t *offt) {int ret;if (filp-f_flags O_NONBLOCK) { // 非阻塞方式访问if(KEY_KEEP atomic_read(key.status))return -EAGAIN;} else { // 阻塞方式访问/* 加入等待队列当有按键按下或松开动作发生时才会被唤醒 */ret wait_event_interruptible(key.r_wait, KEY_KEEP ! atomic_read(key.status));if(ret)return ret;}/* 将按键状态信息发送给应用程序 */ret copy_to_user(buf, key.status, sizeof(int));/* 状态重置 */atomic_set(key.status, KEY_KEEP);return ret; }/** description : fasync函数用于处理异步通知* param – fd : 文件描述符* param – filp : 要打开的设备文件(文件描述符)* param – on : 模式* return : 负数表示函数执行失败*/ static int key_fasync(int fd, struct file *filp, int on) {return fasync_helper(fd, filp, on, key.async_queue); }/** description : 向设备写数据 * param - filp : 设备文件表示打开的文件描述符* param - buf : 要写给设备写入的数据* param - cnt : 要写入的数据长度* param - offt : 相对于文件首地址的偏移* return : 写入的字节数如果为负值表示写入失败*/ static ssize_t key_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt) {return 0; }/** description : 关闭/释放设备* param - filp : 要关闭的设备文件(文件描述符)* return : 0 成功;其他 失败*/ static int key_release(struct inode *inode, struct file *filp) {return key_fasync(-1, filp, 0); }/** description : poll函数用于处理非阻塞访问* param - filp : 要打开的设备文件(文件描述符)* param - wait : 等待列表(poll_table)* return : 设备或者资源状态*/ static unsigned int key_poll(struct file *filp, struct poll_table_struct *wait) {unsigned int mask 0;poll_wait(filp, key.r_wait, wait);if(KEY_KEEP ! atomic_read(key.status)) // 按键按下或松开动作发生mask POLLIN | POLLRDNORM; // 返回PLLINreturn mask; }/* 设备操作函数 */ static struct file_operations key_fops {.owner THIS_MODULE,.open key_open,.read key_read,.write key_write,.release key_release,.poll key_poll,.fasync key_fasync, };/** description : 驱动入口函数* param : 无* return : 无*/ static int __init mykey_init(void) {int ret;/* 初始化等待队列头 */init_waitqueue_head(key.r_wait);/* 初始化按键状态 */atomic_set(key.status, KEY_KEEP);/* 设备树解析 */ret key_parse_dt();if(ret)return ret;/* GPIO 中断初始化 */ret key_gpio_init();if(ret)return ret;/* 注册字符设备驱动 *//* 1、创建设备号 */ret alloc_chrdev_region(key.devid, 0, KEY_CNT, KEY_NAME); /* 申请设备号 */if(ret 0) {pr_err(%s Couldnt alloc_chrdev_region, ret%d\r\n, KEY_NAME, ret);goto free_gpio;}/* 2、初始化cdev */key.cdev.owner THIS_MODULE;cdev_init(key.cdev, key_fops);/* 3、添加一个cdev */ret cdev_add(key.cdev, key.devid, KEY_CNT);if(ret 0)goto del_unregister;/* 4、创建类 */key.class class_create(THIS_MODULE, KEY_NAME);if (IS_ERR(key.class)) {goto del_cdev;}/* 5、创建设备 */key.device device_create(key.class, NULL, key.devid, NULL, KEY_NAME);if (IS_ERR(key.device)) {goto destroy_class;}/* 6、初始化timer设置定时器处理函数,还未设置周期所有不会激活定时器 */timer_setup(key.timer, key_timer_function, 0);return 0;destroy_class:device_destroy(key.class, key.devid); del_cdev:cdev_del(key.cdev); del_unregister:unregister_chrdev_region(key.devid, KEY_CNT); free_gpio:free_irq(key.irq_num, NULL);gpio_free(key.key_gpio);return -EIO; }/** description : 驱动出口函数* param : 无* return : 无*/ static void __exit mykey_exit(void) {/* 注销字符设备驱动 */cdev_del(key.cdev);/* 删除cdev */unregister_chrdev_region(key.devid, KEY_CNT); /* 注销设备号 */del_timer_sync(key.timer); /* 删除timer */device_destroy(key.class, key.devid);/*注销设备 */class_destroy(key.class); /* 注销类 */free_irq(key.irq_num, NULL); /* 释放中断 */gpio_free(key.key_gpio); /* 释放IO */ }module_init(mykey_init); module_exit(mykey_exit); MODULE_LICENSE(GPL); MODULE_AUTHOR(ALIENTEK); MODULE_INFO(intree, Y); 编写 asynchronizationApp.c 文件 #include stdio.h #include unistd.h #include sys/types.h #include sys/stat.h #include fcntl.h #include stdlib.h #include string.h #include signal.hstatic int fd;/** SIGIO信号处理函数* param – signum : 信号值* return : 无*/ static void sigio_signal_func(int signum) {unsigned int key_val 0;read(fd, key_val, sizeof(unsigned int));if (0 key_val)printf(Key Press\n);else if (1 key_val)printf(Key Release\n);printf(SIGIO signal!\r\n); }/** description : main主程序* param – argc : argv数组元素个数* param – argv : 具体参数* return : 0 成功;其他 失败*/ int main(int argc, char *argv[]) {int flags 0;/* 判断传参个数是否正确 */if(2 ! argc) {printf(Usage:\n\t./asyncKeyApp /dev/key\n);return -1;}/* 打开设备 */fd open(argv[1], O_RDONLY | O_NONBLOCK); // 非阻塞O_NONBLOCKif(0 fd) {printf(ERROR: %s file open failed!\n, argv[1]);return -1;}/* 设置信号SIGIO的处理函数 */signal(SIGIO, sigio_signal_func); // signal函数用于设置信号的处理函数fcntl(fd, F_SETOWN, getpid()); // 将当前进程的进程号告诉给内核flags fcntl(fd, F_GETFD); // 获取当前的进程状态fcntl(fd, F_SETFL, flags | FASYNC); // 设置进程启用异步通知功能/* 循环轮询读取按键数据 */while(1) {sleep(2);}/* 关闭设备 */close(fd);return 0; } 三、运行测试 首先先编写 Makefile 文件 KERNELDIR : /home/alientek/linux/atk-mpl/linux/my_linux/linux-5.4.31 CURRENT_PATH : $(shell pwd)obj-m : asynchronization.obuild: kernel_moduleskernel_modules:$(MAKE) -C $(KERNELDIR) M$(CURRENT_PATH) modulesclean:$(MAKE) -C $(KERNELDIR) M$(CURRENT_PATH) clean 之后编译 asynchronization.c 和 asynchronizationApp 文件 make arm-none-linux-gnueabihf-gcc asynchronizationApp.c -o asynchronization 将编译好的 asynchronizationApp 和 asynchronization.ko 复制到 sudo cp asynchronization asynchronization.ko /home/alientek/linux/nfs/rootfs/lib/modules/5.4.31/ -f 开启开发板输入以下命令 cd lib/modules/5.4.31/ depmod modprobe asynchronization.ko 测试 App 应用程序 ./asynchronization /dev/key 按下 Key0则会出现 每当按下 KEY0 的时候就会捕获到 SIGIO信号并且按键获取成功。 卸载驱动rmmod asynchronization.ko 总结 概念 其实异步通知就是让驱动设备空出来的时候发送一个信号给用户进程空间让进程空间知道哦原来可以使用这个设备了一般搭配 非阻塞异步通知使用效果更佳。 异步通知的使用方法需要掌握他们分为驱动和用户进程空间 在内核空间中① 定义 fasync_struct结构体② 编写fasync函数③ 最后当设备空出来的时候指定信号 kill_fasync。 在用户空间中① 编写信号处理函数并且最后把信号处理函数传给 signal函数② 本程序进程号告诉内核 fcntl(fd, F_SETOWN, getpid())③ 开启异步通知flags fcntl(fd, F_GETFL); /* 获取当前的进程状态 */ 、fcntl(fd, F_SETFL, flags | FASYNC); /* 开启当前进程异步通知功能 */ 代码其实跟上一节差不太多在按键按下/松开的时候设置kill_fasync发送信号给用户空间。有个小tip只要使用了file_operations函数里的函数都要在 static struct file_operations key_fops {...}这个函数下写下设备操作函数。测试代码中按照上述用户空间编写即可。
http://wiki.neutronadmin.com/news/194052/

相关文章:

  • 国内flask做的网站android毕业设计代做网站
  • 外贸网站示例建设局是干啥的
  • 怀化高速网站做网站刷东西
  • 一个主体如何添加网站怎样做淘宝客导购网站
  • python网站开发用什么山西省建设监理协会官方网站
  • 网站根目录多文件全国八大员报名官方网站
  • .net响应式网站模板辽宁建设工程信息网外网公示时间
  • 网站怎么登陆后台旅游网站的建设的意义
  • 外贸网站推广和建站网站建设免费模版
  • 深圳 福田网站建设建筑工程网招聘信息
  • 个人怎么进行网站建设wordpress使用手机号登录
  • 怎么把凡科网里做的网站保存成文件选择扬中网站建设
  • 建商城网站需要什么条件外贸建设企业网站服务
  • php做网站协会网站建站
  • 昆明建站网站资讯平台企业网站的建立
  • 旅行网站开发需求说明书免费企业网站开源系统
  • 竹子建站下载阜城县网站建设
  • 网站交易平台网站建设教程金旭亮
  • 网站seo多少钱国内著名设计公司
  • 网站单页制作教程网站动态图片如何做
  • 美食网站的设计与实现织梦网站转跳手机站
  • 黄石网站建设定做网迎客 网站建设
  • 网站推广的图片南宁制作网站服务商
  • 中国十佳网站建设公司组工网站建设方案
  • 建设网站的费用怎么做账上海设计网站大全
  • 上海高端品牌网站建设专家云服务器免费
  • 河池网站开发工程师招聘网html5做网页
  • 高中信息技术课网站怎么做汕头中英文网站推广
  • 山西科技网站建设网页制作中的常见问题
  • 乐清建设路小学网站图片转换链接生成器