Q&A
最後の講義では、学生から送られた質問に回答しました。
- プロセッサ、仮想メモリ、割り込み、メモリ管理など、オペレーティング・システムに関連したトピックを学習するのにおすすめはありますか?
- 優先的に学ぶべきツールは何ですか?
- Python、Bashスクリプト、その他言語を使うのはどのような場合ですか?
source script.sh
と./script.sh
の違いは何ですか- パッケージやツールはどこに保存されていますか? 使用するための参照方法は?
/bin
や/lib
とは何ですか? - Python のパッケージのインストールには、
apt-get install
python-[パッケージ] か、pip install
[パッケージ] どちらを使うべきですか? - コードのパフォーマンスを改善するのに、一番簡単で最善のプロファイリングツールは何ですか?
- ブラウザのプラグインは何を使っていますか?
- 便利なデータ収集ツールには他に何がありますか?
- Docker とバーチャルマシンの違いは何ですか?
- 各 OS の利点と欠点、選び方について教えてください(例:ある目的に最適な Linux のディストリビューション)
- Vim vs Emacs?
- 機械学習アプリケーションに関して、ヒントや小技はありますか?
- Vimの小技は他にありますか?
- 2FA とはどのようなもので、使うべき理由は何ですか?
- ウェブブラウザの違いについてコメントはありますか?
プロセッサ、仮想メモリ、割り込み、メモリ管理など、オペレーティング・システムに関連したトピックを学習するのにおすすめはありますか?
まず、これらは非常に低レベルのトピックなので、 これらすべてに精通する必要が本当にあるのかが不明です。 これらは、カーネルの実装や改変など、より低レベルのコードを書き始めたときに問題となります。 そうでない限り、他の講義で取り扱ったプロセスやシグナルを除き、 ほとんどのトピックは関連がありません。
これらのトピックを学ぶ良いリソースには以下があります。
- MIT’s 6.828 class - オペレーティング・システムのエンジニアリングに関する大学院レベルの講義。講義資料は公開されている。
- Andrew S. Tanenbaum 著『Modern Operating Systems』(第4版) は、ここで言及されているコンセプトの良い概要。
- FreeBSDオペレーティング・システムの設計と実装 - FreeBSD OSに関する良い資料(Linuxではないことに注意)。
- 様々な言語でカーネルをステップ・バイ・ステップで実装している、 Writing an OS in Rust のようなその他のガイド。ほとんどの場合教育目的。
優先的に学ぶべきツールは何ですか?
優先する価値のあるトピックを以下に挙げます。
- キーボードの使用頻度を上げ、マウスの使用頻度を下げる方法を学ぶ。キーボードショートカット、インターフェイスの変更などで行う。
- エディタを詳細に学ぶ。プログラマとして、ほとんどの時間はファイルの編集に費やされるだろう。そのため、このスキルに習熟することは非常に利益をもたらす。
- ワークフローで、自動化、または繰り返しのタスクを単純化する方法を学ぶ。節約できる時間は膨大になるだろう…
- Git のようなバージョン管理ツールについて、そして現代のソフトウェアプロジェクトで協働するために、 GitHub と組み合わせて使用する方法を学ぶ。
Python、Bashスクリプト、その他言語を使うのはどのような場合ですか?
一般的に bash スクリプトは、特定の一連のコマンドを走らせたいだけという時など、短く単純な1回のみのスクリプトに便利です。 bash にはいくつかの特殊性があり、より大きなプログラムやスクリプトでの作業はしにくくなっています。
- bash は単純なユースケースでは簡単に動作するが、可能な限りの全インプットに対しては使用が本当に難しい。例えば、スクリプトの引数にスペースがあると、bash スクリプトで数え切れないバグを生み出す。
- bash はコード再利用のための修正が不可能なので、以前書いたプログラムの部品を再利用するのは難しいこともある。さらに一般的に言って、 bash にはソフトウェアライブラリのコンセプトはない。
- bash は特定の値を参照するのに
$?
や$@
のような多くのマジックストリングに頼っている。一方で他の言語ではそれぞれexitCode
やsys.args
など、明示的に参照している。
そのため、より大規模、または複雑なスクリプトでは、 Python や Ruby などより成熟したスクリプト言語を使用することをおすすめします。 これらの言語での一般的な問題は、すでに多くの人が解決しており、たくさんのライブラリとして入手可能です。 もし、着目している特定の機能が実装されたライブラリがある言語で存在するのを見つけたならば、通常その言語を使うことが最善手です。
source script.sh
と ./script.sh
の違いは何ですか
両方のケースで、 bash セッションで script.sh
が読まれ実行されます。違いは、どのセッションがコマンドを実行しているかです。
source
では、コマンドは現在の bash セッションで実行されているため、あらゆる変更は現在の環境に対して行われます。 source
実行を終了しても、例えばディレクトリの変更や関数の定義は現在のセッションで存続します。
./script.sh
のようなスタンドアロンのスクリプトを実行すると、現在の bash セッションが新しい bash インスタンスを開始し、これが script.sh
のコマンドを実行します。
そのため、 script.sh
がディレクトリを変更すると、新しい bash インスタンスはディレクトリを変更しますが、終了し、親の bash セッションに管理が戻ると、親セッションは同じ場所にあるままです。
同様に、もし script.sh
がターミナルでアクセスしたい関数を定義しているなら、現在の bash セッションで定義するためには source
が必要です。そうでないと、実行した時、現在の shell ではなく新しい bash プロセスが関数定義を処理してしまいます。
パッケージやツールはどこに保存されていますか? 使用するための参照方法は? /bin
や /lib
とは何ですか?
ターミナルで実行しているプログラムによりますが、これらは PATH
環境変数に保存されているディレクトリにあります。 which
コマンド(または type
コマンド)で、特定のプログラムをシェルがどこで見つけているかを確認できます。
一般的には、特定の種類のファイルをどこに保存するかにはいくつかの慣習があります。以下には講義で取り扱ったものを挙げます。より包括的なリストは Filesystem, Hierarchy Standard を参照してください。
/bin
- 重要なコマンドバイナリ/sbin
- 重要なシステムバイナリ、通常 root が実行する/dev
- デバイスファイル、ハードウェアとのインターフェースに用いられる特別なファイル/etc
- ホストに特定なシステムワイドの設定ファイル/home
- そのシステム内のユーザのホームディレクトリ/lib
- システムのプログラムの共通ライブラリ/opt
- 追加のアプリケーションソフトウェア/sys
- システムの情報や設定を含む(最初の講義 で取り扱いました)/tmp
- 一時ファイル(/var/tmp
も同様)。通常再起動の間に削除される。/usr/
- 読み取り専用ユーザデータ/usr/bin
- 重要でないコマンドバイナリ/usr/sbin
- 重要でないシステムバイナリ、通常 root が実行する/usr/local/bin
- ユーザーがコンパイルしたプログラムのバイナリ
/var
- ログやキャッシュなどの変数ファイル
Python のパッケージのインストールには、apt-get install
python-[パッケージ] か、pip install
[パッケージ] どちらを使うべきですか?
この質問へのユニバーサルな回答はありません。 これは、ソフトウェアをインストールするのに、システムのパッケージマネージャか、言語に特化したパッケージマネージャを使用するか、という一般的な質問に関連しています。 考慮すべきいくつかの点を以下に挙げます。
- 一般的なパッケージは両方で入手可能だが、あまり有名でないものやより最新のものは、システムのパッケージマネージャでは入手できないことがある。その場合、言語に特化したツールがベターな選択肢。
- 同様に、言語に特化したパッケージマネージャには通常、システムのパッケージマネージャよりも新しいバージョンがある。
- システムのパッケージマネージャを使う時、ライブラリはシステムワイドにインストールされる。これはつまり、開発用途で様々なバージョンが必要な場合、システムのパッケージマネージャでは不十分なことを意味する。このシナリオの場合、ほとんどのプログラミング言語は、隔離された、または仮想環境の一種を提供しているので、コンフリクトを起こすことなしに様々なバージョンのライブラリをインストールできる。Python の場合は virtualenv 、 Ruby の場合は RVM がある。
- オペレーティング・システムやハードウェアアーキテクチャによるが、これらのパッケージのいくつかは、バイナリで提供されたり、コンパイルが必要な場合がある。例えば、Raspberry Pi のような ARM コンピュータは、バイナリ形式で配布されているものや、後でコンパイルが必要なものに対して、システムのパッケージマネージャの方が言語に特化したものより優れている。これは自分の特定のセットアップに強く依存する。
インストールには、両方の方法ではなく片方のみ使用するべきです。なぜなら、併用することでデバッグが困難なコンフリクトを起こす可能性があるからです。 おすすめは、可能な場合はできる限り言語に特化したパッケージマネージャを使用し、( Python の virtualenv のような)隔離された環境を使用して、グローバル環境の汚染を避けることです。
コードのパフォーマンスを改善するのに、一番簡単で最善のプロファイリングツールは何ですか?
プロファイリングに非常に便利な一番簡単なツールは print timing です。 コードの様々なパーツの間で、かかった時間を手動で計算します。 これを繰り返すことで、コードのバイナリサーチをして、コードの中で最長の時間がかかっているセグメントを効率的に見つけることができます。
より進化したツールとして、 Valgrind の Callgrind があります。これはプログラムを走らせ、全部にどれだけの時間がかかるかと、全コールスタック、どの関数がどの他の関数を呼び出ししているかを測定します。
その後、プログラムのソースに行ごとにかかった時間のメモがついたものを出力します。
しかし、これはプログラムを相当遅くしますし、スレッドをサポートしていません。
他のケースでは、 perf
ツールや他の言語に特化したサンプリングプロファイラが、便利なデータを素早く出力できます。
Flamegraphs は、このようなサンプリングプロファイラの出力を便利に可視化するツールです。
さらに、プログラム言語や、作業中のタスクに特化したツールも使用するべきです。
例えば web 開発では、 Chrome や Firefox にビルトインされた開発ツールに、素晴らしいプロファイラが組み込まれています。
コードの遅い部分の原因が、システムがディスク読み込みやネットワークパケットなどのイベントを待機しているから、というケースもあります。
このようなケースでは、ハードウェア能力の観点から理論的な速度について簡単な計算をして、それが実際の測定値から外れていないか、確認するのが良いでしょう。
さらに、システムコールでの待機時間を解析する専門ツールもあります。ユーザのプログラムのカーネルトレーシングを実行する eBPF などがあります。特に、 bpftrace
は、このような低レベルでのプロファイリングを行う場合、必見です。
ブラウザのプラグインは何を使っていますか?
お気に入りをいくつか挙げます。ほとんどがセキュリティとユーザビリティに関連したものです。
- uBlock Origin - これは wide-spectrum ブロッカーで、広告をブロックするだけではなく、ページが実行しようとするサードパーティのコミュニケーションをすべて遮断します。設定に時間を割く気があるのならば、 medium mode 、もしくは hard mode を試してみてください。これらは、いくつかのサイトを十分な設定が行われるまで動かなくするだけでなく、オンラインセキュリティも格段に向上させます。もしくは、 easy mode もほとんどの広告やトラッキングを設定してくれる十分に良いデフォルトです。どのようなウェブサイトのオブジェクトをブロックするか、独自のルールの定義もできます。
- Stylus - Stylish のフォークで( Stylish は使わないように、ユーザの閲覧履歴を閲覧 することが知られています)、カスタムCSSスタイルシートをウェブサイトにサイドロードできるようになります。 Stylus を使用すれば、ウェブサイトの外見を簡単にカスタマイズしたり変更したりできます。サイドバーの削除、背景色の変更、テキストサイズやフォントの変更も可能です。頻繁に閲覧するウェブサイトの可読性を向上するのに素晴らしいプラグインです。さらに、 Stylus には userstyles.org で公開されている他のユーザが作成したスタイルを導入できます。例えば、有名なウェブサイトには、複数のダークテーマのスタイルシートがあります。
- 全画面スクリーンキャプチャ - Firefoxビルドイン と Chrome拡張 があります。ウェブサイト全体のスクリーンショットを撮影できます。参照のために印刷するよりも遥かに便利なことが多いです。
- Multi Account Containers - cookiesを「コンテナ」に分離することができます。これにより、 web を様々なアイデンティティで閲覧したり、ウェブサイトがアイデンティティ間で情報を共有できないようにします。
- パスワードマネージャ機能 - ほとんどのパスワードマネージャにはブラウザの拡張機能があり、認証情報をより簡単なだけでなく、より安全にウェブサイトに入力できるうようになっています。ユーザ名とパスワードを単純にコピー&ペーストするのと比較すると、これらのツールはまずウェブサイトのドメインがエントリ内にあるか整合を取り、有名なウェブサイトになりすまして認証情報を盗み出すフィッシング攻撃を防ぎます。
便利なデータ収集ツールには他に何がありますか?
データ収集の講義で取り扱う時間がなかったデータ収集ツールには、 jq
や pup
があります。それぞれ JSON と HTML のダータのパーサーに特化しています。
他の小技は column -t
コマンドで、ホワイトスペースで分離されたテキスト(整形されている必要なし)を、カラムで整形されたテキストに適切に変換します。
さらに一般的で柔軟性のあるデータ収集ツールを紹介すると、 vim と Python です。複雑で複数行に渡る変換には、 vim のマクロをツールとして非常に便利に使えます。 一連の動作を記録し、必要な回数だけ繰り返せは良いのです。 例えば、 講義ノート と(去年の ビデオ)には、 vim のマクロのみを使用して XMLフォーマットのファイルを JSON に変換する例が収録されています。
表形式のデータはしばしば CSV として登場しますが、 Python ライブラリの pandas が素晴らしいツールです。 グループ化、結合、フィルタなどの複雑な操作を簡単に定義できるだけでなく、データの様々な特性を簡単にプロットできます。 さらに、 XLS 、 HTML 、 LaTeX などの多くの表フォーマットへのエクスポートもサポートしています。 代替ツールとして、 プログラミング言語の R (議論の余地はあるが 悪い プログラミング言語)には、 データから統計を計算する機能が多くあり、パイプラインの最後のステップとして非常に便利です。 ggplot2 は、 R の素晴らしいプロット用ライブラリです。
Docker とバーチャルマシンの違いは何ですか?
Docker は、コンテナと呼ばれるより一般的な概念に基づいています。 コンテナとバーチャルマシンの違いは、バーチャルマシンはカーネルを含む OS のスタック全体を実行することです。カーネルがホストマシンと同じであっても実行されます。 コンテナが VM と異なるのは、カーネルの新たなインスタンスを実行するのを避け、代わりにホストとカーネルを共有する点です。 Linux では、これは LXC と呼ばれるメカニズムによって実装されています。一連の分離メカニズムを使用して、プログラムに独自のハードウェアで実行しているかのように思わせますが、実際はホストとハードウェアとカーネルをシェアしているのです。そのため、コンテナは完全な VM に対して低負荷です。 一方、コンテナの分離は弱く、ホストが同じカーネルを実行している場合のみ機能します。例えば、もし Docker を macOS で走らせているとして、 Docker が初期の Linux カーネルを取得するために Linux のバーチャルマシンを起動する必要がある場合、負荷は大きなままです。 最後に、 Docker はコンテナの特別な実装であり、ソフトウェア開発用に調整されています。そのため、奇妙な現象があります。例えば、 Docker のコンテナはデフォルトでは、再起動の間いかなるストレージにも残存しません。
各 OS の利点と欠点、選び方について教えてください(例:ある目的に最適な Linux のディストリビューション)
Linux のディストリビューションについては、数多くのディストリビューションがあるものの、 ほとんどの使用ケースについてほとんどがかなり同じような挙動をします。 Linux や UNIX の機能、内部構造のほとんどは、どのディストリビューションでも学べます。 ディストリビューションの根本的な違いは、パッケージのアップデートをどう取り扱っているかです。 Arch Linux のようないくつかのディストリビューションでは、ローリングアップデートポリシーを採用していて、あらゆるものが最新ですが非常に頻繁に壊れます。 一方、 Debian 、 CentOS 、 Ubuntu LTS リリースのような一部のディストリビューションは、 レポジトリにアップデートをリリースするのに遥かに保守的で、新機能を犠牲にする代わりに通常は非常に安定しています。 デスクトップとサーバーの双方で簡単かつ安定した体験をするためのおすすめは、 Debian または Ubuntu の使用です。
Mac OS は、素敵に磨かれたインターフェイスを持つ Windows と Linux の良い中間地点です。 しかし、 Mac OS は Linux よりむしろ BSD が基礎なので、 システムの一部やコマンドは異なります。 チェックすべき代替案は FreeBSD です。 FreeBSD で走らないプログラムもありますが、 BSD のエコシステムは Linux よりも断片化が少なく、ドキュメントも充実しています。 Windows は、 Windows アプリの開発や、解決が必要な難しい問題がある場合、 例えばゲーム向けの充実したドライバーのサポートなどが必要な場合以外にはおすすめしません。
デュアルブートシステムについては、最も実用的な実装は macOS の bootcamp で、他の組み合わせは、 特にディスク暗号化などの他の機能と組み合わせた場合、長期的に見て問題が起こる可能性があると考えています。
Vim vs Emacs?
我々 3 人は vim を主要エディタとして使っていますが、 emacs も良い代替案です。 両方を試して、どちらがしっくり来るか試してみるといいでしょう。 Emacs は vim のモーダルな編集に追随していませんが、これは Evil や Doom Emacs などの Emacs のプラグインで実現可能です。 Emacs を使用するメリットは、エクステンションを Lisp で実装できることで、 これは Vim のデフォルトのスクリプト言語、 vimscript より優れたスクリプト言語です。
機械学習アプリケーションに関して、ヒントや小技はありますか?
この講義での講義や宿題の一部は、 ML のアプリケーションに直接応用できます。 多くの科学の流派でそうであるように、 ML でも一連の実験を行い、何が動き、何が動かないか、確認したくなることがしばしばあるでしょう。 シェルツールを使って簡単かつ素早くこの実験を検索したり、 結果の統計を理解しやすい方法で取ることができます。 これには、特定のタイムフレーム内の全ての実験を選んだり、特定のデータセットを使用したもののみを選択するなどの使い方があります。 実験に関連したパラメータをすべてシンプルな JSON ファイルで記録すれば、これは講義で扱ったツールを使用して非常に簡単に実現可能です。 最後に、GPU にジョブを送る種類のクラスタで作業をしていないならば、 このプロセスを自動化する方法も検討するべきです。 非常に時間がかかるタスクになる上に、 MP も削られるからです。
Vimの小技は他にありますか?
いくつかの小技を紹介します。
- プラグイン - 時間を割いてプラグインの地平線を探索してみよう。 vim の欠点に対処するプラグインや、既存の vim のフレームワークと協調する新機能を追加する偉大なプラグインがたくさんある。これについては、 VimAwesome やその他のプログラマーのドットファイルが良い資料となる。
- マーク - vim では、
m<X>
でX
に相当するマークを設定できる。'<X>
でそのマークに戻れる。ファイル内や、ファイルを横断した特定の場所への移動を素早く行える。 - 移動 -
Ctrl+O
とCtrl+I
で、最近訪れた場所をそれぞれ前後に移動できる。 - UndoTree - vim には変更を記録するなかなか素晴らしいメカニズムが備わっている。他のエディタと異なり、 vim は変更のツリーを保存する。「取り消し」をし、さらに他の変更を行った後でも、 UndoTree を移動することで元々の状態に戻れる。 gundo.vim や undotree のようなプラグインは、このツリーをグラフィカルに表示する。
- Undo with time -
:earlier
と:later
コマンドはファイルの移動を、「 1 回につき 1 つの変更」ではなく、時間を基準できる。 - Persistent undo は vim の素晴らしいビルトイン機能で、初期状態では無効化されている。これは vim の軌道の間で取り消しの履歴を継続させる。
undofile
とundodir
を.vimrc
で設定することで、 vim はファイルごとの変更履歴を保存できる。 - リーダーキー - リーダーキーとは、ユーザがカスタムコマンドを設定できるようにしばしば手つかずになっている特別なキーである。パターンは通常は、このキー(おおよそはスペースキー)を押して離し、次のキーを押して特定のコマンドを実行するものである。プラグインがこのキーを使って独自の機能を追加することが多い。例えば、 UndoTree プラグインは
<Leader> U
で取り消しツリーを表示する。 - 高度なテキストオブジェクト - 検索のようなテキストオブジェクトも、 vim のコマンドで作成可能だ。例えば、
d/<pattern>
は与えたパターンの次のマッチを削除し、cgn
は最後に検索した文字列の次の出現箇所を変更する。
2FA とはどのようなもので、使うべき理由は何ですか?
2 要素認証(Two Factor Authentication、2FA)は、アカウントのパスワードの上にさらに保護のレイヤーを追加するものです。ログインの際、パスワードを知っているだけではなく、あるハードウェアデバイスにアクセス可能であることを「証明」する必要があります。これは、電話で SMS を受信することで実現できますが、 SMS 2FA に関しては 既知の問題 があります。私たちが支持するより良い代替案は、 U2F ソリューションを使用することで、例として YubiKey があります。
ウェブブラウザの違いについてコメントはありますか?
2020年時点でのブラウザの様相は、ほとんどが Chrome に似ているというものです。これは同じエンジン(Blink)を使用しているからです。 これは、 Blink をベースとした Microsoft Edge も、 WebKit をベースとした Safari も、これは Blink に似たエンジンですが、 Chrome の下位互換にすぎないということです。 Chrome は、パフォーマンスとユーザビリティの点においてまあまあ良いブラウザです。 他製品が必要ならば、 Firefox が私たちのおすすめです。 あらゆる点で Chrome に匹敵し、プライバシーの面では優れています。 他には、 Flow というブラウザはユーザの使用準備はできていませんが、新しいレンダリングエンジンを実装していて、 現在のものより速いと請けあっています。
Licensed under CC BY-NC-SA.