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

论文网站开发淘宝购物

论文网站开发,淘宝购物,镇江个人网站建设,如何查一个公司的营业执照一、数据传输 1.1 APP和驱动 APP和驱动之间的数据访问是不能通过直接访问对方的内存地址来操作的#xff0c;这里涉及Linux系统中的MMU#xff08;内存管理单元#xff09;。在驱动程序中通过这两个函数来获得APP和传给APP数据#xff1a; copy_to_usercopy_from_user …一、数据传输 1.1 APP和驱动  APP和驱动之间的数据访问是不能通过直接访问对方的内存地址来操作的这里涉及Linux系统中的MMU内存管理单元。在驱动程序中通过这两个函数来获得APP和传给APP数据 copy_to_usercopy_from_user 简单来讲应用程序与内核/驱动程序在物理空间上是隔离开的应用程序和驱动程序是不可能互相访问到的。驱动程序里的copy_from_user得到应用层传来的数据驱动程序可以使用copy_to_user把数据发给应用程序即应用程序和驱动程序通过这两个函数交换数据。 1.2 驱动和硬件 各个子系统函数通过ioremap映射寄存器地址后直接访问寄存器 驱动程序操作硬件可以通过子系统的方式调用函数来操作硬件或者用最原始的办法ioremap映射寄存器的地址不是直接操作寄存器地址这样在驱动程序里就可以访问寄存器了。 二、APP使用驱动的4种方式 驱动程序提供能力不提供策略(驱动程序提供各种作用的函数供应用程序抉择并使用)。 2.1 非阻塞查询 如果在应用程序里open这个argv[1]设备节点时指定了非阻塞表示读数据时如果没有数据并且这个文件的flag是非阻塞则立刻返回一个错误。APP指定了非阻塞方式驱动程序是否判断它的flag完全由用户决定。 //应用程序 //O_RDWR可读可写O_NONBLOCK非阻塞方式 fd open(argv[1], O_RDWR | O_NONBLOCK);//驱动程序的read static ssize_t gpio_drv_read (struct file *file, char __user *buf, size_t size, loff_t *offset) {int err;int key;if (is_key_buf_empty() (file-f_flags O_NONBLOCK))return -EAGAIN;wait_event_interruptible(gpio_wait, !is_key_buf_empty());key get_key();err copy_to_user(buf, key, 4); return 4; } 2.2 阻塞休眠唤醒 如果一开始buf里没有数据APP调用读函数驱动程序读函数会进入wait_event_interruptible里休眠放弃运行不是死等等待被唤醒。所以我们经常看到read函数很久没有返回是因为在驱动程序里休眠了。该事件会记录在gpio_wait队列中。 //应用程序 //O_RDWR可读可写不设置非阻塞 fd open(argv[1], O_RDWR);//驱动程序的read static ssize_t gpio_drv_read (struct file *file, char __user *buf, size_t size, loff_t *offset) {int err;int key;if (is_key_buf_empty() (file-f_flags O_NONBLOCK))return -EAGAIN;wait_event_interruptible(gpio_wait, !is_key_buf_empty());key get_key();err copy_to_user(buf, key, 4); return 4; } 通常配合中断定时器的方式来唤醒该队列里面等待唤醒的进程/线程。 //中断函数 static irqreturn_t gpio_key_isr(int irq, void *dev_id) {struct gpio_desc *gpio_desc dev_id;printk(gpio_key_isr key %d irq happened\n, gpio_desc-gpio);//定时器 用来消除抖动//修改定时器的超时时间 jiffies(当前时间) 赫兹/5mod_timer(gpio_desc-key_timer, jiffies HZ/5);return IRQ_HANDLED;//成功处理 }//定时器超时函数 static void key_timer_expire(unsigned long data) {struct gpio_desc *gpio_desc (struct gpio_desc *)data;int val;int key;val gpio_get_value(gpio_desc-gpio);key (gpio_desc-key) | (val8);put_key(key);//按键值放入环形缓冲区//唤醒队列中的进程/线程wake_up_interruptible(gpio_wait);kill_fasync(button_fasync, SIGIO, POLL_IN); } 2.3 POLL休眠唤醒超时时间 2.3.1 POLL机制流程 使用休眠-唤醒的方式等待某个事件发生时有一个缺点 等待的时间可能很久。我们可以加上一个超时时间这时就可以使用 poll 机制。poll机制流程如下6步 ①APP不知道驱动程序中是否有数据可以先调用poll函数查询一下poll函数可以传入超时时间 ②APP进入内核态调用到驱动程序的poll函数如果有数据的话立刻返回 ③如果发现没有数据时就休眠一段时间 ④当有数据时比如当按下按键时驱动程序的中断服务程序和定时器超时函数被调用它会记录数据、唤醒APP ⑤当超时时间到了之后内核也会唤醒APP ⑥APP根据poll函数的返回值就可以知道是否有数据如果有数据就调用read得到数据。 2.3.2 POLL执行流程 图1 poll机制 函数执行流程如上图①⑧所示重点从③开始看。假设一开始无按键数据 ③APP调用poll之后进入内核态 ④在循环中执行程序致驱动程序的drv_poll被调用注意drv_poll要把自己这个线程挂入等待队列 wq 中并没有休眠且无数据返回0有数据返回POLLIN ⑤当前没有数据则在内核态中休眠一会等待超时内核唤醒或中断定时器唤醒 中断定时器唤醒情况 ⑥过程中按下了按键发生了中断定时器超时函数在定时器超时函数里记录了按键值并且从gpio_wait队列中把线程唤醒了 ⑦从休眠中被唤醒继续执行 for 循环再次调用 drv_poll在drv_poll中返回数据状态POLLIN ⑧有数据返回到内核态内核态返回到应用态 ⑨APP调用read函数读数据。 超时内核唤醒情况接着上面的⑤ ⑥在休眠过程中一直没有按下了按键超时时间到内核把这个线程唤醒 ⑦线程从休眠中被唤醒继续执行 for 循环再次调用 drv_polldrv_poll返回数据状态 ⑧还是没有数据但是超时时间到了那从内核态返回到应用态 ⑨APP不能调用 read 函数读数据。 需要注意一下几点 drv_poll 要把线程挂入队列gpio_wait但是并不是在 drv_poll 中进入休眠而是在调用 drv_poll 之后休眠drv_poll 要返回数据状态APP 调用一次 poll有可能会导致 drv_poll 被调用 2 次线程被唤醒的原因有 2个中断定时器发生了去队列gpio_wait中把它唤醒超时时间到了内核把它唤醒APP 要判断 poll 返回的原因有数据还是超时。有数据时再去调用read函数 2.3.3 POLL应用和驱动编程  驱动程序中的poll代码 static unsigned int gpio_drv_poll(struct file *fp, poll_table * wait) {poll_wait(fp, gpio_wait, wait);return is_key_buf_empty() ? 0 : POLLIN | POLLRDNORM; } 驱动程序中的中断触发函数按键消抖修改了定时器超时时间 static irqreturn_t gpio_key_isr(int irq, void *dev_id) {struct gpio_desc *gpio_desc dev_id;printk(gpio_key_isr key %d irq happened\n, gpio_desc-gpio);//定时器 用来消除抖动mod_timer(gpio_desc-key_timer, jiffies HZ/5);//修改定时器的超时时间 jiffies(当前时间) 赫兹/5return IRQ_HANDLED;//成功处理 } 定时器超时函数获取按键值储存按键值唤醒线程 static void key_timer_expire(unsigned long data) {struct gpio_desc *gpio_desc (struct gpio_desc *)data;int val;int key;val gpio_get_value(gpio_desc-gpio);key (gpio_desc-key) | (val8);put_key(key);//按键值放入环形缓冲区wake_up_interruptible(gpio_wait);//唤醒队列里的线程kill_fasync(button_fasync, SIGIO, POLL_IN); }应用程序代码 struct pollfd fds[1] int timeout_ms 5000; int ret; int fd; fds[0].fd fd; //查询fd这个文件 fds[0].events POLLIN; //POLLIN表示查询这个文件有没有数据让我读进来 fd open(argv[1], O_RDWR); if(fd -1) {printf(can not open file %s\n, argv[1]); }while(1) {ret poll(fds, 1, timeout_ms);//ret为1表示fds结构体中有文件满足返回条件且返回的事件是这个文件有数据让我读进来POLLINif((ret 1) (fds[0].revents POLLIN)){read(fd, val, 4);printf(get button : 0x%x\n, val);}else{printf(timeout\n);}} 2.4 异步通知 2.4.1 异步通知流程 使用休眠-唤醒、POLL机制时都需要休眠等待某个事件发生时它们的差别在于后者可以指定休眠的时长。如果APP不想休眠怎么办也有类似的方法驱动程序有数据时主动通知APPAPP收到信号后执行信息处理函数这就是异步通知。 图2 异步通知的信号流程 重点从②开始 ② APP 给 SIGIO 这个信号注册信号处理函数 func以后 APP 收到 SIGIO信号时这个函数会被自动调用 ③ 把 APP 的 PID(进程 ID)告诉驱动程序这个调用不涉及驱动程序在内核的文件系统层次记录 PID ④ 读取驱动程序文件 Flag ⑤ 设置 Flag 里面的 FASYNC 位为 1当 FASYNC 位发生变化时会导致驱动程序的 fasync 被调用 ⑥⑦ 调 用 faync_helper 它会根据FAYSNC的值决定是否设置button_async-fa_file驱动文件 filp驱动文件 filp 结构体里面含有之前设置的 PID。 ⑧ APP 可以做其他事 ⑨⑩ 按下按键发生中断驱动程序的中断服务程序被调用里面调用kill_fasync 发信号 ⑪⑫⑬ APP 收到信号后它的信号处理函数被自动调用可以在里面调用read 函数读取按键。 2.4.1 异步通知应用和驱动编程 应用程序信号处理函数注册信号处理函数打开驱动把进程ID告诉驱动使能驱动的FASYNC功能 static void sig_func(int sig) {int val;read(fd, val, 4);printf(get button : 0x%x\n, val); }signal(SIGIO, sig_func);fd open(argv[1], O_RDWR); if(fd -1) {printf(can not open file %s\n, argv[1]); }fcntl(fd, F_SETOWN, getpid()); //告诉驱动程序要给谁发信号 flags fcntl(fd, F_GETFL); //获得之前的flags fcntl(fd, F_SETFL, flags | FASYNC); //这是新的flags并使能驱动的FASYNC功能使能异步通知 驱动程序中的fasync被调用使能异步通知后会调用这个辅助函数来构造结构体结构体里存放进程id //构造button_fasync结构体结构体里存放进程id static int gpio_drv_fasync(int fd, struct file *file, int on) {if (fasync_helper(fd, file, on, button_fasync) 0)return 0;elsereturn -EIO; } 驱动程序中的中断触发函数按键消抖修改了定时器超时时间 static irqreturn_t gpio_key_isr(int irq, void *dev_id) {struct gpio_desc *gpio_desc dev_id;printk(gpio_key_isr key %d irq happened\n, gpio_desc-gpio);//定时器 用来消除抖动mod_timer(gpio_desc-key_timer, jiffies HZ/5);//修改定时器的超时时间 jiffies(当前时间) 赫兹/5return IRQ_HANDLED;//成功处理 } 定时器超时函数最后一行发送信号SIGIO给进程button_fasync结构体中有进程信息发送信号后应用程序中收到信号会打断while循环并先执行对应的信号处理函数再回到while循环。 static void key_timer_expire(unsigned long data) {struct gpio_desc *gpio_desc (struct gpio_desc *)data;int val;int key;val gpio_get_value(gpio_desc-gpio);key (gpio_desc-key) | (val8);put_key(key);//按键值放入环形缓冲区wake_up_interruptible(gpio_wait);//唤醒队列里的线程kill_fasync(button_fasync, SIGIO, POLL_IN); }
http://www.yayakq.cn/news/5794/

