Home arrow BrainDump arrow Page 3 - Advanced File I/O

Return values - BrainDump

If you're reading to take your understanding of Linux I/O file system calls to the next level, keep reading. This seven-part article series will show you everything from system calls to performance considerations. It is excerpted from chapter four of the book Linux System Programming: Talking Directly to the Kernel and C Library, written by Robert Love (O'Reilly, 2007; ISBN: 0596009585). Copyright © 2007 O'Reilly Media, Inc. All rights reserved. Used with permission from the publisher. Available from booksellers or direct from O'Reilly Media.

TABLE OF CONTENTS:
  1. Advanced File I/O
  2. Scatter/Gather I/O
  3. Return values
  4. readv() example
By: O'Reilly Media
Rating: starstarstarstarstar / 5
November 20, 2008

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement

On success, readv()andwritev()return the number of bytes read or written, respectively. This number should be the sum of allcount iov_lenvalues. On error, the system calls return-1, and seterrnoas appropriate. These system calls can experience any of the errors of theread()andwrite()system calls, and will, upon receiving such errors, set the sameerrnocodes. In addition, the standards define two other error situations.

First, because the return type is anssize_t, if the sum of allcount iov_lenvalues is greater thanSSIZE_MAX, no data will be transferred,-1will be returned, anderrnowill be set toEINVAL.

Second, POSIX dictates thatcountmust be larger than zero, and less than or equal toIOV_MAX, which is defined in<limits.h>. In Linux,IOV_MAXis currently1024. Ifcountis0, the system calls return0.* Ifcountis greater thanIOV_MAX, no data is transferred, the calls return-1, anderrnois set toEINVAL.


Optimizing the Count

During a vectored I/O operation, the Linux kernel must allocate internal data structures to represent each segment. Normally, this allocation would occur dynamically, based on the size of count. As an optimization, however, the Linux kernel creates a small array of segments on the stack that it uses ifcountis sufficiently small, negating the need to dynamically allocate the segments, and thereby providing a small boost in performance. This threshold is currently eight, so ifcountis less than or equal to8, the vectored I/O operation occurs in a very memory-efficient manner off of the processí kernel stack.

Most likely, you wonít have a choice about how many segments you need to transfer at once in a given vectored I/O operation. If you are flexible, however, and are debating over a small value, choosing a value of eight or less definitely improves efficiency.


writev( ) example

Letís consider a simple example that writes out a vector of three segments, each containing a string of a different size. This self-contained program is complete enough to demonstrate writev(), yet simple enough to serve as a useful code snippet:

  #include <stdio.h>
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <fcntl.h>
  #include <string.h>
  #include <sys/uio.h>

  int main ()
  {
          struct iovec iov[3];
          ssize_t nr;
          int fd, i;

          char *buf[] = {
                  "The term buccaneer comes from the word boucan.\n",
                  "A boucan is a wooden frame used for cooking meat.\n",
                  "Buccaneer is the West Indies name for a pirate.\n" };

          fd = open ("buccaneer.txt", O_WRONLY | O_CREAT | O_TRUNC);
         
if (fd == -1) {
                  perror ("open");
                  return 1; 
          }

          /* fill out three iovec structures */
         
for (i = 0; i < 3; i++) {
                  iov[i].iov_base = buf[i];
                  iov[i].iov_len = strlen (buf[i]);
          }

          /* with a single call, write them all out */
          nr = writev (fd, iov, 3);
          if (nr == -1) {
                 
perror ("writev");
                 
return 1;
          }
          printf ("wrote %d bytes\n", nr);

          if (close (fd)) {
                  perror ("close");
                  return 1;
         
}

          return 0;
  }

Running the program produces the desired result:

  $ ./writev
  wrote 148 bytes

As does reading the file:

  $ cat buccaneer.txt
  The term buccaneer comes from the word boucan.
  A boucan is a wooden frame used for cooking meat.
  Buccaneer is the West Indies name for a pirate.



 
 
>>> More BrainDump Articles          >>> More By O'Reilly Media
 

blog comments powered by Disqus
escort Bursa Bursa escort Antalya eskort
   

BRAINDUMP ARTICLES

- Apple Founder Steve Jobs Dies
- Steve Jobs` Era at Apple Ends
- Google's Chrome Developer Tool Updated
- Google's Chrome 6 Browser Brings Speed to th...
- New Open Source Update Fedora 13 is Released...
- Install Linux with Knoppix
- iPad Developers Flock To SDK 3.2
- Managing a Linux Wireless Access Point
- Maintaining a Linux Wireless Access Point
- Securing a Linux Wireless Access Point
- Configuring a Linux Wireless Access Point
- Building a Linux Wireless Access Point
- Migrating Oracle to PostgreSQL with Enterpri...
- Demystifying SELinux on Kernel 2.6
- Yahoo and Microsoft Create Ad Partnership

Developer Shed Affiliates

 


Dev Shed Tutorial Topics: