- 概要
- はじめに
- 環境
- VSCode のインストール
- Remote Development のインストール
- リモートマシンに公開鍵を追加する
- リモートマシンのVSCodeに拡張機能をインストールする
- インテリセンスを設定する
- VSCode でソースコードを確認する
- カーネルのビルド
- QEMUで指定したカーネルをブートする
- GDBでターゲットにアタッチする
- おわりに
- 変更履歴
- 参考
概要
Visual Studio Code (VSCode)では、短時間でエディタのセットアップすることができ、テキストエディタとして次の機能が使えることが判明した。
- 関数定義を参照する
- 関数呼び出し元を参照する
- 入力補完機能
- ホバーによるドキュメント表示
- シンタックスチェック
- シンボルの一斉置換
また、VSCodeではデバッグ機能が標準で提供されているので、VSCodeからGDBでアタッチしてデバッグすることもできた。
そこで本記事では、Linuxカーネルのコーディングに必要な設定手順について記載する。
はじめに
Visual Studio Code (VSCode)は、Microsoftが開発・提供しているオープンソースのエディタの一つである。
VSCodeでは、プログラマが必要とする機能 (補完機能やデバッグ機能など) がデフォルトで搭載されていることに加えて、拡張機能が豊富に提供されている。
そこで、VSCodeでソースコードリーディングするために、「初期設定に手間がかかるかどうか」と「実際に使ってみてどうなのか」を確認していくことにする。
環境
今回、Windows 10のローカルマシンからVSCodeを利用して、Ubuntu 20.04のリモートマシンにアクセスして、リモートマシン上にあるソースコードやツールチェーンを利用して、コードリーディングをすることを想定する。
ここでは、次のバージョンで動作を確認している。
Windows 10 Home
- VSCode v1.63.2
- Remote Development v0.21.0
Ubuntu 20.04.3
- C/C++ Extension Pack v1.1.0
VSCode のインストール
Visual Studio Code のサイト VSCodeは、WIndowsに加えてMacOSやLinuxにも対応している。
Remote Development のインストール
Remote Development は、コンテナ・リモートマシン・WSL内のファイルをアクセスできるVSCodeの拡張機能の一つ *1 である。
- アクティビティバーにある拡張機能アイコンを選択する
- 検索窓に「Remote Development」と入力する
- 検索候補にある「Remote Development」を選択する
- エディタグループにある「インストール」を選択する
インストールが完了すると、アクティビティバーに「リモート エクスプローラー」が追加される。
現在、ローカルマシンにはリモートマシンにアクセスするための設定をしていないため、サイドバーには何も表示されていない。
リモートマシンに公開鍵を追加する
既にローカルマシンからリモートマシンにSSHでリモートアクセスできる場合、公開鍵認証が必要ない場合には省略可能。
ここでは、Windows PowerShell を利用して公開鍵を生成をする。*2
コマンドが成功すると指定されたパスに秘密鍵と公開鍵がローカルマシンに生成される。 (ここでは、秘密鍵をid_rsa
、公開鍵をid_rsa.pub
とする)
公開鍵id_rsa.pub
を、何らかの手段(SSH, USBメモリ経由, クリップボードなど) でリモートマシンにコピーし、リモートマシンの.ssh/authorized_keys
に登録する。
その後、ローカルマシンのVSCodeに戻り、SSHの接続先を設定する。
- 「SSH TARGETS」にマウスオーバーすると表示される「Configure」を選択する
- SSH接続先を記述する
- サイドバーに記述したホスト名が出現するので、「Connect to Host in New Window」を選択する
SSH接続に成功した場合、新規ウインドウでリモートマシン内のファイルにアクセスすることができる。
- ステータスバーに接続先のホスト名が出力されていることを確認する
- アクティビティバーの「エクスプローラー」を選択する
- サイドバーから「フォルダーを開く」を選択し、Linuxのソースコードのトップディレクトリを選択する
リモートマシンのVSCodeに拡張機能をインストールする
Linuxカーネルのソースコードの多くはCプログラムとなっているため、リモートマシンにはC/C++開発用の拡張機能をインストールしていく。
その後、再読み込みを促されるので、「再読み込み」を選択する。
インテリセンスを設定する
Linuxカーネルでは、かなり複雑な依存関係を持つため、手動でコンパイルフラグを作成することは難しい。
幸いにも、Linuxカーネルではgen_compile_commands.py
と呼ばれるスクリプトが用意されている。
~/linux:$ ./scripts/clang-tools/gen_compile_commands.py
ビルド済みのカーネルツリーに対して、上記のコマンドを実行することでcompile_commands.json
ファイルが生成される。
上記の情報を渡してあげるためには、VSCodeの設定を変更する必要がある。
デフォルトのc_cpp_properities.json
が表示されるので、compileCommands
フィールドを追加する。
// 1: { "configurations": [ { "name": "Linux", "includePath": [ "${workspaceFolder}/**" ], "defines": [], "compilerPath": "/usr/bin/gcc", "cStandard": "gnu17", "cppStandard": "gnu++14", "intelliSenseMode": "linux-gcc-x64", "compileCommands": "${workspaceFolder}/compile_commands.json", } ], "version": 4 }
またクロスコンパイルを検討している場合には、compilerPath
やintelliSenseMode
を設定する。
これによりVSCodeでは、プロジェクト内にあるcompile_commands.json
を用いてインテリセンスを設定する。
VSCode でソースコードを確認する
関数定義を参照する
<Alt>
+<F12>
関数名や変数名にカーソルを合わせ、<Alt>
+ <F12>
を押下すると、その関数の定義元が表示される。
関数呼び出し元を参照する
<Shift>
+<F12>
関数名や変数名にカーソルを合わせ、<Shift>
+ <F12>
を押下すると、その関数の呼び出し元が表示される。
入力補完機能
<Ctrl>
+<Space>
関数や変数を入力すると、自動でポップアップが表示される。また、<Ctrl>
+ <Space>
を入力でも同様にポップアップが表示される。
ホバーによるドキュメント表示
マウスオーバー
シンタックスチェック
シンボルの一斉置換
<Ctrl>
+<F2>
カーネルのビルド
規模が大きい場合には、コードリーディングだけでプログラムの仕様を完全に理解することは難しい。
そこで、実際にプログラムを動かしてみることで、より詳細な挙動を確認することができる。
まずは、VSCodeからカーネルをビルドできるような設定をしていく。
VSCodeでは、"タスク"と呼ばれる単位で何かしらの処理を実行することができる。
まず初めに、カーネルのビルド/クリーンアップするタスクを追加していく。
- 「ターミナル」を選択する
- 「タスクの構成」を選択する
- 「テンプレートからtasks.jsonを生成する」を選択する
これにより、新規エディタが立ち上がり、tasks.jsonのテンプレートが表示される。
次のようなmake -j$(nproc) bzImage
を実行する Build bzImage
タスクとmake clean
を実行するClean
タスクを追加する。
// 1: { // See https://go.microsoft.com/fwlink/?LinkId=733558 // for the documentation about the tasks.json format "version": "2.0.0", "type": "shell", "echoCommand": true, "tasks": [ { "label": "Build bzImage", "command": "make", "args": [ "-j$(nproc)", "bzImage" ], "group": { "kind": "build", "isDefault": true }, }, { "label": "Clean", "command": "make", "args": [ "clean" ], "group": "none" }, ] }
これにより、ビルドタスクとしてデフォルトでmake -j$(nproc) bzImage
が実行されるようになった。
ビルドタスクを実行するためには、<Ctrl>
+ Shift
+ B
がショートカットとして割り当てられている。
QEMUで指定したカーネルをブートする
ビルドしたカーネルをお試しで動作確認する場合、QEMU*3でエミュレートすると効率が良い。
そこで、VSCodeからQEMUを利用して、カーネルをブートできるような設定をしておく。
カーネルのビルドと同様にQEMUでブートするようなタスクを作成する。
// 1: { // See https://go.microsoft.com/fwlink/?LinkId=733558 // for the documentation about the tasks.json format "version": "2.0.0", "type": "shell", "echoCommand": true, "tasks": [ { "label": "Build bzImage", "command": "make", "args": [ "-j$(nproc)", "bzImage" ], "group": { "kind": "build", "isDefault": true }, }, { "label": "Clean", "command": "make", "args": [ "clean" ], "group": "none" }, { "label": "Boot kernel in QEMU", "command": "qemu-system-x86_64", "args": [ "-kernel", "arch/x86_64/boot/bzImage", "-drive", "file=rootfs.ext4,if=ide,format=raw", "-nographic", "-append", "'root=/dev/sda console=ttyS0 init=/bin/sh'", "-s", "-S" ], "group": "none" }, ] }
- タブバーから「ターミナル」を選択する
- 「タスクの実行」を選択する
作成したタスクのラベル (Boot kernel in QEMU) を選択すると、ターミナルに実行結果が出力される。
GDBでターゲットにアタッチする
上記の手順にて、ビルドしたカーネルを起動させているのでVSCodeからGDBにアタッチしてみる。
VSCodeでは、デバッグ機能が標準として提供されており、GDBを用いたテンプレートが用意されている。
今回は、そのテンプレートを利用して、QEMUで起動させたカーネルにアタッチする。
127.0.0.1:1234
にGDBで接続するためにlaunch.json
を編集する。
// 1: { // IntelliSense を使用して利用可能な属性を学べます。 // 既存の属性の説明をホバーして表示します。 // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "name": "kernel-debug", "type": "cppdbg", "request": "launch", "miDebuggerServerAddress": "127.0.0.1:1234", "program": "${workspaceFolder}/vmlinux", "args": [], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [], "externalConsole": false, "logging": { "engineLogging": false }, "MIMode": "gdb", } ] }
上記のファイルを保存した結果、launch.jsonで作成したサイドバーが更新される。
試しに、ext4_fill_super
関数にブレークポイントを設置して、GDBでデバッグしてみる。
おわりに
VSCodeは非常に便利なテキストエディタであり、豊富な機能が提供されている。
今回の場合では、1時間足らずで次のような機能が有効で確認することができた。
- 関数定義を参照する
- 関数呼び出し元を参照する
- 入力補完機能
- ホバーによるドキュメント表示
- シンタックスチェック
- シンボルの一斉置換
変更履歴
- 2022/2/1: 記事公開