I am just trying to use readv() to fetch some data from a file. But always junk characters are being printed. I tried to allocate space to the iovec.iov_base but no luck there. And I even had a notion of why to use the readv function instead of just sticking to using the read function, which is much simpler and more readable. I am perplexed now to know why there is a need for the readv and writev functions.
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<unistd.h>
#include<fcntl.h>
#include<string.h>
#include<errno.h>
#include<sys/uio.h>
#include<sys/types.h>
#include<sys/stat.h>
#define MAX 50000
int main()
{
struct iovec data[2];
int i=0,fd;
for(i=0; i<3 ; i++ ) {
data[i].iov_len=MAX;
data[i].iov_base=(char*) malloc(MAX); //if this line is in comment, segmentation fault will occur.
/* data[i].iov_base=(char*) malloc(0); //This is also working ?*/
}
fd=open("/tmp/test",O_RDWR);
if(fd==-1){
printf("can't open the input file\n");
return 1;
}
readv(fd,data,3);
for(i=0; i<2 ; i++ ) {
printf("((%s))\n",(char*)data[i].iov_base);
}
}
You use the POSIX readv() and writev() functions ('scatter read' and 'gather write' — see also Wikipedia on Vectored I/O) when you're using file descriptors and need to group reads to or writes from a collection of different (non-contiguous) memory locations but you want the reading or writing to be done with a single function call.
For example, I have a program that needs to log some control data and a hex-dump of some binary data, but it would like to ensure that its writes are atomic. So, I have a function like this:
static void log_message(int log_fd, const char *elapsed, const char *tag, const char *buffer, ssize_t nbytes)
{
char hdrbuff[64];
struct iovec vector[3];
const char *data = format_image(buffer, nbytes);
snprintf(hdrbuff, sizeof(hdrbuff), "%s %s %6ld\n", elapsed, tag, (long)nbytes);
vector[0].iov_base = hdrbuff;
vector[0].iov_len = strlen(hdrbuff);
vector[1].iov_base = CONST_CAST(char *, data);
vector[1].iov_len = strlen(data);
vector[2].iov_base = "\n";
vector[2].iov_len = 1;
if (writev(log_fd, vector, 3) <= 0)
err_syserr("Failed to write log entry (%s: %ld)\n", tag, (long)nbytes);
}
It's a mild nuisance to need to write the newline, but the format_image() function can't add a stray newline. (It is a library function used elsewhere, and those other uses would be broken if it added an extra newline.) However, writev() allows me to write it all without changing the library functions, and maximizes the chance that there won't be any interleaving on the file. (In context, there's a second process using the same log file and same open file description, but the protocol is half-duplex, so there's only a small chance of temporarl overlap. However, using the scatter/gather I/O minimizes the chance of problems.)
I don't have an example of using readv() that I can remember, but you'd use it when you know that you have multiple fixed size blocks of data to read into non-contiguous memory locations.