Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Between read() and pread(), which way has more efficient? [closed]

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.

like image 318
Charles Avatar asked Dec 13 '13 07:12

Charles


1 Answers

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).

like image 102
Art Avatar answered Oct 20 '22 17:10

Art