Java实现DirectIo文件方式操作文件系统

创建于:2025-09-17 修改于:2025-09-17

Java实现DirectIo文件方式操作文件系统

场景

具体方法调用

1
2
3
4
5
private native int open(String pathname, int flags, int mode);  
private native int fcntl(int id, int cmd, int flags);  
private native int write(int fd, Pointer buf, int count);  
private native int posix_memalign(PointerByReference memptr, int alignment, int size);  
private native int close(int fd);  

核心代码

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
  
package com.huadi.utils.directio.io;  
  
import java.io.IOException;  
import java.io.OutputStream;  
  
import com.sun.jna.Native;  
import com.sun.jna.Pointer;  
import com.sun.jna.ptr.PointerByReference;  
  
public class JNAOutputStream extends OutputStream {  
  
//just a couple of them are used, here for eventual future uses  
protected static final int O_RDONLY = 00;  
protected static final int O_WRONLY = 01;  
protected static final int O_RDWR = 02;  
protected static final int O_CREAT = 0100;  
protected static final int O_EXCL = 0200;  
protected static final int O_NOCTTY = 0400;  
protected static final int O_TRUNC = 01000;  
protected static final int O_APPEND = 02000;  
protected static final int O_NONBLOCK = 04000;  
protected static final int O_NDELAY = O_NONBLOCK;  
protected static final int O_SYNC = 010000;  
protected static final int O_ASYNC = 020000;  
protected static final int O_DIRECT = 040000;  
protected static final int O_DIRECTORY = 0200000;  
protected static final int O_NOFOLLOW = 0400000;  
protected static final int O_NOATIME = 01000000;  
protected static final int O_CLOEXEC = 02000000;  
  
//fcntl has also other flags, not presented here  
protected static final int F_SETFL = 4;  
  
public static final int BLOCK_SIZE = 512;   
  
static {  
Native.register("c");  
}   
  
private native int open(String pathname, int flags, int mode);  
private native int fcntl(int id, int cmd, int flags);  
private native int write(int fd, Pointer buf, int count);  
private native int posix_memalign(PointerByReference memptr, int alignment, int size);  
private native int close(int fd);  
  
private int fd;  
private Pointer bufPnt;  
private byte[] buffer;  
private int pos;  
  
public JNAOutputStream(String pathname, boolean direct) throws IOException {  
  
if (!direct) {  
fd = open(pathname, O_CREAT|O_TRUNC|O_WRONLY, 00755);  
} else {  
// fd = open(pathname, O_CREAT|O_TRUNC|O_WRONLY|O_DIRECT, 00755);  
fd = open(pathname, O_CREAT|O_APPEND|O_WRONLY|O_DIRECT, 00755);  
}  
  
PointerByReference pntByRef = new PointerByReference();  
posix_memalign(pntByRef, BLOCK_SIZE, BLOCK_SIZE);  
bufPnt = pntByRef.getValue();   
buffer = new byte[BLOCK_SIZE];  
}  
  
@Override  
public void close() throws IOException {  
  
if (pos % BLOCK_SIZE != 0) {  
if (fcntl(fd, F_SETFL, ~O_DIRECT) < 0) {  
throw new IOException("Impossible to modify fd on close()");  
}  
bufPnt.write(0, buffer, 0, pos);  
int rtn = write(fd,bufPnt,pos);  
if (rtn != pos) {  
throw new IOException(rtn+"/"+pos+" bytes written to disk on close()");  
}  
}  
if (close(fd)< 0) {  
throw new IOException("Problems occured while doing close()");  
}  
}   
  
@Override  
public void write(int b) throws IOException {  
if (pos < BLOCK_SIZE) {  
buffer[pos++] = (byte)b;  
}  
if (pos == BLOCK_SIZE) {  
bufPnt.write(0, buffer, 0, BLOCK_SIZE);  
int rtn = write(fd, bufPnt, BLOCK_SIZE);  
if (rtn != BLOCK_SIZE) {  
throw new IOException(rtn+"/"+BLOCK_SIZE+" bytes written to disk");  
}  
pos = 0;  
}  
}  
  
}  
  

使用方式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
  
package com.huadi.utils.directio.io;  
  
import java.io.*;  
import java.util.Random;  
  
  
public class Run {  
  
/**  
* @ower 张建新  
* @param args  
* @throws IOException   
*/  
private static final int BLOCK_SIZE = 4 * 1024;  
public static void main(String[] args) throws IOException {  
Random rand = new Random(System.nanoTime());  
int runs = Integer.parseInt(args[0]);  
int integers = Integer.parseInt(args[1]);  
long[] sio = new long[2];  
long[] jnaio = new long[2];  
long[] djnaio = new long[2];  
int[] data = new int[integers];  
for (int i = 0; i < integers; i++) {  
data[i] = rand.nextInt();  
}  
for (int i = 0; i < runs; i++) {  
runStd(data, sio);  
runJNA(data, jnaio, false);  
runJNA(data, djnaio, true);  
}  
System.out.println("JNA I/O (ns): "+jnaio[1]/(double)runs+"/"+jnaio[0]/(double)runs);  
System.out.println("O_DIRECT JNA I/O (ns): "+djnaio[1]/(double)runs+"/"+djnaio[0]/(double)runs);  
System.out.println("Standard I/O (ns): "+sio[1]/(double)runs+"/"+sio[0]/(double)runs);  
}  
  
public static void writeLineToFile2(byte[] data,String filename) throws IOException {  
DataOutputStream out = new DataOutputStream(new JNAOutputStream(filename, true));  
write(out, data);  
out.close();  
}  
  
  
public static void runStd(int data[], long time[]) throws IOException {  
String filename = "/tmp/"+System.nanoTime()+".bin";  
DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(filename), 512));  
time[0] += write(out, data);   
out.close();  
DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(filename), 512));  
time[1] += read(in, data);  
in.close();  
}  
  
public static void runJNA(int data[], long time[], boolean o_direct) throws IOException {  
String filename = "/tmp/"+System.nanoTime()+".bin";  
DataOutputStream out = new DataOutputStream(new JNAOutputStream(filename, o_direct));  
time[0] += write(out, data);   
out.close();  
DataInputStream in = new DataInputStream(new JNAInputStream(filename, o_direct));  
time[1] += read(in, data);  
in.close();  
}   
  
public static long write(DataOutputStream out, int[] data) throws IOException {  
long t = System.nanoTime();  
for (int i = 0; i < data.length; i++ ) {  
out.writeInt(data[i]);  
}  
out.flush();  
return System.nanoTime() - t;  
}  
  
public static long write(DataOutputStream out, byte[] data) throws IOException {  
long t = System.nanoTime();  
for (int i = 0; i < data.length; i++ ) {  
out.write(data[i]);  
}  
out.flush();  
return System.nanoTime() - t;  
}  
  
  
public static long read(DataInputStream in, int[] data) throws IOException {  
long t = System.nanoTime();  
for (int i = 0; i < data.length; i++) {  
if (data[i] != in.readInt()) {  
throw new IOException("wrong!");  
}  
}  
return System.nanoTime() - t;  
}  
  
}  
  
💬 评论区