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

泉州网站公司建站惠州seo全网营销

泉州网站公司建站,惠州seo全网营销,网页设计基础课程,深圳做外贸的公司异步IO 异步 I/O 允许应用程序在发起 I/O 操作后,继续执行其他任务,而不需要等待 I/O 操作完成。与非阻塞 I/O 不同的是,异步 I/O 不需要应用程序轮询检查 I/O 操作的状态,而是由操作系统在 I/O 操作完成后通过某种方式&#xff…

异步IO

异步 I/O 允许应用程序在发起 I/O 操作后,继续执行其他任务,而不需要等待 I/O 操作完成。与非阻塞 I/O 不同的是,异步 I/O 不需要应用程序轮询检查 I/O 操作的状态,而是由操作系统在 I/O 操作完成后通过某种方式(如信号、回调函数等)通知应用程序。例如,在 Linux 系统中,可以使用aio_*系列函数(如aio_read、aio_write等)来实现异步 I/O。当调用aio_read函数发起一个异步读操作后,应用程序可以继续执行其他代码,当读取操作完成后,操作系统会向应用程序发送一个信号(默认是SIGIO),应用程序可以通过信号处理函数来处理读取到的数据。异步 I/O 大大提高了应用程序的并发性能和响应能力,但编程模型相对复杂,需要仔细处理 I/O 操作的完成通知和数据处理逻辑。

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>#define BUFFER_SIZE 1024
int mouse_fd = -1;// 统一的信号处理函数
void signal_handler(int signum) {if (signum == SIGIO) {char buffer[BUFFER_SIZE];ssize_t bytes_read;// 读取鼠标输入memset(buffer, 0, sizeof(buffer));bytes_read = read(mouse_fd, buffer, BUFFER_SIZE);if (bytes_read > 0) {printf("鼠标输入: 读取到 %zd 字节\n", bytes_read);}// 读取键盘输入memset(buffer, 0, sizeof(buffer));bytes_read = read(STDIN_FILENO, buffer, BUFFER_SIZE);if (bytes_read > 0) {buffer[bytes_read] = '\0';printf("键盘输入: %s", buffer);}}
}int main() {int flags;struct sigaction sa;// 初始化 sigaction 结构体memset(&sa, 0, sizeof(sa));sa.sa_handler = signal_handler;sigemptyset(&sa.sa_mask);sa.sa_flags = SA_RESTART;// 为 SIGIO 信号设置信号处理函数if (sigaction(SIGIO, &sa, NULL) == -1) {perror("sigaction");return 1;}// 设置当前进程为标准输入的拥有者fcntl(STDIN_FILENO, F_SETOWN, getpid());// 获取标准输入的当前文件状态标志flags = fcntl(STDIN_FILENO, F_GETFL);if (flags == -1) {perror("fcntl F_GETFL");return 1;}// 设置标准输入为异步 I/O 模式flags |= O_ASYNC;if (fcntl(STDIN_FILENO, F_SETFL, flags) == -1) {perror("fcntl F_SETFL");return 1;}// 对鼠标设备文件进行相同的操作mouse_fd = open("/dev/input/mouse0", O_RDONLY);if (mouse_fd == -1) {perror("无法打开鼠标设备文件");return 1;}fcntl(mouse_fd, F_SETOWN, getpid());flags = fcntl(mouse_fd, F_GETFL);if (flags == -1) {perror("fcntl F_GETFL (鼠标)");close(mouse_fd);return 1;}flags |= O_ASYNC;if (fcntl(mouse_fd, F_SETFL, flags) == -1) {perror("fcntl F_SETFL (鼠标)");close(mouse_fd);return 1;}printf("开始异步 I/O 监听...\n");// 进入无限循环,等待信号while (1) {pause();}return 0;
}

在这里插入图片描述
存在bug , 多次操作键盘后,没有进入回调函数,接着移动鼠标,才会触发!!!

存储映射IO

存储映射 I/O(Memory - Mapped I/O)是一种将文件或设备的内容映射到进程地址空间的技术。通过这种方式,应用程序可以像访问内存一样访问文件或设备的数据,而不需要使用传统的read和write系统调用。在 Linux 系统中,可以使用mmap函数来实现存储映射 I/O。

#include <sys/mman.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>int main() {int fd = open("test.txt", O_RDWR);if (fd == -1) {perror("open");exit(EXIT_FAILURE);}off_t file_size = lseek(fd, 0, SEEK_END);lseek(fd, 0, SEEK_SET);// 直接传递 fd,并且进行显式类型转换char *map = static_cast<char*>(mmap(NULL, file_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));if (map == MAP_FAILED) {perror("mmap");close(fd);exit(EXIT_FAILURE);}pid_t pid = fork();if (pid == -1) {perror("fork");munmap(map, file_size);close(fd);exit(EXIT_FAILURE);} else if (pid == 0) {// 子进程printf("子进程读取文件内容:\n%s", map);// 修改映射内存中的内容map[0] = 'Y';} else {// 父进程wait(NULL);printf("父进程读取修改后的文件内容:\n%s", map);}// 解除映射if (munmap(map, file_size) == -1) {perror("munmap");}close(fd);return 0;
}

