panda's tech note

Advent Calendar 2019: advfs

Day 1: 環境の構築

まず,最初に開発環境を構築します。今回はFUSEなので,ホストOSは macOS か Linux (たぶん Windows でも大丈夫) のどちらでもいいのですが,FUSEの使い方を間違えるとホストOSごとクラッシュすることもあるので今年も Docker に実行・テストを行う開発環境を作っていきます。言語はCで,構成ツールには, automake/autoconf を使います。

Dockerfile とビルドに必要な初期ファイルの定義

まず,ビルド・テスト環境を定義する Dockerfile を書きます。Ubuntu 18.04 をベースイメージとして, libfuse-dev および各種ビルドツール(build-essential, automake, autoconf, pkg-config)をインストールします。ソースコードは src に置き,これをコンテナの /usr/src にコピーしてビルドするようにします。今回は環境構築なので,最後に bash を実行するだけとします。 Dockerfile は以下の通りです。

FROM ubuntu:18.04

MAINTAINER Hirochika Asai <panda@jar.jp>

## Install build-essential and fuse
RUN apt-get update
RUN apt-get install -y --no-install-recommends build-essential fuse libfuse-dev vim-common automake autoconf pkg-config

COPY src /usr/src
WORKDIR /usr/src
RUN ./autogen.sh
RUN ./configure
RUN make clean all

## Execute bash
CMD ["bash"]

ソースコードは src/main.c に以下のように printf を1行追加した main() 関数を定義します。ここで,FUSEのバージョンを固定するために <fuse.h> を読み込む前に FUSE_USE_VERSION でバージョンを指定します。今回は 2.8 を指定しています。

#define FUSE_USE_VERSION  28

#include "config.h"
#include <fuse.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <stdint.h>

/*
 * main
 */
int
main(int argc, char *argv[])
{
    printf("To implement advfs.\n");
    return 0;
}

また,Makefile.am, configure.ac, fuse-advfs.pc.in にはビルド関係の定義を書きます。その他,AUTHORS, ChangeLog, NEWS, READMEautomake/autoconf/pkg-config に必須ファイルであるため,空ファイルを追加しています。

これらのファイルは,以下を参照してください。

最後に Docker を起動するための docker-compose.yml を書きます。1コンテナで完結するので,特に docker-compose の利点は享受できないと思いますが,今後ネットワークファイルシステムのように複数コンテナで試験するときに便利になるので,今のうちに docker-compose を使うようにします。

version: '3'

services:
  advfs:
    build:
      context: ./
      dockerfile: Dockerfile
    devices:
      - /dev/fuse:/dev/fuse:rwm
    cap_add:
      - SYS_ADMIN

fuse はカーネルモジュールとして実装されているため,これを Docker コンテナから使うには上記のように SYS_ADMIN capability とを追加し,/dev/fuse デバイスを read/write/mknod 権限付きでコンテナにアタッチします。

コンテナの起動とテストプログラムの実行

まず,

$ docker-compose build

で上記で定義したDockerコンテナのビルドを行います。

ビルド後,

$ docker-compose run advfs

でコンテナが起動できます。 Dockerfile の最後の行に書いた bash が起動するので,ここで, src/main.c プログラムのコンパイル後のバイナリである ./advfs を実行すると,以下のように src/main.c で書いた printf() 内のメッセージが表示されます。

# ./advfs
To implement advfs.

今日のまとめと明日の予定

今日は開発・ビルド・実行環境が構築をしました。明日からは自作ファイルシステムを実装していこうと思います。