相关文章:

  • 锦州网站建设排行榜wordpress个人网站模板
  • 秦皇岛做网站公司汉狮价格wordpress编辑器定义
  • 广州网站建设怎么做许昌网站推广公司
  • 网站如何优化一个关键词网站app开发一站式服务
  • 电商网站运营怎么做网站建设 系统 排名
  • 网站更改对内部网站建设的意见和建议
  • wap网站开发视频教程网站优化网站
  • 网站域名已经解析但没有被百度等搜索引擎收录怎么办网站建设后端前端
  • 社交网站建设流程中国空间站研究项目
  • 网站运营与管理的对策建议虹口建设机械网站
  • 打开上次浏览的网站模板网站选项按钮
  • 做电影网站怎么批量去水印北京出名做网站的公司
  • 上海网站seo社交信息共享网站开发外包
  • 网站建设报价方案模板最近一两天的新闻有哪些
  • o2o分销系统网站建设网站用户运营
  • 网站怎么做图片动态图片大全公司公众网站微信平台建设方案
  • 企业网站php源码公司宣传网站
  • 本溪北京网站建设wordpress 图片放大
  • 深圳外贸网站外贸网站建设仿牌网站容易被攻击吗
  • 象山县建设局网站马鞍山市直网站集约化建设
  • 做视频网站需要多大的带宽wordpress添加自动关键词内链
  • 网站集约化建设存在的困难室内设计需要什么学历
  • 尼高网站设计公司网站开发运营推广叫什么
  • ae模板精品站互联网培训班
  • 宁波网站建设明细报价上海松江水处理网站建设
  • 信阳专业做网站公司网站制作推广需要多少钱
  • 莱芜住房和城乡建设部网站邯郸广告公司网站建设
  • 众筹网站建设报价春雨app直播免费版下载
  • 微信网站公众平台太原网站建设策划方案
  • 建设心理网站的背景网站建设常用代码