Program
/* Below program showcases the use of O_DIRECT file option. Also, demonstrates writev() use */
#include <iostream>
#include <fcntl.h> /* For O_RDWR */
#include <unistd.h> /* For open(), creat() */
#include <string.h> /* For strlen() */
#include <malloc.h> /* For memalign() */
#include <sys/uio.h> /* For struct iovec */
#include <stdint.h> /* For datatypes */
#define O_DIRECT_ENABLE 1
using namespace std;
int main(int argc, char *argv[])
{
if (argc != 3) {
cout << "run: ./<prog_binary_name> <input_file_name> <outputFileName>"<<endl;
return 0;
}
int fd_out, fd_in, ret;
#if O_DIRECT_ENABLE
fd_out = open(argv[2], O_CREAT | O_WRONLY | O_TRUNC | O_APPEND | O_DIRECT, S_IRWXG | S_IRWXU);
fd_in = open(argv[1], O_RDONLY | O_DIRECT);
#else
fd_out = open(argv[2], O_CREAT | O_WRONLY | O_TRUNC | O_APPEND, S_IRWXG | S_IRWXU);
fd_in = open(argv[1], O_RDONLY);
#endif
if(!fd_out || !fd_in) {
cout << "Unable to open one of the given files"<<endl;
return 0;
}
char file_data1[4096];
char *file_data2 = (char*)memalign(4096, 4096);
/* Below vector declaration won't compile since aligned_allocator defined in xilinx lib.
vector<uint8_t, aligned_allocator<uint8_t>> file_data3(4096);
read(fd_in, file_data3, 4096);
int file_data3_len = strlen(file_data2);
*/
Program Output
$g++ odirect_writev_prog.cpp -o odirect_writev_prog
$ ./odirect_writev_prog input.txt output_fd.txt
read_4k_nonMemAlign, read_4k_memAlign: 0, 4096
data(malloc) write ret: -1
data2(memalign) write ret: 4096
seek ret1: 96
write_ret2: -1
seek ret2: 96
total_len: 8288 {96, 95, 0, 4096}
writev ret: -1
seek ret: 4191
ret: -1
/* Below program showcases the use of O_DIRECT file option. Also, demonstrates writev() use */
#include <iostream>
#include <fcntl.h> /* For O_RDWR */
#include <unistd.h> /* For open(), creat() */
#include <string.h> /* For strlen() */
#include <malloc.h> /* For memalign() */
#include <sys/uio.h> /* For struct iovec */
#include <stdint.h> /* For datatypes */
#define O_DIRECT_ENABLE 1
using namespace std;
int main(int argc, char *argv[])
{
if (argc != 3) {
cout << "run: ./<prog_binary_name> <input_file_name> <outputFileName>"<<endl;
return 0;
}
int fd_out, fd_in, ret;
#if O_DIRECT_ENABLE
fd_out = open(argv[2], O_CREAT | O_WRONLY | O_TRUNC | O_APPEND | O_DIRECT, S_IRWXG | S_IRWXU);
fd_in = open(argv[1], O_RDONLY | O_DIRECT);
#else
fd_out = open(argv[2], O_CREAT | O_WRONLY | O_TRUNC | O_APPEND, S_IRWXG | S_IRWXU);
fd_in = open(argv[1], O_RDONLY);
#endif
if(!fd_out || !fd_in) {
cout << "Unable to open one of the given files"<<endl;
return 0;
}
char file_data1[4096];
char *file_data2 = (char*)memalign(4096, 4096);
/* Below vector declaration won't compile since aligned_allocator defined in xilinx lib.
vector<uint8_t, aligned_allocator<uint8_t>> file_data3(4096);
read(fd_in, file_data3, 4096);
int file_data3_len = strlen(file_data2);
*/
read(fd_in, file_data1, 4096); /* not work with O_DIRECT option, it returns 0 bytes */
int file_data1_len = strlen(file_data1);
/* works with O_DIRECT since memalign is used for creating the buffer */
read(fd_in, file_data2, 4096);
int file_data2_len = strlen(file_data2);
cout<<"read_4k_nonMemAlign, read_4k_memAlign: "<<file_data1_len<<", "<<file_data2_len<<endl;
char *data = (char*)malloc(sizeof(char)* 4096);
strcpy(data, "salkfalksfjslfnsdlfksdklfnsldkfslkdfskldfjskldngslkdgjsdngslkdgskldglksdglksdglsdglsdgklsdfgdfkg");
int data_len = strlen(data);
char *data2 = (char*)memalign(4096, 4096);
strcpy(data2, "12345678912345678912345678912345678912345678912345678912345678912345678912345678912345678912345");
int data2_len = strlen(data2);
ret = write(fd_out, data, data_len); /* fails with -1 if O_DIRECT enabled */
cout<<"data(malloc) write ret: "<<ret<<endl;
ret = write(fd_out, data2, 4096); /* write() works with O_DIRECT since data buffer is memaligned and given size is 4096 also aligned */
cout<<"data2(memalign) write ret: "<<ret<<endl;
ret = lseek(fd_out, data_len, SEEK_SET);
cout<<"seek ret1: "<<ret<<endl;
ret = write(fd_out, file_data2, 4096); /* write() works with O_DIRECT since buf is memaligned */
cout<<"write_ret2: "<<ret<<endl;
ret = lseek(fd_out, 0, SEEK_CUR);
cout<<"seek ret2: "<<ret<<endl;
struct iovec iov[4];
iov[0].iov_base = (char *) file_data2;
iov[0].iov_len = 4096;
iov[1].iov_base = (char *) data2;
iov[1].iov_len = 4096;//data2_len;
iov[2].iov_base = (char *) file_data1;
iov[2].iov_len = file_data1_len;
iov[3].iov_base = (char *) data;
iov[3].iov_len = data_len;
int total_len = iov[0].iov_len + iov[1].iov_len + iov[2].iov_len + iov[3].iov_len;
cout<<"total_len: "<<total_len<<" {"<<data_len<<", "<<data2_len<<", "<<file_data1_len<<", "<<file_data2_len<<"}"<<endl;
/* ret = writev(fd_out, &iov[0], 4); */
ret = writev(fd_out, &iov[0], 2);
cout<<"writev ret: "<<ret<<endl; /*writev() works fine when O_DIRECT flag removed in file open option. */
ret = lseek(fd_out, 4096+data2_len, SEEK_SET);
cout<<"seek ret: "<<ret<<endl;
ret = write(fd_out, data, 4096); /* write() works with O_DIRECT since buf is memaligned */
cout<<"ret: "<<ret<<endl;
close(fd_out);
close(fd_in);
return 0;
}
$g++ odirect_writev_prog.cpp -o odirect_writev_prog
$ ./odirect_writev_prog input.txt output_fd.txt
read_4k_nonMemAlign, read_4k_memAlign: 0, 4096
data(malloc) write ret: -1
data2(memalign) write ret: 4096
seek ret1: 96
write_ret2: -1
seek ret2: 96
total_len: 8288 {96, 95, 0, 4096}
writev ret: -1
seek ret: 4191
ret: -1