フリースタンディング環境

フリースタンディング環境（フリースタンディングかんきょう、）はC言語およびC++のプログラム実行環境の一種である。対義語はホスト環境（）。

 概要 
フリースタンディング環境は、オペレーティングシステム (OS) なしでプログラムを実行しなければいけない環境を指すCおよびC++の用語である。それぞれ国際標準化機構による規格ISO/IEC 9899およびISO/IEC 14882で規定されている。OSなしで実行するプログラムとは、組み込みシステム用のプログラムであったり、あるいはOSそのものであったりする。ホスト環境は逆にOSが存在することを想定しており、一般的なアプリケーションソフトウェアやミドルウェアを指す。ただし、フリースタンディング環境用としてつくられたプログラムはOSなしで動作する必要はない。OS上で動くフリースタンディング環境のプログラムとしてはデモシーン用のプログラムが代表的である。
実行環境を指定しない場合は、ホスト環境を対象にしていることがある。組み込みシステムではフリースタンディング環境を対象にすることもある。μITRONはオペレーティングシステムの一種であるが、フリースタンディング環境を選択しているシステムとして提供していることがある。TOPPERSプロジェクトのTRON系、OSEK系などで、模擬環境でないものは、フリースタンディング環境での利用を想定してソースコードを提供している。

 ホスト環境との違い 
フリースタンディング環境はOSから提供される機能が無いこと、プログラムを書き込む記憶領域が狭いことを想定し、ホスト環境で標準Cライブラリとして要求される関数は、Cでは一切要求せず、またC++では言語機能を実装するために必要とされる最低限のものしか要求しない。Cにおいてはを記述したヘッダーファイルのみを要求する（詳細は#制限を参照）。このため、Cにおいてはホスト環境で必要とされるランタイムライブラリを必要としない。

ホスト環境におけるmain関数は、プログラムを呼び出した親プログラム（OS等）の存在を想定しており、フリースタンディング環境のエントリーポイントとしては過剰である。またmainという名前が、main関数を呼び出すスタートアップコードを用意する上で邪魔になる（）ため、エントリーポイントはmain関数とは名前も形式も異なる関数にすることができるようになっている。

 制限 
フリースタンディング環境では言語仕様に以下の制限を受ける。
 エントリーポイントはmain関数である必要はなく、関数の型および名称は処理系定義となる。GCC の場合、デフォルトは void _start(void)。
 標準Cライブラリの大部分がサポートされない。フリースタンディング環境でもサポートされる標準ライブラリを以下に挙げる。
 C89の場合、float.h、limits.h、stdarg.h、stddef.h
 C95の場合、C89の標準ライブラリ、iso646.h
 C99の場合、C95の標準ライブラリ、stdbool.h、stdint.h
 C11の場合、C99の標準ライブラリ、stdalign.h、stdnoreturn.h
 C++03の場合、exception、limits、cstdarg、cstddef、cstdlib（abort、atexit、exitのみ）、new、typeinfo

 例 
この Hello world は GCC と Linux の組み合わせで動作する。gcc -ffreestanding -nostartfiles -static -o freestanding freestanding.c でコンパイルする。exit は各種終了処理を行う stdlib.h の関数のためフリースタンディング環境では使えないが、_exit は unistd.h で定義されたシステムコールを呼び出すだけの POSIX の関数のため GCC の Linux 用フリースタンディング環境でも使える。

#include <unistd.h>

void _start (void)
  {
  char msg [] = "Hello, world!\n" ;
  write (1, msg, sizeof msg) ;
  _exit (0) ;
  }

 標準Cライブラリなし 
類似概念として、コンパイラによっては標準Cライブラリなしでコンパイルすることも可能。例えば GCC の場合、-nostdlib オプションを指定することにより、標準Cライブラリを使わなくなる。さらに制限は厳しくなる。フリースタンディング環境同様、終了処理すら行わないため、コンパイル結果を Linux で動作させる場合、エントリーポイントの最後などで OS のシステムコールの exit を呼び出してプロセスを殺す必要があり、フリースタンディング環境の場合は、GCC と Linux の組み合わせの場合、_exit(0) で終了させられるが、標準Cライブラリがないため、そのコードは OS と CPU 種別依存のアセンブラで書かないといけない。スタックに関しては、Linux の場合、execve システムコールがスタックを準備するため、スタックは正しく準備された状態でエントリーポイントが呼び出される。

 例 
この標準Cライブラリ未使用の Hello world は GCC、Linux、x86-64 の組み合わせで動作する。gcc -nostdlib -fno-builtin -static -o nostdlib nostdlib.c でコンパイルする。
static void write (long fd, const void *buf, unsigned long count)
  {
  __asm__ volatile
    (
    "movq %0, %%rax \n\t"
    "movq %1, %%rdi \n\t"
    "movq %2, %%rsi \n\t"
    "movq %3, %%rdx \n\t"
    "syscall        \n\t"
    :
    : "i" (1), "r" (fd), "r" (buf), "r" (count)
    : "%rax", "%rdi", "%rsi", "%rdx"
    ) ;
  }

static void _exit (long status)
  {
  __asm__ volatile (
    "movq %0, %%rax \n\t"
    "movq %1, %%rdi \n\t"
    "syscall        \n\t" 
    :
    : "i" (60), "r" (status)
    : "%rax", "%rdi") ;
  }

void _start (void)
  {
  write (1, "Hello, world!\n", 14) ;
  _exit (0) ;
  }

 脚注 

 注釈 

 出典 

 関連項目 
 ホスト環境

Category:プログラミング
Category:組み込みシステム
Category:C言語
Category:C++