Skip to content
Published on

[オペレーティングシステム] 13. ファイルシステムインターフェース

Authors

ファイルシステムインターフェース

ファイルシステムはオペレーティングシステムで最も目に見える部分の一つです。 ユーザーがデータを保存・管理するための論理的なインターフェースを提供します。 この記事では、ファイルの概念、アクセス方法、ディレクトリ構造、そしてファイル保護メカニズムを解説します。


1. ファイルの概念

ファイルとは、補助記憶装置に記録された関連情報の名前付きコレクションです。

ファイル属性

属性説明
名前(Name)人が読める識別子
識別子(Identifier)ファイルシステム内の一意番号(inode番号等)
タイプ(Type)拡張子またはマジックナンバーで識別
位置(Location)デバイス上の物理的位置ポインタ
サイズ(Size)現在のファイルサイズ(バイト、ブロック)
保護(Protection)読み取り、書き込み、実行権限
タイムスタンプ作成、変更、アクセス時間
所有者(Owner)ファイルを所有するユーザー

ファイル操作

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
    // 1. 파일 생성 및 열기
    int fd = open("example.txt", O_CREAT | O_WRONLY | O_TRUNC, 0644);
    if (fd == -1) {
        perror("open failed");
        return 1;
    }

    // 2. 파일 쓰기
    const char *data = "Hello, File System!";
    write(fd, data, 19);

    // 3. 파일 닫기
    close(fd);

    // 4. 읽기 모드로 다시 열기
    fd = open("example.txt", O_RDONLY);

    // 5. 파일 읽기
    char buffer[256];
    ssize_t bytes_read = read(fd, buffer, sizeof(buffer) - 1);
    buffer[bytes_read] = '\0';
    printf("읽은 내용: %s\n", buffer);

    // 6. 파일 위치 이동 (seek)
    lseek(fd, 0, SEEK_SET);  // 파일 시작으로 이동

    // 7. 파일 닫기
    close(fd);

    // 8. 파일 삭제
    unlink("example.txt");

    return 0;
}

オープンファイルテーブル

オペレーティングシステムは開いたファイルを管理するためにテーブルを維持します。

プロセスA                    プロセスB
┌──────────────┐             ┌──────────────┐
│ fdテーブル    │             │ fdテーブル    │
0: stdin     │             │ 0: stdin     │
1: stdout    │             │ 1: stdout    │
2: stderr    │             │ 2: stderr    │
3: ─────────┐│             │ 3: ─────────┐│
└─────────────┘│             └─────────────┘│
               ↓                            ↓
        ┌──────────────────────────────────────┐
        │   システム全体オープンファイルテーブル  │
        │ ┌─────────────────────────────────┐   │
        │ │ ファイルA: offset=100, refCount=1│   │
        │ │ ファイルB: offset=0,   refCount=2│ ← 共有│
        │ └─────────────────────────────────┘   │
        └──────────────────────────────────────┘
              ┌──────────────────┐
              │   inodeテーブル   │
              │ (ディスク位置等)│
              └──────────────────┘

2. アクセス方法

順次アクセス(Sequential Access)

ファイルの先頭から末尾まで順番にアクセスします。テープモデルに基づきます。

┌───┬───┬───┬───┬───┬───┬───┐
0123456 │  ← レコード
└───┴───┴───┴───┴───┴───┴───┘
     現在位置ポインタ
     (前進またはリワインド)
// 순차 접근 예시
FILE *fp = fopen("log.txt", "r");
char line[1024];

// 처음부터 끝까지 순서대로 읽기
while (fgets(line, sizeof(line), fp) != NULL) {
    printf("%s", line);
}

// 되감기 (처음으로)
rewind(fp);
fclose(fp);

直接アクセス(Direct / Random Access)

任意の位置に直接アクセスできます。ディスクモデルに基づきます。

┌───┬───┬───┬───┬───┬───┬───┐
0123456 │  ← ブロック番号
└───┴───┴───┴───┴───┴───┴───┘
  ↑               ↑       ↑
  直接アクセス可能(どのブロックでも)
// 직접 접근 예시 - 데이터베이스의 레코드 접근
#include <stdio.h>

typedef struct {
    int id;
    char name[50];
    double balance;
} Account;

// 특정 레코드 번호로 직접 접근
Account read_account(FILE *fp, int record_num) {
    Account acc;
    // 레코드 번호로 오프셋 계산하여 직접 이동
    fseek(fp, record_num * sizeof(Account), SEEK_SET);
    fread(&acc, sizeof(Account), 1, fp);
    return acc;
}

