本連載もついに最終回。今回はTCP/IPを実装し、最終目標である「ソフトウェア完全自作のWebサーバ」を動作させる。その手順を詳しく紹介する。
本連載では、学習用・ホビー用の組み込みOS「KOZOS」を使ってマイコンボード上でいろいろと実験をしつつ、フルスクラッチで組み込みOSを自作していく過程を体験してみます。
前回「『ping』によるネットワーク通信機能を実装してみよう」では、ネットワーク通信を実装し、「ping」による通信を動作させました。
今回は、ついに最終目標の「Webサーバ」を動作させます。それは、ブートローダーからOSのカーネル、TCP/IPスタック、HTTPサーバアプリケーションまで、ソフトウェア完全自作のWebサーバです。そして、ソースコード量はブートローダーとOSモジュール、アプリケーションの全てを含めても、“6000行”を切っています。たった数千行のソースコードで、ソフトウェア完全自作のWebサーバがマイコンボード上で動くと聞いて、何だかワクワクしてきませんか?
本連載では、秋月電子通商の「H8/3069Fネット対応マイコンLANボード(完成品)」(図1)を利用します。マイコンボードの詳細については連載第1回を参照してください。ちなみにこのボードは、3750円(税込)と非常に安価で入手性も良く、個人のホビー用途にオススメです。
今回紹介するソースコードは、著書「12ステップで作る組込みOS自作入門」とKOZOSのWebサイトの内容に、“プラスα”でネットワーク機能を追加したものです。その内容は、http://kozos.jp/kozos/h8_2_06.htmlで公開しています。今回はこちらをダウンロードして使用してください(補足)。
また、開発環境の構築方法は連載第1回で説明してありますので、興味のある方はぜひソースコードをビルドし、実機での動作を試してみてください(幾つか対応は必要となりますが、シミュレータ上でも動作させることが可能です)。
なお、本連載で利用する組み込みOS、KOZOSのカーネル構造については、著書「12ステップで作る組込みOS自作入門」に詳しい説明がありますので、そちらも参考にしてみてください。
Webサーバの動作のためには、まずはTCP/IPスタックの実装が必要です。前回までの内容でIP通信はできていますから、TCPによるやりとり、つまり「プロトコル」が実装できればいいことになります。
TCP/IPは“コネクション型”のプロトコルです。接続側が「SYNパケット」を送信し、受信側がそれに対して「SYN+ACKパケット」で応答します。さらに、接続側がそれを受けて「ACK」を送信することで、コネクションが確立されます。この一連の流れを図2に示します。
コネクションの確立後は転送したいデータを任意に送信し、受信側は応答としてやはりACKを返します。これを簡単な図にすると、図3のようなイメージになります。実際には、データの順番を保証するためのシーケンス番号の制御なども含まれます。
ここまでできれば、取りあえずコネクションを確立してデータの転送を行うことは可能です。さらに、TCP/IPはスライディングウィンドウや輻輳(ふくそう)制御などのさまざまな機能を持っており、ネットワークの帯域や遅延に合わせて動的にチューニングを行います。ただし、単純なデータ転送だけであれば、こうした機能がなくても動作可能です。
KOZOSの開発ポリシーは「組み込みOSが持っているような一通りの機能を、おのおの数百行程度の少ないソースコード量でサンプル実装してみる」ですので、本稿でも難しい付加機能のことは考えず、取りあえず実装してみましょう。
Webサーバとして動作させるためには、HTTPによる接続を受け付けて応答するサーバアプリケーションが必要です。
HTTPは“80番ポート”で待ち受けし、接続したらWebブラウザ側で「GET /index.html」のように取得したいファイルを送信すると、サーバ側が応答でそのファイルを送ってくる……という単純なプロトコルです。このため、TCP/IP通信さえできてしまえば、Webサーバを実装することはそれほど難しいことではありません。
例えば実験として、HTTPプロトコルを手動で発行してみましょう(リスト1)。
hiroaki@red:~>% telnet xxx.xxx.xxx 80 ←telnetでWebサーバの80番ポートに接続 ……(中略)…… Connected to kozos.jp. Escape character is '^]'. GET / HTTP/1.0 ←GETメソッドを手作業で入力 ←空行を入力するとWebサーバから応答が返ってくる HTTP/1.1 200 OK Date: Sat, 21 Jan 2012 00:33:40 GMT ……(中略)…… Connection closed by foreign host. hiroaki@red:~>%
リスト1 HTTPによるGETメソッドの発行 |
リスト1は、TelnetクライアントでWebサーバの80番ポートに接続し、手作業でHTTPのGETメソッドを発行してみたところです。接続後にGETメソッドの一文を手で書き、(HTTPでは空行がヘッダ部とメッセージ部の区切りを表すため)Enterキーを2回押すことでサーバから応答が返ってきます。
つまり、サーバ側はTCPで接続待ち受けをして、行単位に文字列を受信し、GETメソッドが来たら要求されたHTMLの本文をリスト1のようにヘッダを付けて返してやれば、簡単なWebサーバとして機能することになります。
ただし、KOZOSはファイルシステムを持っていないため、「index.html」をファイルとしてシステム上に持つことはできません。そこで、HTMLファイルは、HTTPサーバ側で“静的な文字列”として保持させることにします。つまり、HTML文書をソースコード上にハードコーディングしてしまうわけです。
前回は、Ethernet、ARP、IP、ICMPの処理をそれぞれタスクとして実装しました。これは各処理を細かくタスク分けすることで、おのおのの処理の見通しをよくすることが目的でした。
今回も同様の考えで、TCP処理とHTTPサーバをそれぞれ独立したタスクとして実装することにします。
TCPの処理に必要なのは、IPパケットの送受信のみです。このため「tcpタスク」はipタスクとメッセージ通信し、受信パケットを受け取ったり、送信パケットを依頼したりすることで処理を行います。
HTTPサーバは、「httpdタスク」として実装します。httpdタスクは、tcpタスクに対して接続待ちの依頼を発行します。Webブラウザから接続されたら、tcpタスクからhttpdタスクに対して受信文字列が送られ、httpdサーバは受信文字列を解析してリクエストに応じてHTMLのデータをHTTPで返信します。このようにして、Webサーバの機能が実現されます。
図4は、これらのタスクの構成です。そして、タスク間通信は、KOZOSのメッセージ通信を利用して実装します。
Copyright © ITmedia, Inc. All Rights Reserved.