2026年1月5日月曜日

Rust@はじめてみた(インストール)

Rust@はじめてみた(インストール)

仕事が落ち着いて、年も明けたので、新しいことを始めたい。
そういえば、Rustという言語があるということは知っていたけれど、何も知らないなと思ってちょっとやってみるか!と。C言語大好き人間だけど、Rustにその座が取れるだろうか。

Rustとは

何はともあれ、ホームページ( https://rust-lang.org/ja/ )にいくと3つのキーワードが挙げられていた。

  • パフォーマンス
    ガベージコレクタが無くメモリ効率が良く非常に高速らしい。組込み機器上で動作させることも念頭に置かれているようだ。
  • 信頼性
    なんとなく知っていたのはこっちのほうで、コンパイル時に様々な種類のバグを見つけられるらしい。ベアメタルプログラミングとしてここらの機能がどれだけ利用できるのか期待。信頼性という言葉、好き。
  • 生産性
    コンパイラ君のエラーメッセージが丁寧らしい。最近のgccもすごい親切だからな・・・。とはいえ、ツール類が色々揃っているらしいというところは手を付けるに当たって安心感がある。

Rustの活用事例としては、FireFox、Dropboxなどなどあるらしい。最近LinuxやWindowsもRustに置き換えていくみたいな話があった様な(むしろこの話題で勉強する気になった)

インストール

さすがに日本語ドキュメントも豊富で、こちら( https://doc.rust-jp.rs/book-ja/ch01-01-installation.html )を参照しながらUbuntuにインストールする。

  • rustup
    Rustのバージョンと関連するツールを管理するコマンドラインツールだそう。

まず、これを打て。

curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh

色々説明されて、最後に入力を求められた。

1) Proceed with standard installation (default - just press enter)
2) Customize installation
3) Cancel installation
>

ドキュメントには無いが、1を選択しておく。

Rust is installed now. Great!

To get started you may need to restart your current shell.

無事インストールされたようだ。
環境変数も弄ってくれている様なので反映してから、とりあえずバージョン表示。

$ source ~/.bashrc
$ rustc --version
rustc 1.92.0 (ded5c06cf 2025-12-08)

アップデート

下記コマンドで簡単にできるらしい。忘れそう。

$ rustup update

アンインストール

下記コマンドで簡単にできるらしい。忘れてもいいか。

$ rustup self uninstall

2024年9月23日月曜日

git@よく使うコマンド早見表

git@よく使うコマンド早見表

gitでよく使うコマンドをまとめる。

add

コマンド 説明
git add . ワークディレクトリ配下全てのファイルをステージ(インデックスに記録)する
git add <ファイル> 指定したファイルをステージ(インデックスに記録)する
git add -u ワークツリー内でバージョン管理中の全てのファイルをステージ(インデックスに記録)する

branch

コマンド 説明
git branch ローカルブランチのリストを表示する
git branch -r リモートブランチのリストを表示する
git branch -a ローカルブランチとリモートブランチのリストを表示する
git branch <ブランチ名> 指定したブランチを作成する
git branch -d <ブランチ名> 指定したブランチを削除する

checkout

コマンド 説明
git checkout <ブランチ名> 指定したブランチに移動する
git checkout -b <ブランチ名> 新しくブランチを作成してそのブランチに移動する

clone

コマンド 説明
git clone <リポジトリアドレス> リポジトリアドレスからクローンする
git clone --recursive <リポジトリアドレス> リポジトリ内のサブモジュールもクローンする

commit

コマンド 説明
git commit コミットする(コミットログを編集するエディタが起動する)
git commit -m <コミットログ> 指定したコミットログでコミットする
git commit -a git add -uとgit commitを連続して実行する

config

コマンド 説明
git config --list 設定を確認する
git config --global core.editor vim エディタをvimに設定する
git config --global diff.tool vimdiff diffをvimで見るように設定する

diff

コマンド 説明
git diff ワークツリーとインデックス間のファイル差分を表示する
git diff HEAD ワークツリーと最新のコミット間のファイル差分を表示する
git diff – cached インデックスと最新コミット間のファイル差分を表示する

fetch

コマンド 説明
git fetch リモートリポジトリが更新されているか調べる

log

コマンド 説明
git log コミットログを表示する
git log -p コミットログとコミット毎の差分をパッチ形式で出力する
git log -<ログ数> コミットログを指定した数だけ表示する
git log --pretty=short 各コミットログの最初の1行(要約)だけを表示する

merge

コマンド 説明
git merge <ブランチ名> 現在のブランチに指定したブランチをマージする

pull

