【歴史】Unix、grep、UTF-8、Go言語を作った男。ケン・トンプソン物語。
/ coding_youtuber ==== おすすめ書籍 ==== UNIXという考え方: その設計思想と哲学 https://amzn.to/4xcsBW4 ==== 低レイヤー自作を行う学習教材 ==== バックエンドや要素技術を自作して学びたい方はCodeCraftersがおすすめです。 👇このリンクから登録すると40%OFFになります。 https://app.codecrafters.io/join?via=... ------------ ●お仕事のご依頼はこちらから https://www.naoya-tech.com ●BGM素材 BGMer http://bgmer.net #unix #歴史言及されている人物
ケン・トンプソン
ケン・トンプソン(Ken Thompson)は、現代のコンピュータ社会の「基盤」をほぼ1人で作り上げた伝説のプログラマです。
現代のITエンジニアが毎日使っているLinux、Mac、プログラミング言語のCやGo、文字コードのUTF-8、正規表現検索(grep)に至るまで、彼の足跡を避けて通ることは不可能と言っても過言ではありません。
ケン・トンプソンにまつわる有名な雑学・業界裏話
1. Unix誕生の裏には「宇宙旅行ゲーム」があった
動画の目次にある「非力なPDP-7を選んだ理由」「妻子不在の3週間で書き上げたUnixの原型」に繋がる有名なエピソードです。
ベル研究所が大型OSプロジェクト(Multics)から撤退した際、ケンは自作の宇宙飛行シミュレーションゲーム『Space Travel』を遊ぶマシンを失いました。そこで研究所の隅で埃を被っていた非力なPDP-7(メモリがわずか数キロバイト程度)を発見。 「このマシンでゲームを快適に動かしたい」という一心で、妻と子供が帰省していた3週間の間に、ファイルシステムやエディタ、アセンブラ、そしてOSのカーネル(Unixの原型)を一気に書き上げました。つまり、現代のあらゆるデジタル社会の礎となったUnixは、彼の「ゲームがしたい」という情熱から生まれたのです。
2. 「食堂のナプキン」で一晩でできたUTF-8
動画の「17:03 食堂のナプキンで生まれたUTF-8」に関する逸話です。
1992年、Plan 9(ベル研究所で開発していた次世代OS)のために、多言語を扱える新しい文字コードが必要になりました。 ケン・トンプソンとロブ・パイク(Go言語の共同開発者)は、夕食に入ったニュージャージー州のダイナー(食堂)で「どうすれば既存のASCIIコードと互換性を保ちながら世界中の文字(日本語含む)を表現できるか」を議論。その場でプレイスマット(紙製のナプキン/ランチョンマット)に仕様を書き出し、その日の夜にはコードを実装して完成させたと言われています。
現在、世界のWebサイトの98%以上で採用されている文字コード「UTF-8」は、このディナーの席で誕生しました。
3. トンプソン・ハック(Reflections on Trusting Trust)
1983年にチューリング賞を受賞した際、彼が行った記念講演『Reflections on Trusting Trust』は、コンピュータセキュリティ史上で最も有名な伝説の一つです。
ケンは「コンパイラ(C言語などのプログラムを機械語に変換するソフト)そのものにバックドア(裏口)を仕込んだ」と明かしました。
-
ソースコードに悪意ある処理を書く。
-
そのソースコードをコンパイラでビルドする。
-
ソースコードから悪意ある処理を消去する。
-
しかし、生成されたコンパイラ自体が「自分自身をビルドするときに悪意ある処理を自動注入する」仕組みになっているため、ソースコードをいくら検証してもバックドアは見つからない。
「ソースコードが公開されていても、それを変換するツール(コンパイラ)を信頼できなければセキュリティは成立しない」ということを証明してみせた、伝説のハックです。
4. 飛行機の操縦士ライセンスと「チェス」への執念
ケンはプログラミングだけでなく、非常に多趣味で極めすぎる性格でも知られています。
-
パイロット: 飛行機の操縦士免許を持っており、過去には自作の飛行機を所有・操縦していました。さらに旧ソビエト連邦まで飛んでいき、ミグ戦闘機(MiG-25)に乗った経験もあります。
-
チェスコンピュータ「Belle」: 1970〜80年代、専用ハードウェアを用いたチェス専用マシン「Belle」を開発。当時の世界コンピュータチェス選手権で何度も優勝し、マスターレベル(人間トップクラス)の強さに達した初のマシンとなりました。
ケン・トンプソンの主要な業績まとめ
| 開発物 / 業績 | 概要・インパクト |
|---|---|
| Unix | 現代のLinux, macOS, Android, iOSの源流となったオペレーティングシステム。 |
| B言語 / C言語 | ケンが作った「B言語」をベースに、同僚のデニス・リッチーが「C言語」へと進化させた。 |
| grep / 正規表現 | QEDエディタの検索機能を単体コマンドとして切り出したのが grep(Global Regular Expression Print)。 |
| UTF-8 | 世界中で使われる標準文字コード。後方互換性と効率性を両立させた美しさが特徴。 |
| Go言語 (Golang) | Google在籍時、ロブ・パイクやロバート・グリズマーと共に「C++の煩雑さ」を解決するために開発。 |
エンジニアの世界では「天才」と呼ばれる人物は多くいますが、ケン・トンプソンほど「1人が作ったものが世界中の社会インフラになり続けている」人物は他にほとんど存在しません。
ケン・トンプソンのB言語からデニス・リッチーのC言語がどのように生まれたのか、歴史と技術的な変化を教えてください。
その背景には、「ハードウェアの進化(PDP-7からPDP-11へ)」と「Unixカーネルを高級言語で書き直したい」という強い動機がありました。
1. 誕生の歴史的流れ
マーティン・リチャーズが開発したプログラミング言語BCPL(Basic Combined Programming Language)が登場。システム記述用に簡略化された言語で、B言語の直接のベースとなる。
初期Unixの開発マシンであるPDP-7(メモリが非常に少ない18ビットマシン)上で動作させるため、ケン・トンプソンがBCPLをさらに切り詰め、極限までシンプルにしたB言語(B language)を開発。名前の由来は「BCPLの頭文字」または妻の名前「Bon」から。
ベル研究所に新しいマシンPDP-11(16ビットマシン、バイトアドレス指定が可能)が導入される。B言語でプログラムを書こうとするが、PDP-11のハードウェア構造とB言語の設計が噛み合わず、性能と表現力に限界を迎える。
デニス・リッチーがB言語の改良に着手。型システムを組み込んだ「NB(New B)」を経て、1972年〜1973年にC言語として結実。1973年、Unixのカーネル本体がC言語で完全に書き直される。
2. 技術的な3大変化:B言語とC言語は何が違ったのか?
B言語からC言語への進化における本質は、「型なし(Typeless)」から「型あり(Typed)」への移行と、「メモリ直接操作能力の獲得」にあります。
① 「型なし(Typeless)」から「データ型」の導入へ
-
B言語(型なし): すべての変数は「1つのワード(メモリの1ブロック)」として扱われました。数値も、文字も、メモリのアドレス(ポインタ)もすべて同じサイズ・種類のデータとして扱っていたため、文字処理や浮動小数点演算を効率よく行うことができませんでした。
-
C言語(データ型の導入): デニス・リッチーは
char(8ビット/1バイト)やint(16ビット/2バイトなど)といった型を導入しました。これにより、1バイト単位で文字データを処理できるPDP-11の能力を限界まで引き出せるようになりました。
② ポインタ演算と配列の洗練
-
B言語の課題: B言語で配列を作ると、配列の本体とは別に「先頭アドレスを保持するポインタ変数」が自動的に生成されていました。これは貴重なメモリを圧迫し、実行速度も落ちる原因でした。
-
C言語の解決(配列とポインタの統一): C言語では「配列名は先頭要素へのポインタとして振る舞う」という画期的な設計を採用。余計なメモリ空間を消費せずに、高速なポインタ移動とメモリアクセスが可能になりました。
③ コンパイラの生成コード効率(マシンスペックへの最適化)
-
B言語: B言語はインタープリタ(またはスレッドコード形式)で動作することが多く、OSのカーネルのような超高速性が求められる処理には低速すぎました。
-
C言語: C言語は最初から高度なコンパイラとして設計され、アセンブリ言語で書いた場合とほぼ変わらないレベルの高速な機械語コードを直接出力できるようになりました。
3. この進化がもたらした革命:Unixの再記述
当時(1970年代前半)、オペレーティングシステム(OS)は「アセンブリ言語で書くもの」というのが常識でした。アセンブリ言語で書かれたOSは、特定のコンピュータでしか動かず、新しいマシンが発表されるたびにゼロから書き直す必要があったからです。
1973年、ケンとデニスはUnixの95%以上のコードをC言語で全面的に書き直しました。
これにより、C言語のコンパイラさえ用意すれば、どんなハードウェア上でもUnixを移植して動かせるという前代未聞のポータビリティ(移植性)が実現したのです。この決断が、Unixを世界中の大学や企業へ爆発的に普及させ、今日のLinuxやmacOS、Android、iOSへと繋がる大きな礎となりました。
Unix哲学とは具体的にどのような考え方なのか、代表的な例を挙げて分かりやすく解説してください。
一言で言えば、「1つのことに集中する小さなツールを作り、それらを繋ぎ合わせる」という考え方です。
1. Unix哲学のコアとなる4つの原則
ダグラス・マキロイ(パイプラインの発明者)は、Unix哲学を次のように要約しています。
-
1つのことを、うまくやれ(Do One Thing and Do It Well) 1つのプログラムには1つの機能だけを持たせ、その機能において最高のパフォーマンスを発揮させる。
-
すべてのプログラムの出力は、別のプログラムの入力になり得るものとせよ プログラム間でのデータ受け渡しを前提とし、不要な装飾や複雑なフォーマットを排したプレーンテキストで会話させる。
-
早めに試作せよ(Write programs to work together) 机上の空論で巨大なシステムを作るのではなく、小さく作って動作を確認しながら改良する。
-
不器用な道具より、道具を作る道具を選べ 手作業を減らすため、タスクを自動化・効率化するスクリプトやツールを自作する。
2. 具体例で見る「Unix哲学」の凄さ
Unix哲学の真骨頂は、「パイプライン(|)」を使ったツールの組み合わせです。
例えば、「アクセスログファイルの中から、アクセス回数が多いIPアドレスのTOP 3を知りたい」という問題があったとします。
Unixには「ログ解析専用の巨大なソフト」はありません。代わりに、独立した小さなツールをパイプライン | で繋ぎ合わせます。
cat access.log | grep "ERROR" | cut -d' ' -f1 | sort | uniq -c | sort -nr | head -n 3
この一行で動いている小さなツールたちの役割は以下の通りです。
| ツール | 単一の役割 |
|---|---|
cat |
ファイルの中身を読み込んでそのまま出力する |
grep |
"ERROR" という文字列が含まれる行だけを抽出する |
cut |
各行から1番目の要素(IPアドレス)だけを切り取る |
sort |
IPアドレスを並べ替える(uniq のための前処理) |
uniq -c |
連続する同じIPアドレスをまとめ、出現回数をカウントする |
sort -nr |
カウントされた数字が大きい順に並べ替える |
head -n 3 |
先頭の3行だけを表示する |
なぜこれが素晴らしいのか?
-
再利用性:
sortやgrepはログ解析だけでなく、単語帳の並べ替えにも、システムプロセスの検索にもそのまま使えます。 -
堅牢性: 万が一
headにバグがあっても、grepやsortには影響しません。 -
拡張性: 「結果をファイルに保存したい」「メールで送信したい」と思ったら、末尾に
> result.txtなどを繋ぐだけで完了します。
3. 現代のWeb・システム開発への影響
Unix哲学は、単なるコマンドラインの話にとどまらず、現代のソフトウェア設計全般に深く根付いています。
-
マイクロサービスアーキテクチャ 1つの巨大なWebアプリケーション(モノリス)を作るのではなく、認証・決済・通知などの小さなサービスに分割し、APIで連携させる設計手法はUnix哲学そのものです。
-
KISS原則(Keep It Simple, Stupid) 「コードはシンプルに保て」というプログラミングの格言。複雑なクラスや巨大な関数を作らず、単一責任の原則(SRP)を守る思想の根底にUnix哲学があります。
-
テキストベースのプロトコル HTTPやSMTP(メール送受信)、JSONデータなど、人間が読める「プレーンテキスト」でシステム間がやり取りする設計は、Unixの「出力は次の入力になる」という原則に由来しています。
「巨大で複雑なツールを1つ作るより、シンプルで完璧なツールを10個作り、連携させる方が遥かに強力である」
ケン・トンプソンたちが半世紀前に作ったこのシンプルさへのこだわりが、今なおあらゆるシステム開発のバイブルであり続けています。
デニス・リッチーという人物の業績をもっと知りたい
業界内では彼のアカウント名である "dmr" の名でも親しまれ、現在のデジタル社会の根幹を築いたキーマンの1人です。
1. デニス・リッチーの主な業績
① C言語(C Language)の開発(1972年〜1973年)
ケン・トンプソンのB言語をベースに、型システムや高度なポインタ操作を導入したC言語を生み出しました。 C言語はその後、C++、Java、C#、Objective-C、Go、Rustなど、現代のほぼすべての主要プログラミング言語の直接・間接的な手本となっています。
② UnixのC言語による再記述と移植性の実現
アセンブリ言語で書かれていたUnixカーネルをC言語で全面的に書き直しました。これによりUnixは特定のハードウェアに依存しない「ポータブルなOS」となり、世界のあらゆるコンピューターへ広がるきっかけを作りました。
③ 聖書と呼ばれた名著『The C Programming Language(K&R)』執筆
1978年、ブライアン・カーニハンと共に『The C Programming Language』(著者二人の頭文字を取ってK&Rと呼ばれる)を執筆・出版しました。 この本はANSI(米国国家規格協会)による標準化以前の「事実上のC言語の仕様書」となり、数多くのエンジニアのバイブルとなりました。プログラミングの最初の例題として有名な「Hello, World!」を世界に広めたのも本書です。
④ 次世代分散OS「Plan 9」と「Inferno」の開発
1980〜90年代には、ベル研究所でUnixの正統な進化形として「Plan 9」や「Inferno」などの分散オペレーティングシステムプロジェクトを指揮しました。ここで培われた「すべてのリソースをファイルとして扱う」思想は、現在のシステム設計や分散環境の基礎アイデアとなっています。
2. ケン・トンプソンとの関係性(名コンビ「Ken and Dennis」)
ケン・トンプソンとデニス・リッチーの二人は、計算機科学の歴史において最も成功した「天才ペア」として知られます。
-
数学・理系エリートとアイデアマンの対比:
-
ケン・トンプソン: 直感的で、アイデアがひらめくと超人的なスピードでコードを書き上げるタイプ(ハッカー気質)。
Wikipedia -
デニス・リッチー: ハーバード大学で物理学と応用数学を学んだ理論派。ケンのアイデアを整理・洗練させ、美しい仕様や型システムに落とし込むタイプ。
Wikipedia
-
-
分業が生んだ奇跡: ケンがB言語やUnixの骨組みを作り、デニスがC言語へと昇華させ、Unix全体をC言語で洗練させるという完璧な相互補完によって、UnixとC言語は完成しました。
二人はその功績により、コンピューター界のノーベル賞とされるチューリング賞(1983年)、米国最高峰のアメリカ国家技術賞(1998年/1999年)、そして日本国際賞(2011年)などを共同受賞しています。
3. 主な受賞歴と名言
| 年 | 賞・栄誉 | 授与理由 |
|---|---|---|
| 1983年 | チューリング賞 | 汎用OS理論の発達、およびUNIX OSの実装に対して |
| 1990年 | IEEE ハミングメダル | UNIXオペレーティングシステムおよびC言語の創出に対して |
| 1998年 | アメリカ国家技術賞 | UNIX OSおよびCプログラミング言語の発明に対して |
| 2011年 | 日本国際賞 | UNIXオペレーティングシステムの開発における先駆的貢献に対して |
“C is quirky, flawed, and an enormous success.” (C言語は変で、欠点もあるが、とてつもない大成功を収めた。) — デニス・リッチー
Wikipedia
4. ジョブズの陰に隠れた「2011年10月」の静かな去り際
デニス・リッチーは2011年10月12日、70歳で逝去しました。
偶然にも、Appleの共同創業者スティーブ・ジョブズが亡くなったわずか1週間後のことでした。メディアがジョブズの訃報一色で持ちきりだったため、リッチーの死が大きく一般ニュースで報じられることは稀でした。
しかし、技術コミュニティでは彼への追悼と感謝が溢れました。 「スティーブ・ジョブズが創り出した美しい製品(Mac, iPhone, iOS)は、すべてデニス・リッチーが創ったC言語とUnixの上で動いている」という言葉が語られた通り、目立つ表舞台には出ずとも、現代のIT社会の根底を支え続けた真の英雄でした。
ブライアン・カーニハンとデニス・リッチーの関係や、名著『K&R』が業界に与えたインパクトについて教えてください。
ブライアン・カーニハン(Brian Kernighan)とデニス・リッチー(Dennis Ritchie)は、ベル研究所で共に過ごした同僚であり、名著『The C Programming Language』(通称:K&R)の共著者としてコンピューター史に名を刻んだ黄金ペアです。
二人の役割分担と、1978年に出版された本書がソフトウェア業界に与えた圧倒的なインパクトについて解説します。
1. カーニハンとリッチーの関係性:役割の完璧な分担
「C言語を作ったのはデニス・リッチー」ですが、「C言語を世界中に広め、美しく整理したのはブライアン・カーニハン」と言えます。
-
デニス・リッチー(設計者・実装者): C言語の型システムやコンパイラ本体を設計・実装する技術的・理論的中心人物でした。
-
ブライアン・カーニハン(解説者・洗練者): カーニハン自身は「C言語の設計には自分は関わっていない」と謙虚に語っていますが、彼は優れたドキュメント執筆能力と教育的センスを持っていました。リッチーが作った言語の仕様を、初心者から熟練者まで誰にとっても分かりやすく文章化し、サンプルコード(「Hello, World!」など)を洗練させたのがカーニハンでした。
カーニハンの持つ「説明の天才的うまさ」と、リッチーの「技術的エレガントさ」が出会ったことで、C言語は単なるベル研究所内の社内ツールに留まらず、世界標準へと躍り出ることになりました。
2. 名著『K&R』が業界に与えた4つのインパクト
① 事実上の「標準仕様書」となった
1978年に初版が出版された当時、C言語にはまだANSI(米国国家規格協会)やISOによる公的な標準規格が存在しませんでした。 そのため、『The C Programming Language』(K&R)は単なる解説書を超えて、世界中のコンパイラ開発者が「これがC言語の正しい仕様だ」と参照する唯一無二のバイブル(事実上の標準規格)として機能しました。
② 「Hello, World!」を世界中に定着させた
プログラミング言語を学ぶ際、最初に画面に文字を表示させる演習プログラム "hello, world" は、本書の冒頭で紹介されたことで世界中に一気に広まりました。
#include <stdio.h>
main()
{
printf("hello, world\n");
}
今やPythonやJava、Go、Rustに至るまで、あらゆる言語のチュートリアルで最初に「Hello, World!」を書く風習は、カーニハンがK&Rで書いたこのわずか数行のコードがルーツです。
③ プログラミング技術書の「新しいデファクトスタンダード」となった
K&Rが出版される以前の技術書は、重厚で学術的、あるいはマニュアルのように退屈なものが大半でした。 しかし、K&Rは以下の特徴を持っており、その後のプログラミング書籍の書き方を一変させました。
-
薄くて無駄がない: わずか200ページ程度の中に、言語の全仕様と実践的な概念が凝縮されている。
-
動くコード重視: 理屈を長々と説明する前に「まずは動くプログラム」を見せる構成。
-
美しいコーディングスタイル: インデントや波かっこ
{}の配置ルール(いわゆるK&Rスタイル)を提示し、数世代にわたるエンジニアのコードの書き方に影響を与えた。
④ 爆発的なC言語の普及と「ポータブルなソフトウェア」の時代を開拓
K&Rの読みやすさと完成度の高さによって、大学や企業のエンジニアたちが一気にC言語を習得しました。
それまでハードウェア(メインフレームやミニコン)ごとにバラバラだったプログラミング言語がC言語へと統一され始め、「同じC言語のコードを書けば、異なるメーカーの計算機上でもプログラムが動く」というポータビリティの時代が本格的に到来しました。
3. カーニハンと「Unix」「AWK」などの関わり
カーニハンはK&R以外にも、IT業界に膨大な貢献を残しています。
-
「Unix」という名前の名付け親: Multicsプロジェクトからの派生で生まれた新しいOSに対し、不完全さを皮肉りつつも「単一の」という意味を込めて Unics(後に Unix)と名付けたのはカーニハンです。
-
AWK言語の「K」: テキスト処理言語
awk(アルホ、ワインバーガー、カーニハンの3人によって開発)の「K」はカーニハンの頭文字です。 -
Unix哲学のドキュメント化: Unixの思想をまとめた名著『Unixプログラミング環境』などの執筆を通じて、Unix哲学を世界に知らしめました。
「プログラムは、人間が読むために書かれるものであり、マシンが実行するのはついでに過ぎない」 (カーニハンの著書や思想に通底する有名なロジック)
デニス・リッチーという稀代のエンジニアが作った「C言語」は、ブライアン・カーニハンという最高の文筆家・プログラマと出逢ったからこそ、今日まで続くコンピュータ社会の「共通言語」となり得たと言えます。Gemini は AI であり、不正確な情報を表示することがあります。
Plan 9(ベル研究所の次世代OS)について詳しく知りたい
Plan 9 from Bell Labs(Plan 9)は、1980年代後半からケン・トンプソン、デニス・リッチー、ロブ・パイク、ブラッド・コックスらUnixの生みの親たちがベル研究所で開発した「Unixの正統な後継(次世代)オペレーティングシステム」です。
Unixで培った思想をさらに突き詰め、ネットワーク時代に最適化された究極のシンプルさを目指して作られました。
名前の由来は、カルト的B級SF映画『Plan 9 from Outer Space(外宇宙からのプラン9)』から来ています。
1. なぜPlan 9が作られたのか?(Unixの限界と課題)
1970年代に生まれたUnixは非常に優秀でしたが、1980年代になると以下のような「時代の変化」に伴う課題に直面しました。
-
ネットワークの普及: Unixは単一の大型コンピュータで動くことを前提に作られており、分散した複数の端末やサーバーをシームレスにつなぐ仕組みが後付けだった。
-
グラフィック(GUI)の登場: テキスト端末(CLI)前提の設計に、後からX Window Systemなどの重厚なGUIを無理やり載せたため、システムが複雑化していた。
そこでケンやデニスらは、「もし今(1980年代末)、ゼロからUnixを作り直すとしたらどうなるか?」という問いへの答えとしてPlan 9の設計を始めました。
2. Plan 9の3大イノベーション
Plan 9の核心は、Unixの概念を極限までシンプルかつ強力に拡張した点にあります。
① 「すべてはファイルである」の完全なる拡張
Unixには「すべてはファイルである」という有名な原則がありますが、Unixの段階ではネットワークやグラフィックデバイスなどは例外的な扱い(特殊なAPIやソケット等)が必要でした。
Plan 9ではこれを徹底し、端末、メモリ、ネットワーク接続、プロセス、グラフィック画面に至るまで、文字通りあらゆるリソースをファイルシステム上のファイルとして表現しました。
-
例えば、ネットワーク接続を開くには
/net/tcp/cloneというファイルを読み書きするだけで完了します。
② 9Pプロトコルによる「分散環境の透明性」
Plan 9の心臓部と言えるのが9P(Plan 9 Protocol)というネットワークファイルプロトコルです。
すべてのリソースが「ファイル」として抽象化されているため、9Pを使えばネットワーク越しにある別のマシンのリソース(CPU、ディスプレイ、マウス、ファイル)を、あたかも自分のローカルファイルであるかのように自分のファイルツリーに組み込む(マウントする)ことができました。
-
例: CPUが強力なリモートサーバーの
/proc(プロセス)を自分の手元にマウントして計算させ、結果だけを手元のディスプレイデバイス(ファイル)に出力する、といった芸芸がOS標準の仕組みだけでシームレスに行えました。
③ 文字コード「UTF-8」の誕生地
Plan 9は、世界で初めて全システムレベルでUnicode(UTF-8)をネイティブサポートしたOSです。
1992年、Plan 9で多言語(日本語やアラビア語など)をシンプルに扱うため、ケン・トンプソンとロブ・パイクがダイナーの紙ナプキンの上で仕様を書き上げたのが、現在世界中で使われている「UTF-8」です。
3. なぜ商用OSとしてUnixやLinuxのように普及しなかったのか?
極めて先進的で美しい設計だったPlan 9ですが、世界標準のOSにはなれませんでした。
-
Linuxの急速な台頭 Plan 9の開発と同時期の1991年、リーナス・トーバルズがLinuxを公開しました。Linuxは「既存のUnix互換」であったため、膨大なPCハードウェアや既存のソフトウェア資産をそのまま利用でき、爆発的に普及しました。
-
ベル研究所のライセンス問題 当時、AT&T/ベル研究所はPlan 9のソースコード権利やライセンスのオープン化に慎重でした(後にオープンソース化されますが、時期が遅すぎました)。
-
互換性の欠如 Plan 9はあまりに革新的だったため、既存のPOSIX(Unix標準規格)やC言語のライブラリとの互換性を削ぎ落としていました。そのため既存のアプリを移植するのが困難でした。
4. 現代に息づくPlan 9の遺伝子
Plan 9というOS自体は普及しませんでしたが、そこで生み出されたアイデアや技術は、形を変えて現代の巨大プラットフォームの中に生きています。
-
Go言語 (Golang): ケン・トンプソンやロブ・パイクらがGoogleで作ったGo言語の並行処理モデル(
goroutineやchannel)や、シンプルさを追及する設計思想は、Plan 9用に開発されたC言語の拡張(8cコンパイラ等)や通信思想から直接引き継がれています。 -
WSL2(Windows Subsystem for Linux 2): MicrosoftのWSL2では、WindowsホストとLinuxゲスト間での高速なファイル共有のために、Plan 9の 9Pプロトコル が採用されています。
-
Linuxの
/procや/sys: Linuxのカーネル情報やプロセス情報をファイルとして扱う仕組みは、Plan 9の設計から強い影響を受けています。
「Plan 9は商業的には敗北したかもしれないが、思想的には未来を20年先取りしていた」
ケン・トンプソンたちが「理想のコンピューティング」を追い求めて作ったPlan 9は、今日のクラウドコンピューティングやマイクロサービス、分散システムの思想的原点となっています。
ケン・トンプソンやロブ・パイクがGo言語を設計した際、Plan 9やC言語からどのような思想や技術を引き継いだのか詳しく教えてください。
2007年、Googleにてケン・トンプソン(Ken Thompson)、ロブ・パイク(Rob Pike)、そしてロバート・グリズマー(Robert Griesemer)の3人によってGo言語(Golang)の設計が開始されました。
ケンとロブはベル研究所時代に「Unix」「C言語」「Plan 9」「UTF-8」を共に作り上げてきた盟友です。そのため、Go言語は一見現代的な言語に見えながら、その根底にはUnix / C言語の愚直な実践性と、Plan 9で試みた分散処理・並行処理の美学が色濃く脈打っています。
1. C言語から引き継いだ思想と技術
Go言語の文法(シンタックス)や基本的な手触りは、C言語の直接的な「正統進化系」です。
① シンプルさとミニマリズム(KISS原則)
C言語もGo言語も「言語仕様を意図的に小さく保つ」という強い意志を持って設計されています。
-
学習コストの低さ: C言語の文法キーワードはわずか32個ですが、Go言語も25個しかありません(JavaやC++は50〜100以上)。
-
「やり方は1つだけ」: 複雑な言語機能を削ぎ落とし、誰が書いても同じような可読性の高いコードになるよう設計されています(例えば、ループ構文は
forしか存在しません)。
② 実行速度とコンパイル速度の圧倒的な重視
C言語がPDP-11の機械語に直接変換される高速な言語であったように、Go言語も中間言語や仮想マシン(JVMなど)を介さず、OSネイティブの機械語バイナリを出力します。 さらに、Go言語は「大規模システムでのビルド待ち時間」を劇的に減らすため、依存関係の解決をC言語以上に厳密かつ高速に行えるコンパイラ設計になっています。
③ ポインタと明示的なメモリモデル
Go言語にはガベージコレクション(GC)が導入され、C言語のような「手動のメモリ解放(free)」による事故は防がれています。しかし、「ポインタ」という概念自体はそのまま残されました。 値渡し(コピー)なのか、参照渡し(ポインタ)なのかをエンジニアが明示的にコントロールできる設計は、C言語の「ハードウェアのメモリ構造を意識する」思想を継承しています。
2. Plan 9から引き継いだ思想と技術
Plan 9でケンやロブが目指した「多数のプロセスがネットワーク越しに協調して動く世界」のツールキットが、Go言語の文法や標準ライブラリとして結実しています。
① CSPモデルに基づく強力な並行処理(Goroutine & Channel)
Plan 9を開発する中で、ロブ・パイクらはSqueak(1989)やNewsqueak(1980年代末)、Alef(Plan 9用のプログラミング言語)といった並行処理言語を試作していました。これらは計算機科学者トニー・ホーアのCSP(Communicating Sequential Processes)という理論に基づいています。
この直系の子孫が、Go言語の最大の特徴である goroutine と channel です。
-
メモリを共有して通信するな。通信によってメモリを共有せよ。 (“Do not communicate by sharing memory; instead, share memory by communicating.”)
-
スレッド間で複雑なロック(排他制御)をかけるのではなく、データを「チャンネル」経由でメッセージとしてやり取りする思想は、Plan 9のシステム設計から直接移植されたものです。
② 文字コード「UTF-8」のファーストクラスサポート
前述の通り、UTF-8は1992年にPlan 9のためにケンとロブが考案した文字コードです。 Go言語では、ソースコード自体がUTF-8で記述されることを前提としており、文字列処理(rune 型など)においてもUTF-8が完全に組み込まれています。文字化けやエンコーディング変換に悩まされない設計は、自作した文字コードへの絶対的な信頼から来ています。
③ インターフェースによる「ルーズな結合」(ダックタイピング)
Plan 9では「すべてのリソースをファイルという共通のインタフェースで扱う」ことで柔軟性を実現していました。 Go言語の interface は、ある型が特定のメソッドを持っていれば、明示的な宣言(implements など)をしなくても自動的にそのインターフェースを満たしているとみなされます。
-
例えば、標準ライブラリの
io.Readerやio.Writerは、ファイルであれ、ネットワークソケットであれ、メモリバッファであれ「Read/Writeできればすべて同列に扱う」という、Plan 9やUnixの抽象化思想そのものです。
3. C言語やPlan 9から「あえて捨て去ったもの」
トンプソンらは、過去の反省を生かして「あえて排除したもの」もあります。
| 捨て去ったもの | 理由 |
|---|---|
| 複雑な継承(オブジェクト指向) | C++やJavaの複雑なクラス階層がコードの可読性を下げると判断。継承ではなく「構造体の埋め込み(コンポジション)」を採用。 |
| ポインタ演算 | C言語の事故(バッファオーバーフローなど)の最大の原因である ptr++ のような算術演算を禁止。 |
ヘッダーファイル (.h) |
C言語の #include によるビルド速度低下を解消するため、モダンな package システムを導入。 |
| 手動メモリ管理 | 安全性と生産性を最優先し、高性能なガベージコレクタ(GC)を標準搭載。 |
まとめ
Go言語を一言で表現するなら、「C言語の手触りと速度」+「Plan 9の並行処理思想」−「C++の過剰な複雑さ」 です。
1970年代にUnixとC言語を作り、1980〜90年代にPlan 9で分散システムを模索したケン・トンプソンとロブ・パイク。彼らが40年以上のキャリアの中で培った「本当に必要な機能だけを残す」という洗練された美学が、今日クラウドインフラ(DockerやKubernetesなど)を支えるGo言語として結実しています。
なぜDockerやKubernetesといった現代のインフラ技術のデファクトスタンダードにGo言語が選ばれたのか教えてください。
その最大の理由は、「C言語並みの実行・ビルド速度」と「Java/Python並みの高い生産性・安全性」を絶妙なバランスで両立しており、システムプログラミングの要件に完璧に合致していたからです。
具体的には、以下の5つの技術的・思想的理由が挙げられます。
1. 静的単一バイナリの配布性(依存関係ゼロ)
DockerやKubernetesのようなインフラツールは、あらゆるサーバー(Linuxディストリビューションやバージョンを問わず)上で即座に動作する必要があります。
-
Go言語の特徴: コンパイルすると、実行に必要なすべてのライブラリやランタイムを1つの大きな実行ファイル(静的バイナリ)にまとめて出力します。
-
メリット: 実行するサーバー側に Python、Ruby、Java (JVM)、あるいは特定の動的ライブラリ(.soファイル)がインストールされているかを気にする必要がありません。「1つのバイナリファイルをサーバーに置くだけで即起動する」 という圧倒的なデプロイの手軽さが、インフラ構築・自動化において最強の強みとなりました。
2. 超軽量な並行処理(Goroutine)
DockerやKubernetesは、何千・何万というコンテナの状態をリアルタイムに監視し、ネットワーク通信やプロセスの起動・停止を同時に処理する必要があります。
-
従来のOSスレッド(C++ / Java): 1スレッドあたり数MBのメモリを消費するため、数千スレッドを同時に立ち上げるとメモリ不足やコンテキストスイッチのオーバーヘッドで性能が低下します。
-
GoのGoroutine: OSスレッドの上で動作する軽量なユーザー空間スレッドであり、1つあたりわずか数キロバイトのメモリで起動できます。1つのプロセス内で数万・数十万のGoroutineを同時に走らせることが可能なため、大量のコンテナやネットワークAPI要求を処理する分散システムに最適でした。
3. C言語 / Linuxカーネルとの親和性
Dockerの本質は、Linuxカーネルが持つ cgroups(リソース制限)や namespaces(プロセス隔離)という機能を組み合わせたラッパー(制御ツール)です。
Go言語はケン・トンプソンらUnixの創始者が作った言語であるため、POSIXシステムコールやLinuxカーネルのAPIを直接叩くための標準ライブラリ(syscall や os パッケージなど)が最初から非常に充実しており、システムレベルの低レイヤープログラミングが極めて容易でした。
4. 圧倒的なコンパイル速度と開発サイクル
大規模なシステムソフトウェア(C++など)では、コードを変更してからコンパイルが完了するまでに数分〜数十分かかることが珍しくありません。
Go言語は最初から「Googleのような超大規模コードベースでのビルド時間削減」を目的に設計されているため、大規模なプロジェクトであっても数秒でコンパイルが完了します。この「書いてすぐテストして動かせる」という高速な開発ループ(フィードバックループ)が、初期のDockerやKubernetesの開発速度を爆発的に加速させました。
5. シンプルな言語仕様による「巨大オープンソースコミュニティ」の形成
Kubernetesのような巨大プロジェクトには、世界中の何千人ものエンジニアがオープンソースとしてコードを寄稿(コントリビュート)します。
-
言語機能が多すぎる場合(C++やScalaなど): 書き手によってコードの書き方が全く異なり、他人の書いたコードを読むのが困難になります。
-
Go言語の場合: 文法規則がわずか25個のキーワードに絞られており、コードフォーマッタ(
gofmt)が標準提供されているため、「誰が書いても同じような可読性の高いコード」になります。
学習コストが低く、新規参加者がコードベースを理解しやすい設計になっていたからこそ、世界最大級のオープンソースコミュニティを円滑に維持・拡大することができました。
まとめ:Unixの系譜が咲かせた現代の華
ケン・トンプソンやロブ・パイクらがPlan 9やUnixの経験を結実させて作ったGo言語は、「ネットワーク越しに無数の小さなプロセスが連携して動く」という時代を20年先取りした設計を持っていました。
そのGo言語の登場と、クラウド・マイクロサービス時代(Docker / Kubernetes)の到来が完全に合致したことで、Go言語は「現代のクラウドインフラにおけるC言語(標準OS言語)」としての確固たる地位を築くことになったのです。
Go言語の並行処理(GoroutineとChannel)の仕組みを知りたい
Go言語の並行処理の核心である Goroutine(ゴルーチン) と Channel(チャネル) は、伝統的なプログラミング言語が抱えていた「マルチスレッド処理の難しさやオーバーヘッド」を解決するために設計されました。
その裏側には、OSの仕組みを熟知したケン・トンプソンやロブ・パイクらによる極めてスマートなスケジューラ設計と通信モデルが存在します。
1. Goroutine(ゴルーチン)の仕組み:なぜ「超軽量」なのか?
Goroutineはよく「軽量スレッド」と呼ばれますが、OS(Linuxなど)が管理する「OSスレッド」とは根本的に異なる存在です。
① OSスレッドとGoroutineの違い
| 項目 | OSスレッド | Goroutine |
|---|---|---|
| 管理主体 | OSのカーネル | Goのランタイム(Goプログラム内部) |
| 初期メモリ消費 | 約 1MB 〜 2MB | 約 2KB(必要に応じて自動伸縮) |
| 切り替え(コンテキストスイッチ) | 重い(CPUレジスタ退避、カーネル空間呼び出し) | 極めて軽い(ユーザー空間内で完結、数ナノ秒) |
| 生成限界数 | 数千個程度で限界 | 数百万個 を同時に起動可能 |
② M:N スケジューラ(GMPモデル)
Goランタイムは、「少数のOSスレッド(M)」の上で「無数のGoroutine(G)」をやりくりして動かす「M:N スケジューラ」 を備えています。これを内部では GMPモデル と呼びます。
-
G (Goroutine): 実行したい処理(コードのかたまり)。
-
M (Machine / OS Thread): 実際にCPUコア上で動作する本物のOSスレッド。
-
P (Processor): 実行権限・リソース(スケジューリング用のキュー)。CPUのコア数ぶん用意される。
スケジューラの賢い動き(ワークスティーリング)
あるOSスレッド(M)が管理しているGoroutineが「I/O待ち(ファイル読み書きやネットワーク通信)」でブロックされた場合、GoスケジューラはそのOSスレッドを解放し、別のヒマなOSスレッドに処理を付け替えます。
さらに、特定のコア(P)の処理待ちキューが空になると、「他の混んでいるコアのキューから仕事(Goroutine)を横取りして実行する(Work Stealing)」 という仕組みが備わっているため、マルチコアCPUの性能を無駄なく限界まで引き出せます。
2. Channel(チャネル)の仕組み:「通信によるメモリ共有」
従来のスレッドプログラミング(C++やJavaなど)では、複数のスレッドが同じメモリ(変数)を同時に書き換えないよう、Mutex(ロック)を使って「他を排除しながらアクセスする」のが普通でした。しかし、これはデッドロック(処理の永久停止)やバグの温床になりがちです。
Go言語では、「メモリを共有して通信するな。通信によってメモリを共有せよ」 という思想のもと、データ受け渡しのためのパイプラインとして Channel を提供しています。
① Channelの2つのタイプ
-
バッファなしチャネル(Unbuffered Channel)
-
仕組み: 送信側と受信側の「手渡し」です。
-
動作: 受信側が受け取るまで、送信側のGoroutineはその場で一時停止(ブロック)します。逆も然りです。これにより、特別なロックを書かなくても自動的にGoroutine同士の同期(待ち合わせ) が完了します。
-
-
バッファありチャネル(Buffered Channel)
-
仕組み: 一定数のデータを溜め込める「キュー(Queue)」を持ったチャネルです。
-
動作: バッファの容量(例: 10個)がいっぱいになるまでは、送信側は待ち時間なしで次々とデータを放り込めます。
-
② Channelの内部構造
Channelの正体は、Goランタイム内部にある hchan という構造体です。
-
内部に リングバッファ(循環配列) を持っており、データを順番に保持します。
-
データを待っているGoroutineのリスト(送信待ちリスト / 受信待ちリスト)を内部で保持しています。
-
チャネルへのアクセス自体は内部で安全に排他制御されているため、エンジニアが自分でロックを書く必要がありません。
3. 具体コードで見る Goroutine & Channel
以下のコードは、複数のGoroutine(職人)が並行して計算を行い、結果をChannelを通じてメイン処理に集約する例です。
package main
import (
"fmt"
"time"
)
// 重い計算を行う関数
func worker(id int, ch chan string) {
time.Sleep(1 * time.Second) // 重い処理のシミュレーション
// Channelに結果を送信
ch <- fmt.Sprintf("ワーカー %d の処理が完了しました", id)
}
func main() {
ch := make(chan string) // 文字列を送受信するChannelを作成
// 3つのGoroutineを並行して起動(go キーワードをつけるだけ)
for i := 1; i <= 3; i++ {
go worker(i, ch)
}
// 3つの結果を受け取る
for i := 1; i <= 3; i++ {
msg := <-ch // Channelからデータを受信するまでここで自動的に待機(ブロック)
fmt.Println(msg)
}
}
実行結果
通常なら1秒×3回=3秒かかるところが、3つのGoroutineがマルチコア上で同時に動くため、わずか1秒で3つすべての結果が出力されます。
まとめ
-
Goroutine: OSスレッドより圧倒的に軽い「2KBの実行単位」。GoのGMPスケジューラがOSスレッド上で効率よく回すため、数万個動かしても重くならない。
-
Channel: Goroutine同士が安全にデータを手渡しするための「安全なパイプ」。ロックを書かずにスレッド間の同期とデータ共有ができる。
この「go と書くだけで起動する超軽量スレッド」と「チャネルによるシンプルな手渡し」の組み合わせこそが、Go言語がDockerやKubernetesのような超並行処理が求められるインフラ基盤ソフトウェアで圧倒的な威力を発揮している最大の理由です。
0 件のコメント:
コメントを投稿