The following are the declarations of read
and pread
:
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
ssize_t pread(int fd, void *buf, size_t count, off_t offset);
We all know that they have almost the same functionality, but which one is more efficient?
Add the use cases: 1.Scan a large file. 2.Random read one large file.
Depends on how you define "efficient". If you're asking about performance the difference is microscopic. So use the one that solves the problem for you. In many cases pread
is the only option when you're dealing with threads reading from a database or such. In other cases read
is the only sensible option. And the question is a little bit unfair since pread
does more than read
. A fair comparison would be lseek
+ read
which will definitely be slower than just pread
.
Let's look at the differences in implementation of both in an operating system source I had available. I cut out the exact same code from both functions to highlight the differences. There's much more code than this.
This is part of pread
:
vp = (struct vnode *)fp->f_data;
if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO ||
(vp->v_flag & VISTTY)) {
return (ESPIPE);
}
offset = SCARG(uap, offset);
if (offset < 0 && vp->v_type != VCHR)
return (EINVAL);
return (dofilereadv(p, fd, fp, &iov, 1, 0, &offset, retval));
This is the equivalent part of read
:
return (dofilereadv(p, fd, fp, &iov, 1, 0, &fp->f_offset, retval));
So, pread
does some extra checks to make sure that we're not trying to seek on a pipe, fifo, tty, etc. And it checks that we're not reading a negative offset from a character device. It also doesn't update the offset in the file pointer (fp
in the code).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With