コマンド 説明
git pull 現在のブランチの最新コミットとリモートブランチの最新コミットをマージしてコミットする

push

コマンド 説明
git push <登録リポジトリ名> <ブランチ> 登録リポジトリのブランチにプッシュする

status

コマンド 説明
git status 現在の状態を表示する

submodule

コマンド 説明
git submodule init ローカルの設定ファイルを初期化する
git submodule update [<サブモジュールディレクトリ>] 登録されているサブモジュールをチェックアウトする
git submodule update --remote [<サブモジュールディレクトリ>] 登録されているサブモジュールをリモートリポジトリの内容にマージする(サブモジュールディレクトリ内でgit fetch;git mergeの実行と同等)
git submodule add -b <ブランチ> <リポジトリアドレス> 指定したリポジトリと同じディレクトリ名で指定したブランチのサブプロジェクトのデータを格納する

2024年7月21日日曜日

MochiOS開発記@突然のTripleFaultの原因判明!

 デバッグログ強化を進めたお陰でタイトルの通り原因判明に至った。

以下、なりゆき。


(1) デバッグログをメモリ上にも吐き出すように機能追加

(2) TripleFaultを再現させるも、吐き出したメモリ上のログが破壊されていることに気づく

(3) GDB繋いでログメモリ先頭アドレスにwatchpoint設定して監視するも、引っ掛からない

 ⇒つまり、別の仮想アドレスからメモリ破壊していることに気づく

(4) ページマッピング箇所にトレースログを仕込み

(5) どんどんページに割り当ててる物理アドレスが加算されていることに気づく

 ⇒つまり、メモリリーク

(6) 怪しい所にどんどんトレースログ追加していき原因判明



直接的原因1:

 プロセスのヒープ領域を縮小する時に、ページマッピング解除は行っているが、割り当てている物理メモリを解放していなかった。

直接的原因2:

 普通に設計上固定的に使っている物理メモリ領域をカーネルの物理メモリ管理くんが未使用と認識していて、割当てを行っていた。


直接的原因1の動機的原因(根本)は、後で実装すればいいや精神でテキトーに実装したからだな・・・。ページマッピング解除時に関数のインタフェース仕様が理由で割り当てていた物理メモリアドレスがわからないから解放ができず、割と大がかりな構成変更が必要だったから後回しにしていたようだ。なんにも残してない自分が悪いね。個人開発でもTODO管理やチケット管理ってやっぱ必要だと思う。うん。


直接的原因2のほうは・・・なんでだろうね。どう考えていたか覚えていない。



あー超スッキリした!メモリマネージャ大改造しよ。これが当面の目標。


2024年6月1日土曜日

MochiOS開発記@デバッグログ強化検討

 MochiKernelのデバッグログは下記情報を持っている。

・ログ出力したモジュール-サブモジュール(つまりひとつのソースファイル)のID

・ログ出力した行数

・文字列


デバッグログ種別やレベルなどは持たせていなくて、好き勝手していた。

いざ不具合があると情報が足りなくなるし、不具合がないと不要なログで埋め尽くされて見たいものが見れなくなる、ということに悩まされてきたので、種別の概念を追加することにする。


大体、世の中のシステムログ種別は以下のような感じか(超適当)

種別 概要
emergency システムが使用できなくなった系
alert 対処しないとまずい系
critical 致命的で対処しようがない系
error エラー全般
warning 警告全般
notice エラーでも警告でもないがちょっとあやしい系
informational なんか処理したよ系
debug プログラムデバッグ情報系

参考にしてこんな感じにしよう。(全然参考にしてない)
種別 概要
abort あぼーと。もう何もできない。死んだ。
error 想定外のエラー。処理を続けられないので中断。
warning 想定内のエラー。処理を続けられないので中断。
info なんか処理した。頻度低(HW割込みとかタスクスイッチ系はダメ)。
trace コードここ通ったよ。頻度低(HW割込みとかタスクスイッチ系はダメ)。
temp デバッグ中に使う専用。残さない。

種別ごとに有効化マクロ定義しとこ。

2024年5月28日火曜日

MochiOS開発記@当面の目標

突然のフリーズ。 カーネルログを見ても解析困難。
というわけで、このバグ修正を当面の目標にしよう。
INT14なのでページフォルトなのだけど、誰かがメモリ破壊してる気がするなぁ。。。
とりあえず、カーネルログのレベル実装してもうちょい情報増やしてみよう。

2024年3月3日日曜日

CUnit@単体テストはじめ

CUnit@単体テストはじめ

はじめに

