- 追加された行はこの色です。
- 削除された行はこの色です。
* ファイルシステムとタイムスタンプ [#e41c69af]
** そもそもの疑問 [#y52839a4]
Linux で FAT フォーマットの SD カードを mount し,ls -l でディレクトリの中身を覗いていて
> 何で Linux 上で FAT filesystem のタイムスタンプが正常に表示できるんだろう
と,すごく気になりだしたのである.
というわけで追っかけてみた.
** epoch と timezone [#abe51c4f]
「何でそんなこと気にするんだ」と話のとっかかりとして,まずはここらへんから.
まず,epoch とは「1970 年 1 月 1 日 UTC からの経過秒数」のことである.
UTC とは協定世界時のことで,サマータイムが適用されていないグリニッジ標準時と同じ時刻である.
UNIX では,カーネルが持っている時計の現在時刻を time(2) システムコールで取得することができる.
次に timezone について.
timezone とは要するに「現地時間の UTC からの時差」である.
たとえば日本時間は,UTC に対して 9 時間進んだ時刻である.
** ls -l コマンドを実行すると… [#meee1fa6]
まず,ディレクトリ内のファイル名・ディレクトリ名の一覧を取得する.
そして,各ファイル・ディレクトリに対して stat(2) システムコールを発行する.
stat(2) が返す構造体の形式は以下のとおりである.
struct stat {
dev_t st_dev; /* ファイルがあるデバイスの ID */
ino_t st_ino; /* inode 番号 */
mode_t st_mode; /* アクセス保護 */
nlink_t st_nlink; /* ハードリンクの数 */
uid_t st_uid; /* 所有者のユーザ ID */
gid_t st_gid; /* 所有者のグループ ID */
dev_t st_rdev; /* デバイス ID (特殊ファイルの場合) */
off_t st_size; /* 全体のサイズ (バイト単位) */
blksize_t st_blksize; /* ファイルシステム I/O での
ブロックサイズ */
blkcnt_t st_blocks; /* 割り当てられたブロック数 */
time_t st_atime; /* 最終アクセス時刻 */
time_t st_mtime; /* 最終修正時刻 */
time_t st_ctime; /* 最終状態変更時刻 */
};
ファイルのタイムスタンプは time_t 型であり,つまり epoch 形式である.
この epoch 形式を現地時間の「年月日時分秒」に変換するのは libc の仕事である.
libc は /etc/localtime ファイルにある時差情報に基づいて epoch を現地時間に変換する.
かくして ls -l のタイムスタンプは現地時間で表示されるわけである.
あ,そうそう,ext3 などの UNIX / Linux native のファイルシステムでは,タイムスタンプは epoch 形式のまま HDD に保存されている.
HDD
epoch
|
|
--------|----------
kernel |
|
--------|---------- stat(2)
user |
+---- /etc/localtime
#
#
V
yy/mm/dd hh:mm:ss JST
** FAT の場合 [#mea1bd8a]
FAT filesystem の場合,少々話が違ってくる.
「[http://www.geocities.co.jp/SiliconValley-PaloAlto/2038/fat.html FAT FS フォーマットの実装についての覚え書き]」あたりを見てみると,FAT では「年月日時分秒」形式で時刻が保存されているが,''timezone という概念は存在しない''.
つまり「どこの現地時間か UTC かは知らないけど,そういう時刻」ということでタイムスタンプが打たれているわけである.
しかし,strace をかけてみても ls -l ではやはり stat(2) でファイル情報を取得していており,ext3 上のディレクトリの処理と一緒である.
ということは,
> カーネル内部で年月日時分秒形式を epoch 形式に変換している
ということになる.
ところが,これには timezone 情報が必要であるのだが,timezone 情報は /etc/localtime ファイルに保存されている.
/etc/* のファイルは,ユーザランドプログラムやライブラリが設定ファイルを慣習的に配置しているだけであり,カーネルがここのファイルを直接参照することは,普通はない.
(つづく)