在这里插入图片描述

通过mmap函数,将文件test.txt映射到进程的地址空间,map指向映射后的内存区域。对map的读写操作就相当于对文件的读写操作,并且对映射内存的修改会自动同步到文件中。存储映射 I/O 提高了 I/O 操作的效率,特别是对于大文件的读写操作,减少了数据在用户空间和内核空间之间的复制次数。同时,多个进程可以共享同一个文件的映射,实现进程间通信和数据共享。

LCD 显存的内存映射

基本概念

LCD 显存:LCD(Liquid Crystal Display,液晶显示器)显存是专门用于存储要显示在屏幕上的图像数据的内存区域。显示器会按照一定的刷新频率从显存中读取数据,并将其转换为对应的像素点显示在屏幕上。
内存映射:内存映射是一种将物理内存地址(如 LCD 显存的物理地址)映射到进程的虚拟地址空间的技术。通过内存映射,应用程序可以像访问普通内存一样访问物理设备的内存,从而实现对设备的直接读写操作。

实现步骤

  1. 打开设备文件
    在 Linux 系统中,LCD 设备通常以文件的形式存在于/dev目录下。应用程序需要使用open()函数打开对应的设备文件,以获取设备文件描述符。
#include <fcntl.h>
#include <stdio.h>int fd = open("/dev/fb0", O_RDWR);
if (fd == -1) {perror("open");return -1;
}
  1. 获取 LCD 显存的物理地址和大小
    通过ioctl()函数向设备驱动程序发送特定的命令,获取 LCD 显存的物理地址和大小等信息。
#include <sys/ioctl.h>
#include <linux/fb.h>struct fb_fix_screeninfo finfo;
struct fb_var_screeninfo vinfo;if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) {perror("ioctl FBIOGET_FSCREENINFO");close(fd);return -1;
}if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) == -1) {perror("ioctl FBIOGET_VSCREENINFO");close(fd);return -1;
}size_t screen_size = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;

#include <sys/ioctl.h>:该头文件提供了 ioctl 函数的声明。ioctl(Input/Output Control)是一个用于设备输入输出控制操作的系统调用,它允许用户空间程序向设备驱动程序发送特定的控制命令,以实现对设备的各种操作。
#include <linux/fb.h>:此头文件定义了与 Linux 帧缓冲设备(Frame Buffer)相关的数据结构和常量。帧缓冲设备是 Linux 系统中用于管理图形显示的一种抽象设备,通过它可以直接访问显示器的显存。

struct fb_fix_screeninfo finfo;:定义了一个 fb_fix_screeninfo 类型的结构体变量 finfo。fb_fix_screeninfo 结构体用于存储帧缓冲设备的固定信息,这些信息在设备初始化后通常不会改变,例如帧缓冲设备的物理地址、一行像素数据的字节数等。
struct fb_var_screeninfo vinfo;:定义了一个 fb_var_screeninfo 类型的结构体变量 vinfo。fb_var_screeninfo 结构体用于存储帧缓冲设备的可变信息,这些信息可以通过 ioctl 命令进行修改,例如屏幕的分辨率、像素深度等。