自作kernel作るにあたってDebug機能が欲しくなり。
snprintfが必要となり。
やっぱlibc欲しいなとlibcを作り始め(newlib使ってもよかったんだけど、自作楽しいので)。
snprintfを作ったのだが、これ動くのか?と。
単純に作業量2倍になるので、趣味でテスト系は避けてきたのだけど、やっぱ避けて通れないよねテスト。
というわけで、CUnit使うか・・・の備忘録。

ライブラリインストール

sudo apt-get install libcunit1-dev

テスト対象コード例(target.c)

int target_func( void )
{
	return 5;
}

テストコード例

#include <CUnit/CUnit.h>
#include <CUnit/Basic.h>

#include "target.c"

void test_func_1( void )
{
	ret = target_func();

	CU_ASSERT_EQUAL( ret, 5 );
}

int main( void )
{
	CU_pSuite suite;

	/* テストレジストリ初期化 */
	CU_initialize_registry();
	
	/* テストスイート追加 */
	suite = CU_add_suite( "TestSuite", NULL, NULL );

	/* テスト追加 */
	CU_add_test( suite, "test1", test_func_1 );

	/* テスト実行 */
	CU_basic_set_mode( CU_BRM_VERBOSE );
	CU_basic_run_tests();

	/* テストレジストリ削除 */
	CU_cleanum_registry();

	return 0;
}

static関数をテストしたい場合も考慮して、テスト対象コードをinclude。

サブ関数をstub化

サブ関数をstub化する方法はいくつかあるが、テスト対象コードをいっさい変えずにやるのは無理っぽい。
下記が最善策かなぁ。検索してもいい案が出てこないので自分で考えてみた。

#ifndef CALL
#define CALL( a ) a
#endif

#ifndef PROTO
#define PROTO( a, b ) a b
#endif

PROTO( extern int, target_sub( void ) );

int target_sub( void )
{
	return 5;
}

int target_func( void )
{
	return CALL( target_sub() );
}

テストコードは、テスト対象コードのincludeの前に下記を定義しておく

#define CALL( a ) stub_##a
#define PROTO( a, b ) a stub_##b

テスト対象コードincludeの後に下記を定義する

int stub_target_sub( void )
{
	return 5;
}

2022年11月22日火曜日

linux@VPN構築

linux@VPN構築

はじめに

在宅勤務になってから、ほぼ外出することが無くなり、外出先から自宅ネットワークに繋ぐことも無くなっていた。久しぶりに繋いでみたら、繋がらない。どうやら使っていたDDNSサービス(ieserver)が終了したらしく、他にも色々と理由があってダメだったので、見直すことにした。

ネットワーク構成は下記の通り。

My home
My Device
Rooter
VPN server
VPN Client
INTERNET
DDNS

VPN serverは、Debian GNU/Linux 9 (stretch)
VPNClientは、WindowsだったりAndroidだったり。

ドメイン名設定

私の自宅インターネット接続環境は固定IPアドレスではなく、再接続なんかの度にコロコロIPアドレスが変わるので、外出先からはvpn.mochi.cоm(仮)みたいなドメイン名を使ったアクセスをできるようにする必要がある。
これは、どこかのDDNSサービスを使ってドメイン名を取得し、自宅サーバから定期的に自分のグローバルIPアドレスを更新してあげることで実現できる。

DDNSサービスの選択

今回、適当に検索して色々出てくるなか、下記サービスを使うことにした。

DDNS Now

簡単に説明すると、

  • 無料
  • ホスト名:アカウント名.f5.si ※siはスロベニアらしい
  • Aレコード設定可
  • AAAAレコード設定可
  • TXTレコード設定可

こんな素晴らしいサービスを無料で提供して頂けることに感謝。
そして、もともと使っていたieserver並みにシンプルに使える。

crondでIPを自動更新する

自宅のIPアドレスはインターネット再接続の度に変わってしまい、その都度手動でDDNSサービスに再登録するのは面倒な上に、外出先からはIPアドレスが判らず再登録できないので、VPNサーバを使って自動的にIPをDDNSサービスに再登録する様にする。

  1. crontabを開く
crontab -e
  1. 10分毎に実行するコマンドを追加する
0,10,20,30,40,50 * * * * wget -O DDNSNow_update.log "https://f5.si/update.php?domain=ユーザ名&password=パスワード"

パスワードはAPIトークンでもOK。というかAPIトークンがいいかな。
この設定だと、ログ(DDNSNow_update.log)はホームディレクトリに吐かれる。

PPPoE接続設定