void write_account(FILE *fp, int record_num, Account *acc) {
    fseek(fp, record_num * sizeof(Account), SEEK_SET);
    fwrite(acc, sizeof(Account), 1, fp);
}

インデックスアクセス

インデックスファイルを通じてデータファイルのレコードを検索する方式です。

インデックスファイル:                データファイル:
┌──────┬─────────┐              ┌─────────────────┐
│ キー │ ポインタ │              │ レコード 0├──────┼─────────┤        ┌───→│ Smith, 1000Kim  │ ──────────────┐  │    ├─────────────────┤
Lee  │ ────────────┐ │  │    │ レコード 1Park │ ──────┐     │ │  │    │ Lee, 2000Smith│ ──────┼─────┼─┼──┘    ├─────────────────┤
└──────┴───────┘     │ │       │ レコード 2                     │ └──────→│ Kim, 3000                     │         ├─────────────────┤
                     └────────→│ レコード 3Park, 4000                               └─────────────────┘

3. ディレクトリ構造

ディレクトリはファイル名を対応するメタデータにマッピングするテーブルです。

単一レベルディレクトリ

┌──────────────────────────────────────┐
│           ルートディレクトリ           │
│                                      │
│  cat  bo  a   test  data  mail  hex  │
│   │   │   │    │     │     │     │   │
│   ○   ○   ○    ○     ○     ○     ○   │
└──────────────────────────────────────┘
すべてのファイルが同じディレクトリに存在
→ 名前衝突問題、グループ化不可

2段階ディレクトリ

┌────────────────────────────────────┐
│        マスターファイルディレクトリ   │
│                                    │
│   user1        user2       user3   │
│     │            │           │     │
│  ┌──┴──┐     ┌──┴──┐    ┌──┴──┐  │
│  │ UFD │     │ UFD │    │ UFD │  │
│  │cat a│     │cat b│    │  a  │  │
│  └─────┘     └─────┘    └─────┘  │
└────────────────────────────────────┘
ユーザーごとに別のディレクトリ → 名前衝突解決

ツリー構造ディレクトリ

現代のファイルシステムの基本構造です。

              / (ルート)
            ╱   │    ╲
         home  etc    var
        ╱   ╲   │      │
     user1 user2 passwd log
      │      │          │
    docs   code      syslog
    │  │     │
  a.txt b.txt main.c
# 트리 구조에서의 경로
# 절대 경로: 루트부터 시작
/home/user1/docs/a.txt

# 상대 경로: 현재 디렉토리 기준
# 현재 디렉토리가 /home/user1 일 때
docs/a.txt

非循環グラフディレクトリ

ファイルやディレクトリを複数の場所から共有できます。(ハードリンク、シンボリックリンク)

         /
      home
     ╱    ╲
  user1   user2
    │       │
  shared ──┘  (シンボリックリンクまたはハードリンク)
  project
// 하드 링크 생성 (같은 inode를 가리킴)
#include <unistd.h>

int main() {
    // 하드 링크: 동일한 inode에 대한 새 이름
    link("/home/user1/shared/project",
         "/home/user2/project");

    // 심볼릭(소프트) 링크: 경로명을 가리키는 특수 파일
    symlink("/home/user1/shared/project",
            "/home/user2/project_link");

    return 0;
}

ハードリンク vs シンボリックリンク

特性ハードリンクシンボリックリンク
inode原本と同一別のinode
ファイルシステム間不可可能
ディレクトリリンク不可(ループ防止)可能
原本削除時データ保持壊れたリンク
サイズディレクトリエントリパス名サイズ

4. ファイル共有

マルチユーザー環境でのファイル共有

ユーザーA(所有者)
    ├── ファイルX(読み/書き/実行)
    │      │
    │      ├── ユーザーB(グループ)→ 読み/実行
    │      │
    │      └── その他のユーザー → 読みのみ
    └── グループ: developers

ファイルロック(File Locking)

#include <fcntl.h>
#include <unistd.h>

int main() {
    int fd = open("shared_data.txt", O_RDWR);

    struct flock lock;
    lock.l_type   = F_WRLCK;    // 쓰기 잠금
    lock.l_whence = SEEK_SET;
    lock.l_start  = 0;          // 시작 오프셋
    lock.l_len    = 0;          // 전체 파일

    // 잠금 획득 (다른 프로세스는 대기)
    fcntl(fd, F_SETLKW, &lock);

    // 파일 작업 수행
    write(fd, "critical data", 13);

    // 잠금 해제
    lock.l_type = F_UNLCK;
    fcntl(fd, F_SETLK, &lock);

    close(fd);
    return 0;
}