ioctl(fd, FBIOGET_FSCREENINFO, &finfo):调用 ioctl 函数向帧缓冲设备发送 FBIOGET_FSCREENINFO 命令,该命令用于获取帧缓冲设备的固定屏幕信息。fd 是帧缓冲设备文件的文件描述符,&finfo 是存储固定屏幕信息的结构体变量的地址。
if (ioctl(…) == -1):检查 ioctl 函数的返回值。如果返回值为 -1,表示 ioctl 操作失败。
perror(“ioctl FBIOGET_FSCREENINFO”);:如果 ioctl 操作失败,使用 perror 函数输出错误信息,提示用户在获取固定屏幕信息时发生了错误。
close(fd);:关闭帧缓冲设备文件的文件描述符,释放相关资源。
return -1;:返回 -1 表示程序执行失败。

ioctl(fd, FBIOGET_VSCREENINFO, &vinfo):调用 ioctl 函数向帧缓冲设备发送 FBIOGET_VSCREENINFO 命令,该命令用于获取帧缓冲设备的可变屏幕信息。&vinfo 是存储可变屏幕信息的结构体变量的地址。
后续的错误处理逻辑与获取固定屏幕信息时类似,如果 ioctl 操作失败,输出错误信息,关闭文件描述符,并返回 -1 表示程序执行失败。

vinfo.xres:表示屏幕的水平分辨率,即屏幕一行的像素数量。
vinfo.yres:表示屏幕的垂直分辨率,即屏幕一列的像素数量。
vinfo.bits_per_pixel:表示每个像素占用的位数,例如 8 位、16 位、24 位等。
vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8:通过水平分辨率、垂直分辨率和每个像素占用的位数计算出屏幕显存的总字节数,并将结果存储在 screen_size 变量中。

  1. 进行内存映射
    使用mmap()函数将 LCD 显存的物理地址映射到进程的虚拟地址空间。
#include <sys/mman.h>char *fbp = (char *)mmap(0, screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (fbp == MAP_FAILED) {perror("mmap");close(fd);return -1;
}
  1. 访问 LCD 显存
    应用程序可以像访问普通内存一样访问映射后的虚拟地址,从而实现对 LCD 屏幕的控制。
// 在屏幕左上角绘制一个红色像素点
int x = 0;
int y = 0;
long location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) +(y+vinfo.yoffset) * finfo.line_length;*(fbp + location) = 255;        // 蓝色通道
*(fbp + location + 1) = 0;      // 绿色通道
*(fbp + location + 2) = 0;      // 红色通道
*(fbp + location + 3) = 0;      // 透明度通道
  1. 解除内存映射并关闭设备文件
    在使用完 LCD 显存后,需要使用munmap()函数解除内存映射,并使用close()函数关闭设备文件。
if (munmap(fbp, screen_size) == -1) {perror("munmap");
}
close(fd);

优点

高效性:内存映射避免了数据在用户空间和内核空间之间的频繁拷贝,提高了数据传输的效率。
简化编程:应用程序可以使用普通的内存访问指令来访问 LCD 显存,无需使用复杂的设备驱动接口,降低了编程难度。

刷新显存