以前の私のインターネットはPPPoE接続だったのだが、FTTHなのに通信速度が遅く、在宅勤務となった際に安定したビデオ会議が出来なかったため、IPoE・IPv4 over IPv6接続に切り替えていた。
ただし、この接続はIKEv2のVPNで使用する500番や4500番などの特定ポートが使用できないため、ここでも外出先からVPN接続できない要因となっていた。
これまでの環境は維持しながらVPN接続できるようにもしたいため、ルータでIPoE接続しつつPPPoEパススルーさせ、VPNサーバから直接PPPoE接続させることで、通常のインターネット通信は高速のまま外部からのVPN接続を可能にさせる。
(これは通信事業者・プロバイダによって出来たり出来なかったりするかも)

My home
IPoE
PPPoE
PPPoE
Rooter
-PPPoE pass through-
VPN server
VPN Client
INTERNET

基本的なファイアウォール設定

VPNサーバもグローバルIPアドレスを獲得したわけなので、直接攻撃されることができて超危険。ファイアウォールを設定する。

  1. ufw(ファイアウォール)インストール
sudo apt-get install ufw
  1. 全アクセスの拒否
sudo ufw default deny
  1. ローカルLAN(192.168.1.*)からの全アクセスを全許可
sudo ufw allow in from 192.168.1.0/24
  1. ファイアウォール有効化
sudo ufw enable
  1. ログレベルの設定
    お好みで。フラッシュメモリを温存したいので、ログを無効にする。
sudo ufw logging off

出したい場合はoffをonに、またはlowに。

pppoeconf設定

  1. pppoeconfインストール
sudo apt-get install pppoeconf
  1. 接続設定
pppoeconf

色々質問されるが、大体は「はい」を選択すれば問題ない。

PPPoE接続

pon dsl-provider

接続状況確認

ip address show

(参考)PPPoE切断

poff dsl-provider

VPNサーバ構築

認証方式の選択

VPNのサーバ/ユーザ認証方式は、相互に証明書を使った認証(EAP-TLS)にする。
下記のような鍵構成にする。

My Home
My Device
クライアント証明書事前登録
ルート証明書事前配布
ルート証明書事前配布
オレオレ認証局
・個人鍵       
・公開鍵(ルート証明書)
VPNサーバ
・ルート証明書    
・個人鍵       
・公開鍵(サーバ証明書)
・クライアント証明書 
VPNクライアント
・ルート証明書    
・個人鍵       
・公開鍵(ユーザ証明書)

ユーザ証明書とサーバ証明書は、オレオレ認証局の個人鍵によって署名し、オレオレ認証局の公開鍵(ルート証明書)によって正しさを検証することができる。
VPN接続時、VPNサーバはクライアントにサーバ証明書を送信し、クライアントは事前配布済のルート証明書を使ってサーバを認証する。同様にクライアントはVPNサーバにクライアント証明書を送信し、ルート証明書を使ってクライアントを認証する。
(なお、VPNサーバにクライアント証明書を事前登録しておく理由は、失効済証明書で認証を防ぐため)

VPNサーバ設定

StrongSwanを使ってlinux上にVPNサーバを構築する。

StrongSwanインストール

sudo apt-get install strongswan

ipsecを設定する

/etc/ipsec.confを修正し、VPN構成を設定する。

conn ikev2-vpn
	# 基本設定
	auto=add
	keyingtries=1
	keyexchange=ikev2

	# VPNサーバ設定
	left=%any
	leftsubnet=0.0.0.0/0
	leftcert=server-cert.pem
	leftid=vpn.mochi.com
	leftsendcert=always
	
	# VPNクライアント設定
	right=%any
	rightauth=eap-tls
	rightcert=mochi-cert.pem
	rightca="CN=vpn.mochi.com"
	rightid=mochi
	rightsourceip=192.168.1.192/26
	rightdns=8.8.8.8,8.8.4.4
	
	# VPNクライアント生存確認設定
	dpddelay=60s
	dpdtimeout=20s
	dpdaction=clear
項目 説明
auto connのロード方法と接続タイミング。「add」は、ロードだけで接続しない(サーバ設定なので接続も何もない)設定
keyingtries 接続試行回数
keyexchange 鍵交換方法
left VPNサーバのローカルIPアドレス
leftcert VPNサーバ証明書のパス(絶対パスまたは/etc/ipsec.d/certsからの相対パス)
leftid VPNサーバ証明書のsubject(公開鍵の発行者)の識別名
leftsendcert VPNサーバ証明書をVPNクライアントに渡す方法
right VPNクライアント側のエンドポイントIPアドレス
rightauth VPNクライアントの認証方法
rightcert VPNクライアント証明書のパス(絶対パスまたは/etc/ipsec.d/certsからの相対パス)
rightca VPNクライアント証明書の検証に使用する認証局のDN(Distingished Name)。(/etc/ipsec.d/cacertsの中から該当するDNのルート証明書を使って検証される)
rightsourceip VPNクライアントに割り当てるIPアドレスの範囲
rightdns VPNクライアントに伝えるDNSアドレス
dpddelay 通信の生存確認間隔(デフォルトは30s)
dpdtimeout 生存確認応答待ちタイムアウト(デフォルトは150s)
dpdaction 生存確認できなかった場合のアクション。clearは接続終了を意味する。

