linux中将外设物理地址mmap映射到用户空间,通过在用户进程中访问映射的虚拟地址来读取外设的数据,并落盘,落盘时open函数使用O_DIRECT方式,直接write数据会报bad address错误,但如果使用posix_memalign申请一块空间来中转数据,再write就能写进去,这是为什么呢?
因为项目追求速度要快,所以使用O_DIRECT的方式,如果在途中还需要memcpy也会影响效率,有其他方法可以不经过缓存直接落盘吗?
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#define SHR_MEMSIZE 0x800000
#define MEM_CLEAR 0x0
#define MEM_RESET 0x1
#define MEM_DEV_FILENAME "/dev/mychrmem"
int main()
{
int fd;
int file_fd;
ssize_t ret;
char *shm = NULL;
char *rev_buf;
// posix_memalign((void**)&rev_buf, 512, SHR_MEMSIZE);
fd = open(MEM_DEV_FILENAME, O_RDWR);
if (fd < 0) {
printf("open(): %s\n", strerror(errno));
return -1;
}
file_fd = open("/mnt/test",O_WRONLY|O_CREAT|__O_DIRECT,0666);
if (file_fd < 0)
{
perror("open");
return -1;
}
shm = mmap(NULL, SHR_MEMSIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if (MAP_FAILED == shm) {
printf("mmap: %s\n", strerror(errno));
}
printf("Before Write, shm = %s\n", shm);
strcpy(shm,"User write to share memory!");
printf("After write, shm = %s\n", shm);
while(1)
{
// memcpy(rev_buf, shm, SHR_MEMSIZE); //中转数据能成功,但影响效率
// ret = write(file_fd, rev_buf, SHR_MEMSIZE);
ret = write(file_fd, shm, SHR_MEMSIZE); //直接写会提示bad address
printf("mem addr is 0x%lx\n",(long)shm);
if(ret==-1)
{
perror("write");
}
else
{
printf("write len 0x%lx\n",ret);
}
}
munmap(shm, SHR_MEMSIZE);
close(file_fd);
close(fd);
return 0;
}