全部刷新

  • 原理
    全部刷新指的是每次刷新时把整个显存区域的数据都更新一遍。也就是不管屏幕上的图像有没有变化,都会将新的一帧完整图像数据写入显存。这种方式简单直接,不过可能会消耗较多的带宽和计算资源,尤其是在画面变化较小时。
  • 实现步骤
    生成新的图像数据:在应用程序里,按照需求生成一帧完整的图像数据。这可能涉及到图形渲染、图像处理等操作。
    写入显存:把生成的新图像数据写入到显存对应的地址空间。在不同的系统中,写入方式会有所不同,常见的有内存映射、直接内存访问(DMA)等。
    等待显示器刷新:显示器会按照一定的刷新频率从显存读取数据并显示出来。在完成数据写入后,需要等待显示器进行下一次刷新,这样新的图像才能显示在屏幕上。
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <stdio.h>
#include <stdlib.h>int main() {int fd = open("/dev/fb0", O_RDWR);if (fd == -1) {perror("open");return -1;}struct fb_fix_screeninfo finfo;struct fb_var_screeninfo vinfo;if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) {perror("ioctl FBIOGET_FSCREENINFO");close(fd);return -1;}if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) == -1) {perror("ioctl FBIOGET_VSCREENINFO");close(fd);return -1;}size_t screen_size = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;char *fbp = (char *)mmap(0, screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);if (fbp == MAP_FAILED) {perror("mmap");close(fd);return -1;}// 生成新的图像数据(这里简单地将整个显存清零)for (size_t i = 0; i < screen_size; i++) {fbp[i] = 0;}// 解除映射并关闭文件if (munmap(fbp, screen_size) == -1) {perror("munmap");}close(fd);return 0;
}

更新刷新

  • 原理
    更新刷新只更新显存中发生变化的部分,而不是整个显存区域。这样可以减少数据传输量和处理时间,提高效率,特别是在画面只有部分区域变化的情况下。
  • 实现步骤
    检测变化区域:**应用程序需要检测出屏幕上哪些区域的图像发生了变化。**这可以通过比较前后两帧图像的差异来实现,也可以根据应用程序的逻辑直接确定变化的区域。
    生成变化区域的新数据:针对检测到的变化区域,生成新的图像数据。
    更新显存:把变化区域的新数据写入到显存对应的位置。
    等待显示器刷新:和全部刷新一样,等待显示器进行下一次刷新,让变化的部分显示在屏幕上。
# 假设 old_frame 和 new_frame 是前后两帧图像数据
old_frame = get_old_frame()
new_frame = get_new_frame()# 检测变化区域
changed_rects = detect_changed_rects(old_frame, new_frame)# 遍历变化区域并更新显存
for rect in changed_rects:x, y, width, height = rectfor i in range(y, y + height):for j in range(x, x + width):# 计算显存中的位置index = calculate_index(i, j)# 更新显存中的数据update_framebuffer(index, new_frame[i][j])

总结

全部刷新实现简单,但效率较低;更新刷新能提高效率,但实现复杂度较高,需要额外的处理来检测变化区域。在实际应用中,要根据具体的需求和场景选择合适的刷新方式。

http://www.dtcms.com/wzjs/111036.html

相关文章:

  • 红色色系做网站的配色宁波seo在线优化哪家好
  • 做网站一般要多少钱成都官网seo费用
  • 建设网站公司兴田德润官方地址seo公司外包
  • 网站建设403武汉外包seo公司
  • 网站建设公司资讯培训网站搭建
  • wordpress做社交网站江苏网站建设推广
  • 重庆网站制作一般多少钱小红书推广价目表
  • 佛山做网站的哪个好bing搜索引擎国际版
  • 可以做渗透的网站百度网址大全下载
  • 茶叶网站建设太原做网站哪家好
  • 郴州文明网网站市场营销师报名官网
  • 个人如何做问答类网站网络营销服务外包
  • 网站建设托管定制微信小程序怎么制作自己的程序
  • asp网站 证书实训百度搜索引擎的总结
  • 征婚网站上拉业务做恒指期货武汉网站seo服务
  • php网站开发技术文档南京seo公司教程
  • 企业管理平台系统网站网络营销app有哪些
  • 中国建设银行网站-诚聘英才海南百度推广电话
  • wordpress 迅雷seo和sem的关系
  • 哪个网站可以做司考题站长工具站长
  • 建筑网站知名度seo在线培训课程
  • 网站建设服务费属于什么费用sem什么意思
  • 服装代销的网站源码下载百度推广app
  • 闸北专业做网站sem竞价推广代运营收费
  • 制作网站的方法打开官方网站
  • 广州公司网站开发seo平台
  • 建湖做网站哪家最好百度明星人气榜排名
  • 苏州工业园区规划建设局网站广告联盟点击赚钱平台
  • 动态网站建设名词解释武汉seo软件
  • 广州做网站系统全球疫情最新消息