ロックの種類

種類説明互換性
共有ロック(Read Lock)複数プロセスが同時読み取り可能共有ロック同士互換
排他ロック(Write Lock)1つのプロセスのみアクセス可能すべてのロックと非互換
強制ロック(Mandatory)カーネルが強制適用システム依存
勧告ロック(Advisory)プロセスが自発的に遵守POSIXデフォルト

5. 保護(Protection)

アクセス制御リスト(ACL)

ファイル: /project/secret.txt

ACL (Access Control List):
┌──────────┬─────────────────┐
│ ユーザー │ 権限             │
├──────────┼─────────────────┤
│ admin    │ 読み、書き、実行 │
│ user1    │ 読み、書き       │
│ user2    │ 読み             │
│ group:dev│ 読み、実行       │
│ others   │ (なし)         │
└──────────┴─────────────────┘

UNIX権限モデル

UNIXは所有者(owner)、グループ(group)、その他(others)の3つのカテゴリと読み(r)、書き(w)、実行(x)の3つの権限を組み合わせます。

$ ls -l example.txt
-rwxr-x--- 1 user1 developers 1024 Mar 19 10:00 example.txt

 │││││││││
 │├┤├┤├┤
 │ │ │ └── others:  --- (権限なし)
 │ │ └──── group:   r-x (読み、実行)
 │ └────── owner:   rwx (読み、書き、実行)
 └──────── ファイルタイプ: - (通常ファイル)
#include <sys/stat.h>

int main() {
    // 8진수로 권한 설정
    // 7=rwx, 5=r-x, 0=---
    chmod("example.txt", 0750);

    // 소유자 변경
    chown("example.txt", 1000, 100);  // uid=1000, gid=100

    // 새 파일 생성 시 기본 권한 마스크
    umask(0022);  // 기본 권한에서 group/others의 쓰기 제거

    return 0;
}

特殊権限ビット

ビットシンボル効果
setuids(所有者実行)実行時にファイル所有者の権限で実行
setgids(グループ実行)実行時にファイルグループの権限で実行
sticky bitt(その他実行)ディレクトリ内のファイルは所有者のみ削除可能
# setuid 설정 예시 (passwd 명령어)
# 일반 사용자도 root 소유 파일을 수정 가능
$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 68208 ... /usr/bin/passwd
    ^
    setuid 비트 설정됨

# sticky bit 설정 예시 (/tmp 디렉토리)
$ ls -ld /tmp
drwxrwxrwt 15 root root 4096 ... /tmp
         ^
         sticky bit 설정됨

6. まとめ

  • ファイルの概念: 名前付き情報の集合で、属性と操作が定義されている
  • アクセス方法: 順次(テープモデル)、直接(ディスクモデル)、インデックスアクセス
  • ディレクトリ構造: 単一レベルから非循環グラフまで発展。現代のシステムはツリー+リンク
  • ファイル共有: ロックメカニズム(共有/排他、強制/勧告)による同時アクセス管理
  • 保護: UNIX権限モデル(rwx、owner/group/others)とACLによるアクセス制御
クイズ:ファイルシステムインターフェース

Q1. ハードリンクとシンボリックリンクの違いを説明してください。

A1. ハードリンクは原本ファイルと同じinodeを共有するため、原本が削除されてもデータにアクセスできます。 シンボリックリンクは別のinodeを持ちパス名を保存するため、原本が削除されると壊れたリンクになります。 ハードリンクはファイルシステム境界を越えられず、ディレクトリに適用できませんが、 シンボリックリンクは両方とも可能です。

Q2. UNIXファイル権限0754はどのような意味ですか?

A2. 所有者(7=rwx):読み、書き、実行すべて可能。 グループ(5=r-x):読みと実行可能、書き不可。 その他(4=r--):読みのみ可能。

Q3. sticky bitの用途は何ですか?

A3. sticky bitがディレクトリに設定されると、そのディレクトリ内のファイルは ファイルの所有者、ディレクトリの所有者、またはrootのみが削除できます。 /tmpディレクトリに設定されており、すべてのユーザーがファイルを作成できますが、 他のユーザーのファイルは削除できないようにしています。