diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2009-10-09 18:17:02 +0000 |
---|---|---|
committer | <> | 2013-09-20 15:53:04 +0000 |
commit | e6a27c468cae77ce26f6aa924b22bd39055892fe (patch) | |
tree | 5799c05ec62d99e582db411ed0fe5ffd2ba519db /libaio-0.3.109/man/io.3 | |
download | libaio-tarball-e6a27c468cae77ce26f6aa924b22bd39055892fe.tar.gz |
Imported from /home/lorry/working-area/delta_libaio-tarball/libaio_0.3.109.orig.tar.gz.HEADlibaio_0.3.109.origmaster
Diffstat (limited to 'libaio-0.3.109/man/io.3')
-rw-r--r-- | libaio-0.3.109/man/io.3 | 351 |
1 files changed, 351 insertions, 0 deletions
diff --git a/libaio-0.3.109/man/io.3 b/libaio-0.3.109/man/io.3 new file mode 100644 index 0000000..d910a68 --- /dev/null +++ b/libaio-0.3.109/man/io.3 @@ -0,0 +1,351 @@ +.TH io 3 2002-09-12 "Linux 2.4" Linux IO" +.SH NAME +io \- Asynchronous IO +.SH SYNOPSYS +.nf +.B #include <errno.h> +.sp +.br +.B #include <libio.h> +.sp +.fi +.SH DESCRIPTION +The libaio library defines a new set of I/O operations which can +significantly reduce the time an application spends waiting at I/O. The +new functions allow a program to initiate one or more I/O operations and +then immediately resume normal work while the I/O operations are +executed in parallel. + +These functions are part of the library with realtime functions named +.IR "libaio" +. They are not actually part of the +.IR "libc" +binary. +The implementation of these functions can be done using support in the +kernel. + +All IO operations operate on files which were opened previously. There +might be arbitrarily many operations running for one file. The +asynchronous I/O operations are controlled using a data structure named +.IR "struct iocb" +It is defined in +.IR "libio.h" +as follows. + +.nf + +typedef struct io_context *io_context_t; + +typedef enum io_iocb_cmd { + IO_CMD_PREAD = 0, + IO_CMD_PWRITE = 1, + + IO_CMD_FSYNC = 2, + IO_CMD_FDSYNC = 3, + + IO_CMD_POLL = 5, + IO_CMD_NOOP = 6, +} io_iocb_cmd_t; + +struct io_iocb_common { + void *buf; + unsigned __pad1; + long nbytes; + unsigned __pad2; + long long offset; + long long __pad3, __pad4; +}; /* result code is the amount read or -'ve errno */ + + +struct iocb { + void *data; + unsigned key; + short aio_lio_opcode; + short aio_reqprio; + int aio_fildes; + union { + struct io_iocb_common c; + struct io_iocb_vector v; + struct io_iocb_poll poll; + struct io_iocb_sockaddr saddr; + } u; +}; + + +.fi +.TP +.IR "int aio_fildes" +This element specifies the file descriptor to be used for the +operation. It must be a legal descriptor, otherwise the operation will +fail. + +The device on which the file is opened must allow the seek operation. +I.e., it is not possible to use any of the IO operations on devices +like terminals where an +.IR "lseek" +call would lead to an error. +.TP +.IR "long u.c.offset" +This element specifies the offset in the file at which the operation (input +or output) is performed. Since the operations are carried out in arbitrary +order and more than one operation for one file descriptor can be +started, one cannot expect a current read/write position of the file +descriptor. +.TP +.IR "void *buf" +This is a pointer to the buffer with the data to be written or the place +where the read data is stored. +.TP +.IR "long u.c.nbytes" +This element specifies the length of the buffer pointed to by +.IR "io_buf" +. +.TP +.IR "int aio_reqprio" +Is not currently used. +.TP +.B "IO_CMD_PREAD" +Start a read operation. Read from the file at position +.IR "u.c.offset" +and store the next +.IR "u.c.nbytes" +bytes in the +buffer pointed to by +.IR "buf" +. +.TP +.B "IO_CMD_PWRITE" +Start a write operation. Write +.IR "u.c.nbytes" +bytes starting at +.IR "buf" +into the file starting at position +.IR "u.c.offset" +. +.TP +.B "IO_CMD_NOP" +Do nothing for this control block. This value is useful sometimes when +an array of +.IR "struct iocb" +values contains holes, i.e., some of the +values must not be handled although the whole array is presented to the +.IR "io_submit" +function. +.TP +.B "IO_CMD_FSYNC" +.TP +.B "IO_CMD_POLL" +This is experimental. +.SH EXAMPLE +.nf +/* + * Simplistic version of copy command using async i/o + * + * From: Stephen Hemminger <shemminger@osdl.org> + * Copy file by using a async I/O state machine. + * 1. Start read request + * 2. When read completes turn it into a write request + * 3. When write completes decrement counter and free resources + * + * + * Usage: aiocp file(s) desination + */ + +#include <unistd.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/param.h> +#include <fcntl.h> +#include <errno.h> + +#include <libaio.h> + +#define AIO_BLKSIZE (64*1024) +#define AIO_MAXIO 32 + +static int busy = 0; // # of I/O's in flight +static int tocopy = 0; // # of blocks left to copy +static int dstfd = -1; // destination file descriptor +static const char *dstname = NULL; +static const char *srcname = NULL; + + +/* Fatal error handler */ +static void io_error(const char *func, int rc) +{ + if (rc == -ENOSYS) + fprintf(stderr, "AIO not in this kernel\n"); + else if (rc < 0 && -rc < sys_nerr) + fprintf(stderr, "%s: %s\n", func, sys_errlist[-rc]); + else + fprintf(stderr, "%s: error %d\n", func, rc); + + if (dstfd > 0) + close(dstfd); + if (dstname) + unlink(dstname); + exit(1); +} + +/* + * Write complete callback. + * Adjust counts and free resources + */ +static void wr_done(io_context_t ctx, struct iocb *iocb, long res, long res2) +{ + if (res2 != 0) { + io_error("aio write", res2); + } + if (res != iocb->u.c.nbytes) { + fprintf(stderr, "write missed bytes expect %d got %d\n", iocb->u.c.nbytes, res2); + exit(1); + } + --tocopy; + --busy; + free(iocb->u.c.buf); + + memset(iocb, 0xff, sizeof(iocb)); // paranoia + free(iocb); + write(2, "w", 1); +} + +/* + * Read complete callback. + * Change read iocb into a write iocb and start it. + */ +static void rd_done(io_context_t ctx, struct iocb *iocb, long res, long res2) +{ + /* library needs accessors to look at iocb? */ + int iosize = iocb->u.c.nbytes; + char *buf = iocb->u.c.buf; + off_t offset = iocb->u.c.offset; + + if (res2 != 0) + io_error("aio read", res2); + if (res != iosize) { + fprintf(stderr, "read missing bytes expect %d got %d\n", iocb->u.c.nbytes, res); + exit(1); + } + + + /* turn read into write */ + io_prep_pwrite(iocb, dstfd, buf, iosize, offset); + io_set_callback(iocb, wr_done); + if (1 != (res = io_submit(ctx, 1, &iocb))) + io_error("io_submit write", res); + write(2, "r", 1); +} + + +int main(int argc, char *const *argv) +{ + int srcfd; + struct stat st; + off_t length = 0, offset = 0; + io_context_t myctx; + + if (argc != 3 || argv[1][0] == '-') { + fprintf(stderr, "Usage: aiocp SOURCE DEST"); + exit(1); + } + if ((srcfd = open(srcname = argv[1], O_RDONLY)) < 0) { + perror(srcname); + exit(1); + } + if (fstat(srcfd, &st) < 0) { + perror("fstat"); + exit(1); + } + length = st.st_size; + + if ((dstfd = open(dstname = argv[2], O_WRONLY | O_CREAT, 0666)) < 0) { + close(srcfd); + perror(dstname); + exit(1); + } + + /* initialize state machine */ + memset(&myctx, 0, sizeof(myctx)); + io_queue_init(AIO_MAXIO, &myctx); + tocopy = howmany(length, AIO_BLKSIZE); + + while (tocopy > 0) { + int i, rc; + /* Submit as many reads as once as possible upto AIO_MAXIO */ + int n = MIN(MIN(AIO_MAXIO - busy, AIO_MAXIO / 2), + howmany(length - offset, AIO_BLKSIZE)); + if (n > 0) { + struct iocb *ioq[n]; + + for (i = 0; i < n; i++) { + struct iocb *io = (struct iocb *) malloc(sizeof(struct iocb)); + int iosize = MIN(length - offset, AIO_BLKSIZE); + char *buf = (char *) malloc(iosize); + + if (NULL == buf || NULL == io) { + fprintf(stderr, "out of memory\n"); + exit(1); + } + + io_prep_pread(io, srcfd, buf, iosize, offset); + io_set_callback(io, rd_done); + ioq[i] = io; + offset += iosize; + } + + rc = io_submit(myctx, n, ioq); + if (rc < 0) + io_error("io_submit", rc); + + busy += n; + } + + // Handle IO's that have completed + rc = io_queue_run(myctx); + if (rc < 0) + io_error("io_queue_run", rc); + + // if we have maximum number of i/o's in flight + // then wait for one to complete + if (busy == AIO_MAXIO) { + rc = io_queue_wait(myctx, NULL); + if (rc < 0) + io_error("io_queue_wait", rc); + } + + } + + close(srcfd); + close(dstfd); + exit(0); +} + +/* + * Results look like: + * [alanm@toolbox ~/MOT3]$ ../taio kernel-source-2.4.8-0.4g.ppc.rpm abc + * rrrrrrrrrrrrrrrwwwrwrrwwrrwrwwrrwrwrwwrrwrwrrrrwwrwwwrrwrrrwwwwwwwwwwwwwwwww + * rrrrrrrrrrrrrrwwwrrwrwrwrwrrwwwwwwwwwwwwwwrrrrrrrrrrrrrrrrrrwwwwrwrwwrwrwrwr + * wrrrrrrrwwwwwwwwwwwwwrrrwrrrwrrwrwwwwwwwwwwrrrrwwrwrrrrrrrrrrrwwwwwwwwwwwrww + * wwwrrrrrrrrwwrrrwwrwrwrwwwrrrrrrrwwwrrwwwrrwrwwwwwwwwrrrrrrrwwwrrrrrrrwwwwww + * wwwwwwwrwrrrrrrrrwrrwrrwrrwrwrrrwrrrwrrrwrwwwwwwwwwwwwwwwwwwrrrwwwrrrrrrrrrr + * rrwrrrrrrwrrwwwwwwwwwwwwwwwwrwwwrrwrwwrrrrrrrrrrrrrrrrrrrwwwwwwwwwwwwwwwwwww + * rrrrrwrrwrwrwrrwrrrwwwwwwwwrrrrwrrrwrwwrwrrrwrrwrrrrwwwwwwwrwrwwwwrwwrrrwrrr + * rrrwwwwwwwrrrrwwrrrrrrrrrrrrwrwrrrrwwwwwwwwwwwwwwrwrrrrwwwwrwrrrrwrwwwrrrwww + * rwwrrrrrrrwrrrrrrrrrrrrwwwwrrrwwwrwrrwwwwwwwwwwwwwwwwwwwwwrrrrrrrwwwwwwwrw + */ +.fi +.SH "SEE ALSO" +.BR io_cancel(3), +.BR io_fsync(3), +.BR io_getevents(3), +.BR io_prep_fsync(3), +.BR io_prep_pread(3), +.BR io_prep_pwrite(3), +.BR io_queue_init(3), +.BR io_queue_release(3), +.BR io_queue_run(3), +.BR io_queue_wait(3), +.BR io_set_callback(3), +.BR io_submit(3), +.BR errno(3) |