我在使用Java的Linux UIO设备时遇到问题。这个设备背后的想法是你有一个带有一组内存映射寄存器的外设。为了访问这些寄存器以进行读写,内核模块公开了一个可以被映射的设备文件(例如/ dev / ui0)以及用于与寄存器交互的指针。 C ++中的以下代码演示了行为:
#include <sys/mman.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <assert.h>
#include <cstdio>
int main() {
size_t filesize = 256;
//Open file
int fd = open("/dev/uio0", O_RDWR);
assert(fd != -1);
//Execute mmap
void* mmappedData = mmap(NULL, filesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
assert(mmappedData != MAP_FAILED);
//Write the mmapped data to stdout (= FD #1)
volatile int* regs = (int*) mmappedData;
for(int i =0; i < 7; i++) printf("REG[%d]=0x%08x\n", i, regs[i]);
//Cleanup
int rc = munmap(mmappedData, filesize);
assert(rc == 0);
close(fd);
return 0;
}
上面代码的输出是:
REG[0]=0x00000001
REG[1]=0x00000001
REG[2]=0x00000004
REG[3]=0x00000024
REG[4]=0xa0109146
REG[5]=0x00000024
REG[6]=0x000000b9
哪个是对的。但是,我试图通过以下Java代码实现相同的目标:
public class RegisterFile {
private final RandomAccessFile mRegisterSetFile;
private final MappedByteBuffer mByteBuffer;
public RegisterFile(String deviceName) throws IOException {
LOGGER.log(Level.INFO, "Mapping device: {0}", deviceName);
mRegisterSetFile = new RandomAccessFile(deviceName, "rws");
LOGGER.log(Level.INFO, "File length is: {0}", mRegisterSetFile.length());
mByteBuffer = mRegisterSetFile.getChannel().map(FileChannel.MapMode.READ_WRITE, 0, 256);
dump();
}
public final void dump() throws IOException {
StringBuilder builder = new StringBuilder("\n");
for (Address address : Address.values()) {
builder.append(String.format("REGFILE[%02d] = 0x%08x\n", address.get(), mByteBuffer.getInt(address.get())));
}
LOGGER.log(Level.INFO, "{0}", builder.toString());
}
}
但结果是:
[junit] Jan 13, 2018 3:50:26 PM org.apache.hadoop.io.compress.gzipFpga.RegisterFile <init>
[junit] INFO: Mapping device: /dev/uio0
[junit] Jan 13, 2018 3:50:26 PM org.apache.hadoop.io.compress.gzipFpga.RegisterFile <init>
[junit] INFO: File length is: 0
[junit] Jan 13, 2018 3:50:26 PM org.apache.hadoop.io.compress.gzipFpga.GzipFpgaCompressor gzipCoreAvailable
[junit] SEVERE: Unable to read from GZIP core devices.
[junit] java.io.IOException: Invalid argument
[junit] at sun.nio.ch.FileDispatcherImpl.truncate0(Native Method)
[junit] at sun.nio.ch.FileDispatcherImpl.truncate(FileDispatcherImpl.java:80)
[junit] at sun.nio.ch.FileChannelImpl.map(FileChannelImpl.java:906)
[junit] at org.apache.hadoop.io.compress.gzipFpga.RegisterFile.<init>(RegisterFile.java:85)
我认为原因是File.length()返回0,因为这不是真正的文件。有没有办法强制映射文件?