ユーザ認証情報を設定する

サーバの秘密鍵もここに設定しておく。
/etc/ipsec.secretsを修正する

: RSA "server-key.pem"

鍵・証明書作成

作業ディレクトリ作成

下記の通り作業ディレクトリを作成して、そのディレクトリ内で作成する。

mkdir ~/pki
mkdir ~/pki/cacerts
mkdir ~/pki/certs
mkdir ~/pki/private
chmod go-rwx ~/pki/private
ディレクトリ 概要
cacerts ルート証明書を格納
certs 証明書を格納
private 個人鍵(秘密鍵)を格納

オレオレ認証局の個人鍵・証明書作成

  1. オレオレ認証局の個人鍵を作成する
pki --gen --type rsa --size 4096 --outform pem > ~/pki/private/ca-key.pem
  1. オレオレ認証局の公開鍵証明書(ルート証明書)を作成する
オレオレ認証局個人鍵
ca-key.pem
ルート証明書
ca-cert.pem
pki --self --ca --lifetime 3650 --in ~/pki/private/ca-key.pem --type rsa --dn "CN=ca.mochi.com" --outform pem > ~/pki/cacerts/ca-cert.pem

※CNの値は適切に変更すること。

VPNサーバの個人鍵・証明書作成

  1. サーバの個人鍵を作成する
pki --gen --type rsa --size 4096 --outform pem > ~/pki/private/server-key.pem
  1. サーバの公開鍵証明書(サーバ証明書)を作る
VPNサーバ個人鍵
server-key.pem
VPNサーバ公開鍵
VPNサーバ証明書
server-cert.pem
オレオレ認証局個人鍵
ca-key.pem
pki --pub --in ~/pki/private/server-key.pem --type rsa | pki --issue --lifetime 1825 --cacert ~/pki/cacerts/ca-cert.pem --cakey ~/pki/private/ca-key.pem --dn "CN=vpn.mochi.com" --san vpn.mochi.com --flag serverAuth --flag ikeIntermediate --outform pem > ~/pki/certs/server-cert.pem

※CNと-sanの値はDDNSサービスで取得したドメイン名に変更すること。

クライアントの個人鍵・証明書作成

  1. クライアントの個人鍵を作成する
pki --gen --type rsa --size 4096 --outform pem > ~/pki/private/mochi-key.pem
  1. クライアントの公開鍵証明書(クライアント証明書)を作る
クライアント個人鍵
mochi-key.pem
クライアント公開鍵
クライアント証明書
mochi-cert.pem
オレオレ認証局個人鍵
ca-key.pem
pki --pub --in ~/pki/private/mochi-key.pem --type rsa | pki --issue --lifetime 1825 --cacert ~/pki/cacerts/ca-cert.pem --cakey ~/pki/private/ca-key.pem --dn "CN=mochi" --san mochi --outform pem > ~/pki/certs/mochi-cert.pem

※ファイル名は適切に変更すること。
※CNと-sanの値は適切に変更すること。

  1. pkcs12(pfx)形式に証明書を変換
クライアント証明書
mochi-cert.pem
クライアント証明書
mochi.p12
クライアント個人鍵
mochi-key.pem
openssl pkcs12 -export -inkey ~/pki/private/mochi-key.pem -in ~/pki/certs/mochi-cert.pem -certfile ~/pki/cacerts/ca-cert.pem -caname "ca.mochi.com" -name "mochi" -out ~/mochi.p12

これは、クライアント側で証明書をインストールする際に使用する。

作業ディレクトリコピー

/etc/ipsec.dに作業ディレクトリ内容をそのままコピーする

sudo cp -r ~/pki/* /etc/ipsec.d/

IPsec再起動

sudo ipsec restart

VPN用ファイアウォール設定

IKEv2の鍵交換でUDP500番と4500番を使用するため、下記を用いてそのポートを解放する。

sudo ufw allow 500,4500/udp

Rust@はじめてみた(インストール)

Rust@はじめてみた(インストール) 仕事が落ち着いて、年も明けたので、新しいことを始めたい。 そういえば、Rustという言語があるということは知っていたけれど、何も知らないなと思ってちょっとやってみるか!と。C言語大好き人間だけど、...