ファイルのランダムアクセス

システム・プログラム

                                       電子・情報工学系
                                       新城 靖
                                       <yas@is.tsukuba.ac.jp>

このページは、次の URL にあります。
http://www.hlla.is.tsukuba.ac.jp/~yas/coins/syspro-2000/2000-04-24 /lseek.html
あるいは、次のページから手繰っていくこともできます。
http://www.hlla.is.tsukuba.ac.jp/~yas/coins/
http://www.is.tsukuba.ac.jp/~yas/index-j.html

■lseek

UNIXでは、ファイルを read() したり write() したりするたびに、ファイル を読み書きする位置(先頭からのバイト数)が移動する。この位置は、シーク・ ポインタやファイル・ポインタと呼ばれる。(FILE *とは違うので注意。)

ファイルを先頭から順にアクセスするのではなく、ランダムにアクセスしたい 時には、まず読み書きしたい場所にシーク・ポインタを移動させる。これを行 うのが、lseek() システム・コールである。

off_t lseek(int fildes, off_t offset, int whence);
引数は、ファイル記述子、オフセット(バイト数)、移動方法である。移動方法 (whence)には、次の3種類のいずれかを指定する。
SEEK_SET
ファイルの先頭から offset バイト目に移動。
SEEK_CUR
現在の位置から offset バイト目に移動。
SEEK_END
ファイルの末尾から offset バイト目に移動。
ファイルの末尾から読むプログラムの例。

----------------------------------------------------------------------
   1:	
   2:	/*
   3:	        wtmp-last10.c -- /var/adm/wtmpの最後の10個を表示するプログラム
   4:	        ~yas/syspro1/file/wtmp-last10.c
   5:	        $Header: /home/lab2/OS/yas/syspro1/file/RCS/wtmp-last10.c,v 1.3 1998/05/11 15:09:23 yas Exp $
   6:	        Start: 1995/03/06 09:01:09
   7:	*/
   8:	
   9:	#include <stdio.h>      /* FILE, NULL, stderr */
  10:	#include <utmp.h>       /* struct utmp */
  11:	#include <sys/types.h>  /* open(),lseek() */
  12:	#include <sys/stat.h>   /* open() */
  13:	#include <fcntl.h>      /* open() */
  14:	#include <unistd.h>     /* lseek() */
  15:	
  16:	void wtmp_last10_print_file();
  17:	void utmp_print( struct utmp *u );
  18:	void print_char_array( char a[], int len );
  19:	
  20:	main()
  21:	{
  22:	        wtmp_last10_print_file();
  23:	}
  24:	
  25:	void wtmp_last10_print_file()
  26:	{
  27:	    struct utmp  entry;
  28:	    int fd, i ;
  29:	    off_t offset ;
  30:	
  31:	        if( (fd = open(  WTMP_FILE, O_RDONLY )) == -1 )
  32:	        {
  33:	            perror( WTMP_FILE );
  34:	            exit( -1 );
  35:	        }
  36:	        for( i=-1 ; i>-10; i-- )
  37:	        {
  38:	            offset = sizeof(struct utmp)*i ;
  39:	
  40:	            if( lseek( fd, offset, SEEK_END ) == -1 )
  41:	            {
  42:	                perror("lseek");
  43:	                exit( -1 );
  44:	            }
  45:	            if( read(fd, &entry, sizeof(entry)) != sizeof(entry) )
  46:	            {
  47:	                perror("read");
  48:	                exit( -1 );
  49:	            }
  50:	            utmp_print( &entry );
  51:	        }
  52:	        close( fd );
  53:	}
  54:	
  55:	void utmp_print( struct utmp *u )
  56:	{
  57:	        print_char_array( u->ut_user, sizeof(u->ut_user) );
  58:	        print_char_array( u->ut_id, sizeof(u->ut_id) );
  59:	        print_char_array( u->ut_line, sizeof(u->ut_line) );
  60:	        printf("%6d ", u->ut_pid );
  61:	        printf("%6d ", u->ut_type );
  62:	        printf("%s",ctime(&u->ut_time) );
  63:	}
  64:	
  65:	void print_char_array( char a[], int len )
  66:	{
  67:	    int i ;
  68:	        for( i=0 ; i<len && a[i] ; i++ )
  69:	            putchar( a[i] );
  70:	        for( ; i<len ; i++ )
  71:	            putchar(' ');
  72:	        putchar(' ');
  73:	}
  74:	
  75:	/* ------------------------ utmp-print.c ------------------------ */
  76:	static char rcsid[] =
  77:	"$Header: /home/lab2/OS/yas/syspro1/file/RCS/wtmp-last10.c,v 1.3 1998/05/11 15:09:23 yas Exp $" ;
----------------------------------------------------------------------

実行例。
----------------------------------------------------------------------
% ./wtmp-last10 [←]
yas      q4   ttyq4         16360      7 Tue May 12 00:07:23 1998
rlogin   q4   ttyq4         16360      6 Tue May 12 00:07:23 1998
telnet   q3   ttyq3         16201      8 Mon May 11 23:47:57 1998
e96????  q3   ttyq3         16202      7 Mon May 11 23:43:51 1998
telnet   q3   ttyq3         16202      6 Mon May 11 23:43:47 1998
a???     q1   ttyq1         16110      7 Mon May 11 23:33:52 1998
telnet   q1   ttyq1         16110      6 Mon May 11 23:33:49 1998
telnet   q1   ttyq1         16063      8 Mon May 11 23:33:43 1998
a???     q1   ttyq1         16064      7 Mon May 11 23:08:18 1998
% last | head -10 [←]
yas      ttyq4        hlla-gw.hlla.is.tsuku Tue May 12 00:07   still logged in
e96????  ttyq3        130.158.125.185       Mon May 11 23:43 - 23:47  (00:04)
a???     ttyq1        AMIcc-01p08.ppp.xxxxx Mon May 11 23:33   still logged in
a???     ttyq1        AMIcc-01p08.ppp.xxxxx Mon May 11 23:08 - 23:33  (00:25)
k?????   ttyq0        balsam-serv           Mon May 11 22:31   still logged in
t????    ttyq1        adonis7               Mon May 11 21:49 - 21:49  (00:00)
to????   ttyq0        icho.ipe.tsukuba.ac.j Mon May 11 21:38 - 22:01  (00:23)
m????    ttyq0        azalea11              Mon May 11 21:06 - 21:17  (00:11)
to????   ttyq4        icho.ipe.tsukuba.ac.j Mon May 11 19:06 - 19:09  (00:03)
m????    ttyq4        azalea11              Mon May 11 18:01 - 18:07  (00:05)
% []
----------------------------------------------------------------------

■fseek

高水準入出力ライブラリ を使う時には、lseek() で はなく fseek() を使う。

■mmap

mmap() システム・コールを使うと、ファイルをメモリに 張り付けることができる。これを使うと、ファイルの内容を全てある番地から メモリに読み込んだように扱うことができる。実際には、アクセスした部分だ けしかメモリに読み込まれない。

★練習問題31 tail プログラム

lseek() システム・コール、mmap() システム・コール、 または、fseek() ライブラリを使って、tail コマンドに似たコマンドを作り なさい。
↑[もどる] ←[4月17日] ・[4月24日] →[5月01日] [課題]
Last updated: 2000/04/23 02:04:03
Yasushi Shinjo / <yas@is.tsukuba.ac.jp>