Open Source Web Development Tutorials - Dev Shed
Linux I/Oファイルのシステムコール
(2009/03/03公開)
readv()例
ここで、プログラムの1例を考えてみましょう。readv()システムコールを使い、前節で生成したテキストファイルからベクター型I/Oで読み出しを行うプログラムです。この例も自給的で、シンプルであると同時に完結しています。
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/uio.h>
int main ()
{
char foo[48], bar[51], baz[49];
struct iovec iov[3];
ssize_t nr;
int fd, i;
fd = open ("buccaneer.txt", O_RDONLY);
if (fd == -1) {
perror ("open");
return 1;
}
/* set up our iovec structures */
iov[0].iov_base = foo;
iov[0].iov_len = sizeof (foo);
iov[1].iov_base = bar;
iov[1].iov_len = sizeof (bar);
iov[2].iov_base = baz;
iov[2].iov_len = sizeof (baz);
/* read into the structures with a single call */
nr = readv (fd, iov, 3);
if (nr == -1) {
perror ("readv");
return 1;
}
for (i = 0; i < 3; i++)
printf ("%d: %s", i, (char *) iov[i].iov_base);
if (close (fd)) {
perror ("close");
return 1;
}
return 0;
}
前のプログラムを実行した後にこのプログラムを実行すると、以下が出力されます。
$ ./readv
0: The term buccaneer comes from the word boucan.
1: A boucan is a wooden frame used for cooking meat.
2: Buccaneer is the West Indies name for a pirate.
実装
readv()およびwritev()の素朴な実装は、シンプルなループとして、ユーザースペースで行えます。大体、以下のようになります。
#include <unistd.h>
#include <sys/uio.h>
ssize_t naive_writev (int fd, const struct iovec *iov, int count)
{
ssize_t ret = 0;
int i;
for (i = 0; i < count; i++) {
ssize_t nr;
nr = write (fd, iov[i].iov_base, iov[i].iov_len);
if (nr == -1) {
ret = -1;
break;
}
ret += nr;
}
return ret;
}
ありがたいことに、これはLinux実装ではありません。Linuxはreadv()およびwritev()をシステムコールとして実装し、内的にスキャタ/ギャザーI/Oを実行します。事実、Linuxカーネル内のすべてのI/Oはベクター型I/Oです。read()およびwrite()は、単一のセグメントから成るベクターのベクター型I/Oとして実行されます。
次回に続きます。
Copyright © 2008 Ziff Davis Enterprise, Inc.
Originally appearing in the U.S. Edition of Dev Shed. All Rights Reserved.








