接上一篇讲到了lseek偏移量,
文件空洞
文件空洞是指:文件中某些部分没有实际存储数据,但是占用了磁盘空间
作用: 1.节省存储空间 2.提高文件读写效率 3.支持稀疏文件
例如下面的例子
液晶屏的基本概念
像素:
屏幕上显示颜色的最小单位,英文名pixel
分辨率:
宽,高两个维度上的像素点数目,分辨率越高所需要的显存越大。
色深:
每个像素所对应的内存字节数,一般有8位,16位,24位,32位,32位色深的屏幕一般被称为真彩屏。
色深决定了一个像素点所能表达的颜色的丰富程度,色深越大,色彩表现力越强。
内存映射基本原理mmap()
注意几点:
1.使用mmap内存映射时,指定的读写权限必须是打开模式的子集。
2.映射模式为MAP_SHSRED时,修改的内容会影响文件。
3.映射模式为MAP_PRIVATE时,修改的内容不会影响文件。
屏幕参数设定
屏幕的硬件参数,都是有硬件驱动工程师根据硬件数据手册和内核的相关规定,填入某个固定的地方的(指的是源码,结构体),再有开发工程师使用特定的函数接口,将源码里面的信息读出来
输入子系统
在linux的内核中,对输入设备的使用,实际运用的三大块来管理,分别是输入设备驱动层,输入子系统核心层,以及时间触发层。各自的工作分别是:
1.输入设备驱动层:
每一种设备都有其特定的驱动程序,他们被装载到操作系统的设备模型框架内,封装硬件所提供的功能,向上提供规定的接口。
2.核心层:
此处将收集由设备驱动层发来的数据,整合之后触发某一事件。
3.事件触发层:
这一层是我们需要关注的,我们可以通过在用户空间读取相应设备的节点文件,来获知某设备的某一动作。
输入信息结构体
内核所获知的各类输入事件,比如滑动屏幕,键盘被按了一下等,都将被统一封装在一个叫做input_event的输入信息结构体中
该结构体有4个成员
1.time:
输入时间发生的时间戳,精确到微秒。
2.type:
输入事件的类型,比如:
3.code :
对事件类型做进一步描述。比如:
4.value:
当code 都不足以区分事件的性质的时候,可以用value来确认。
触摸屏操作
对于触摸屏而言会产生三种数据:X轴坐标值 Y轴坐标值 P压力值
滑屏显示坐标,松手退出
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <string.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <linux/input.h>
int main(int argc, char const *argv[])
{
int ts_x,ts_y;
// 非阻塞打开触摸屏设备
//int ts_fd = open("/dev/input/event1",O_RDWR|O_NONBLOCK);
// 阻塞打开触摸屏设备
int ts_fd = open("/dev/input/event1",O_RDWR);
if(ts_fd == -1)
{
perror("open ts failed:");
return -1;
}
struct input_event ts_event = {0};
// 循环读取事件
while(1)
{
read(ts_fd, &ts_event, sizeof(ts_event));
if(ts_event.type == EV_ABS && ts_event.code == ABS_MT_POSITION_X)
{
ts_x = ts_event.value;
}
if(ts_event.type == EV_ABS && ts_event.code == ABS_MT_POSITION_Y)
{
ts_y = ts_event.value;
}
// 判断持续事件,并且连续事件结束后打印坐标值
if(ts_event.type == EV_SYN && ts_event.code == SYN_REPORT)
{
printf("(%d,%d)\n",ts_x,ts_y);
}
// 松手
if(ts_event.code == ABS_MT_TRACKING_ID && ts_event.value == -1)
{
break;
}
}
// 关闭ts
close(ts_fd);
return 0;
}
显示BMP图片流程
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <string.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <linux/input.h>
int main(int argc, char const *argv[])
{
// 打开lcd设备文件
int lcd_fd = open("/dev/fb0",O_RDWR);
if(lcd_fd == -1)
{
perror("open lcd failed:");
return -1;
}
// 打开bmp图片
int bmp_fd = open("./dog.bmp",O_RDWR);
if(bmp_fd == -1)
{
perror("open bmp failed:");
return -1;
}
// 跳过54字节bmp头信息
lseek(bmp_fd, 54, SEEK_SET);
// 读取图片数据
char buf[1024*600*3] = {0};
read(bmp_fd, buf, sizeof(buf));
// 将3字节的bmp数据转为4字节的bmp数据
int bmp_buf[1024*600] = {0};
int i,j;
for(i = 0,j = 0; i < 1024*600; i++,j+=3)
{
bmp_buf[i] = buf[0+j] << 0 | buf[1+j] << 8 | buf[2+j] << 16 | 0x0 << 24;
}
// 图片进行翻转
int lcd_buf[1024*600] = {0};
int x,y;
for(y = 0; y < 600; y++)
{
for(x = 0; x < 1024; x++)
{
lcd_buf[y*1024+x] = bmp_buf[(599-y)*1024+x];
}
}
// 将bmp写入到lcd
write(lcd_fd, lcd_buf, sizeof(lcd_buf));
// 关闭lcd
close(lcd_fd);
close(bmp_fd);
return 0;
}
通过mmap内存映射显示图片
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <string.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <linux/input.h>
void showBmp(const char *bmp_path)
{
// 打开lcd
int lcd_fd = open("/dev/fb0",O_RDWR);
if(lcd_fd == -1)
{
perror("open lcd failed:");
return ;
}
// lcd映射
int *lcd_ptr = mmap(NULL,
1024*600*4,
PROT_READ|PROT_WRITE,
MAP_SHARED,
lcd_fd,
0 );
if(lcd_ptr == NULL)
{
perror("mmap failed:");
return ;
}
// 打开图片
int bmp_fd = open(bmp_path,O_RDWR);
if(bmp_fd == -1)
{
perror("oopen bmp failed");
return ;
}
// 跳过54字节头信息
lseek(bmp_fd, 54, SEEK_SET);
// 读取图片
char buf[1024*600*3] = {0};
read(bmp_fd,buf,sizeof(buf));
// 关闭图片
close(bmp_fd);
// 将3字节转为4字节
int i,j;
int bmp_buf[1024*600] = {0};
for(i = 0, j = 0; i < 1024*600; i++,j+=3)
{
bmp_buf[i] = buf[j+0] << 0 | buf[j+1] << 8 | buf[j+2] << 16;
}
// 翻转
int x, y;
for(y = 0; y < 600; y++)
{
for(x = 0; x < 1024; x++)
{
lcd_ptr[y*1024+x] = bmp_buf[(599-y)*1024+x];
}
}
// 解除映射,关闭设备
munmap(lcd_ptr,1024*600*4);
close(lcd_fd);
}
int main(int argc, char const *argv[])
{
// 显示图片
showBmp("./dog.bmp");
return 0;
}