- 论坛徽章:
- 0
|
下面的程序用于在屏幕上绘制一个矩形,在Ubuntu中能够编译通过,但运行时提示“Segmentation fault”。用GDB跟踪发现在第54行发生错误。既然已经将Frame Buffer映射到了进程地址空间中,为何不能访问该内存呢?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <sys/mman.h>
int main()
{
int fbfd = 0;
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
struct fb_cmap cmapinfo;
long int screensize = 0;
char *fbp = 0;
int x = 0, y = 0;
long int location = 0;
int b, g, r;
fbfd = open("/dev/fb0", O_RDWR);
if (fbfd < 0){
printf("Error: can not open framebuffer device: %x\n", fbfd);
exit(1);
}
printf("The framebuffer device was opened successfully.\n");
if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)){
printf("Error reading fixed information.\n");
exit(2);
}
printf("%s\n", finfo.id);
printf("type: 0x%x\n", finfo.type);
printf("visual: %d\n", finfo.visual);
printf("line_length: %d\n", finfo.line_length);
printf("mem_start: 0x%lx, smem_len: %d\n", finfo.smem_start, finfo.smem_len);
printf("mmio_start: 0x%lx, mmio_len: %d\n", finfo.mmio_start, finfo.mmio_len);
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)){
printf("Error reading variable information. \n");
exit(3);
}
printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);
screensize = vinfo.xres * vinfo.bits_per_pixel / 8;
fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
if ((int)fbp == -1){
printf("Error: failed to map framebuffer device to memory.\n");
exit(4);
}
printf("The framebuffer device was mapped to memory successfully.\n");
vinfo.xoffset = (vinfo.xres - 420) / 2;
vinfo.yoffset = (vinfo.yres - 340) / 2;
b = 10; g = 100; r = 100;
for (y = 0; y < 340; y++)
for ( x = 0; x < 420; x++){
location = (x + vinfo.xoffset) * (vinfo.bits_per_pixel/8 <<===== 这里发生错误
+ (y + vinfo.yoffset) * finfo.line_length;
if (vinfo.bits_per_pixel == 32){
*(fbp + location) = b;
*(fbp + location + 1) = g;
*(fbp + location + 2) = r;
*(fbp + location + 3) = 0;
}
else{
unsigned short int t = r << 11 | g << 5 | b;
*((unsigned short int *)(fbp + location)) = t;
}
}
munmap(fbp, screensize);
close(fbfd);
return 0;
}
|
|