Linux下使用各种设备是一件令人兴奋的事情。在Unix的世界里,用户与硬件打交待总是简单的。最近笔者在Linux下搞了摄像头的开发,有一点感想发于此处。
Linux中操作一个设备一般都是打开(open),读取(read)和关闭(close)。使用Read的大多是一些字符型设备,然而对于显示屏或者摄像头这种字符设备而已,挨个字的读写将使得系统调用变得频繁,众所周之,系统调用对于系统而已是个不小的开销。于是有内存映射(mmap)等物,本例中将讲述在Linux下开发摄像头的一般过程以及使用Qt进行界面开发的实例。
使用mmap方式获取摄像头数据的方式过程一般为:
打开设备 -> 获取设备的信息 -> 请求设备的缓冲区 -> 获得缓冲区的开始地址及大小 -> 使用mmap获得进程地址空间的缓冲区起始地址 -> 读取缓冲区。
Mmap就是所谓内存映射。很多设备带有自己的数据缓冲区,或者驱动本身在内核空间中维护一片内存区域,为了让用户空间程序安全地访问,内核往往要从设备内存或者内核空间内存复制数据到用户空间。这样一来便多了复制内存这个环节,浪费了时间。因此mmap就将目标存储区域映射到一个用户空间的一片内存,这样用户进程访问这片内存时,内核将自动转换为访问这个目标存储区。这种转换往往是地址的线性变化而已(很多设备的存储空间在所谓外围总线地址空间(X86)或者总的地址空间(ARM)上都是连续的),所以不必担心其转换的效率。
现在开始叙述Video4Linux2的使用。
/* 打开设备并进行错误检查 */
int fd = open ("/dev/video",O_RDONLY);
if (fd==-1){
perror ("Can't open device");
return -1;
}
/* 查询设备的输出格式 */
struct v4l2_format format;
memset (&format,0,sizoef(format));
format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (-1==ioctl(fd,VIDIOC_G_FMT,&format)){
perror ("While getting format");
return -2;
}
<