2021年11月23日火曜日

github@パスワード認証でpushできなくなった

github@パスワード認証でpushできなくなった

はじめに

最近、漸くコードをイジれて、久しぶりにgithubにpushしようとしたのだが、

$ git push origin develop
Username for 'https://github.com': MasterMochi
Password for 'https://MasterMochi@github.com':
remote: Support for password authentication was removed on August 13, 2021. 
Please use a personal access token instead.
remote: Please see https://github.blog/2020-12-15-token-authentication-requirements-for-git-operations/ for more information.
fatal: Authentication failed for 'https://github.com/MasterMochi/mvfs.git/'

あれ、pushできな~い。なになに・・・

パスワード認証のサポートは2021年8月13日に削除されました~。
代わりにパーソナルアクセストークンを使ってくれ~

そういえば、以前pushした時にそんな警告が出ていた気がする。承認方法変わったのか。
8月ってダイブ前だな・・・

誘導されたページを見てみる

https://github.blog/2020-12-15-token-authentication-requirements-for-git-operations/
前置きはすっ飛ばして、"What you need to today"をテキトーに読むと、

今日すべきこと

  • 開発者さんのために、もしGitHub.comでGit操作を承認するためにパスワード使ってんなら、HTTPS (推奨)かSSH鍵を介した パーソナルアクセストークン を使わなきゃダメよ。

うん、で?と思ったら、「パーソナルアクセストークン」にリンクがついてて、そこに飛ぶと生成方法が書いてあった。

パーソナルアクセストークン取得

  • githubページにアクセス
  • 自分のアイコンから「Settings」に飛ぶ
  • 左のメニューから「Developer settings」に飛ぶ
  • 左のメニューから「Personal access tokens」に飛ぶ
  • 「Generate new token」をクリック
  • 「Note」に適当にトークンの説明を書く
  • 「Expiration」を適当に設定(No expirationにしちゃった…無期限)
  • 「Select scopes」で「repo」にチェックいれる
  • 「Generate token」をクリックしてトークンを取得

トークン使ってpush

passwordに取得したトークン入れるだけでOKだった。

2019年9月17日火曜日

MochiOS@仮想ファイルシステムの作成part10

MochiOS@仮想ファイルシステムの作成part10

前提知識無しで作るなんちゃって仮想ファイルシステムpart10。

開発日記です。独り言です。

これまでのあらすじ

part 内容
0 仮想ファイルシステムを作りたい宣言をする。
1 ざっくり仮想ファイルシステムの機能を決める。
が、機能呼出し先の仮想ファイルシステムのタスクIDをどう取得するかという問題に気付く。
2 カーネルにタスク名登録機能を実装した。
これでタスク名からタスクIDを取得する事が出来る様になるハズ、なので試したいが試す方法が無い事に気付き、ログ出力タスクの開発を宣言する。
3 ログ出力の為に使うvsnprintf()の仕様を調べる。
4 ログ出力タスクを開発してタスク名からタスクIDの取得機能が正しく動いている事が確認できた。
5 mount機能を実装した。たぶんできてる。
6 FDどうやって管理しようかー。メッセージのやり取り制御を状態遷移で制御しようかー。とか考えて、open機能を実装した。たぶんできてる。
7 openと同じようなシーケンスなので、メッセージとちょっとやる事変えて簡単にwrite機能を実装できちゃった。
8 writeと同じようなシーケンスなので、メッセージとちょっとやる事変えて簡単にread機能を実装できちゃった。
9 readと同じようなシーケンスなので、メッセージとちょっとやる事変えて簡単にclose機能を実装できちゃった。

応用

これまでmount、open~closeまでさくっと何も考えずに実装してきた。(そういえばunmount実装してないな。まいいか)
全てはドライバとアプリ間のインタフェースを作ることがひとまずの目的だったので、ドライバを作ってみなければ。

というわけでns16550ドライバを作った。
ns16550は所謂、RS-232C、COMポート、シリアルポート、UARTなどと呼ばれているハードウェアで、割りと制御が簡単。

それぞれ16byteの転送バッファと受信バッファがあって、書き込む(VfsWrite)時は転送バッファがフルでなければ1byteづつ書き込んでフルの時は転送バッファ空割り込みが来るまで待つ。読み込む時は受信割り込みが来たときに1byteづつ読み込んでいたデータを返すだけ。

mvfsメインスレッド受信スレッド転送スレッドNS16550VfsReadReqVfsReadRespVfsWriteReq転送バッファ書込転送要求VfsWriteResp転送バッファ空割込み割込み要求転送バッファ読込書込転送バッファ読込書込受信割込み読込受信バッファ書込み読込受信バッファ書込みVfsReadReq受信バッファ読込VfsReadRespmvfsメインスレッド受信スレッド転送スレッドNS16550

MochiKernelのメッセージパッシングはキューがなく、即座にメッセージ受信をしないと仮想ファイルサーバがブロックされてシステムの性能が悪くなってしまうので、メインと受信と転送用に1プロセス3スレッド構成に。
(MochiKernelにスレッド機能なんて無かったので、作った。)

とまぁ、これだけでかなりのネタになるんだけれど、割愛。
⇂がコミットログ。
https://github.com/MasterMochi/drv-ns16550/commit/a09994d07188ec84b663b902f6dbc07509cc44de

本題はこれから。

ttyサーバを作りたいが…

tty「サーバ」って書くと???になるのだけれど、要はttyドライバです。MochiOSではサーバープロセスとしてttyファイルを提供するので「サーバ」にしているだけです。

そんで考えたのだけれど、次のシーケンスで悩みが出てくる。

  1. ユーザアプリがttyサーバに行読込み(cockedモード)
  2. ttyサーバがドライバからデータ読込み
  3. 受信データ無しのため、読込サイズ0で応答。
NS16550ドライバttyサーバユーザアプリ1. VfsRead...Read2. VfsRead...Read3. 受信データ無しの為、サイズ0応答どうやって待ち合わせる…?NS16550ドライバttyサーバユーザアプリ

(シーケンス図では、仮想ファイルサーバは省略。それぞれのインタフェースは仮想ファイルサーバ上で行われる。そのためVfsRead…Readのような形式で記載。上位からはReadを起動し、それを受け取って仮想ファイルサーバから下位へVfsReadが起動される。)

ttyサーバは行データが揃うまでユーザアプリへRead要求を返さない。行データが揃うまで、ドライバから文字を読み続けなければいけないわけだけど、ドライバは受信データが無い(EOF)ので直ぐに読込サイズ0でReadを返す。
(ところが上のコミットではドライバがブロックする設計ミス。。。修正する。)

今、実装済みの機能でこれを実現するには、ttyサーバはドライバへのReadを繰り返すしかない。

NS16550ドライバttyサーバユーザアプリVfsRead...ReadVfsRead...ReadVfsRead...ReadVfsRead...ReadVfsRead...ReadVfsRead...ReadVfsRead...ReadNS16550ドライバttyサーバユーザアプリ

これは、もう、CPU100%一直線。

Select/VfsReady機能を追加する

説明しなくても大体わかると思うけど、selectです。指定したファイルディスクリプタの読み込みまたは書き込みが出来るまで待ち合わせます。
VfsReadyはファイルの読み込みまたは書き込み準備が出来た事を意味する通知。

NS16550NS16550ドライバ仮想ファイルサーバttyサーバSelectレディチェック。読込・書込ともレディでないので待ち合わせ受信割り込み読み込みVfsReadyレディ設定ReadVfsReadデータ & レディ状態読込レディ設定データWriteVfsWriteレディ状態書込レディ設定NS16550NS16550ドライバ仮想ファイルサーバttyサーバ

いちいちSelectで指定した全てのFDに対応するMountプロセスにレディ状態を問い合わせると、メッセージのやり取りが増えて待ち合わせ状態の管理や時間がかかるので、レディ状態は仮想ファイルシステムでも保持する仕様にした。その為、VfsRead応答に最新のレディ状態を含める様に修正する。

以下、メッセージ仕様。

■ Select要求メッセージ

offset size 内容 意味
0x00 4 機能ID 0x0000_0009 Select
0x04 4 タイプ(要求/応答) 0x0000_0000 要求
0x08 4 読込監視グローバルFD数 0~1024 -
0x0C 4 書込監視グローバルFD数 0~1024 -
0x10 4 読込監視グローバルFD[0] 任意 -
読込監視グローバルFD[…]
可変 4 書込監視グローバルFD[0] 任意 -
書込監視グローバルFD[…]

■ Select応答メッセージ

offset size 内容 意味
0x00 4 機能ID 0x0000_0009 Select
0x04 4 タイプ(要求/応答) 0x0000_0001 応答
0x08 4 処理結果 0x0000_0000
0x0000_0001
成功
失敗
0x0C 4 読込レディグローバルFD数 0~1024 -
0x10 4 書込レディグローバルFD数 0~1024 -
0x14 4 読込レディグローバルFD[0] 任意 -
読込レディグローバルFD[…]
可変 4 書込レディグローバルFD[0] 任意 -
書込レディグローバルFD[…]

■ VfsReady通知メッセージ

offset size 内容 意味
0x00 4 機能ID 0x0000_0008 vfsClose
0x04 4 タイプ(要求/応答) 0x0000_0002 通知
0x08 4 グローバルFD 任意 -
0x0C 4 Ready対象 0bit目: read
1bit目: write
読込みレディ
書込みレディ

■ vfsRead応答メッセージ(改造)

offset size 内容 意味
0x00 4 機能ID 0x0000_0006 vfsRead
0x04 4 タイプ(要求/応答) 0x0000_0001 応答
0x08 4 グローバルFD 任意 -
0x0C 4 処理結果 0x0000_0000
0x0000_0001
成功
失敗
0x10 4 読込レディ状態 0x0000_0000
0x0000_0001
非レディ
レディ
0x14 4 読込み実施サイズ 0~24,064 -
0x18 0~24,064 データ 任意 -

■ vfsWrite応答メッセージ(改造)

offset size 内容 意味
0x00 4 機能ID 0x0000_0004 vfsWrite
0x04 4 タイプ(要求/応答) 0x0000_0001 応答
0x08 4 グローバルFD 任意 -
0x0C 4 処理結果 0x0000_0000
0x0000_0001
成功
失敗
0x10 4 書込レディ状態 0x0000_0000
0x0000_0002
非レディ
レディ
0x10 4 書込み実施サイズ 0~24,064 -

実装してみた

ttyプロセスが、select->read->writeを無限に繰り返す様にお試し。COM1で「1234567890Select!」を入力してみた。上のウィンドウは画面でデバッグログを、下のウィンドウはCOM1。端っこ切れてる。。
enter image description here
深く説明はしないけど、まぁCPU100%にならずに読込み待ちできたって感じです。

ここで問題発生

これまで、突貫で適当に作りすぎてて、機能毎に複数の要求を扱えない。
なので、ttyファイルをReadするとその先のドライバファイルのReadが行えない状況に。。。

driver仮想ファイルサーバttyサーバuser「/com1」をMount「/ttyS0」をMount「/ttyS0」に対してReadVfsRead「/com1」に対してReaduserからのReadを実行中なので無理VfsReaddriver仮想ファイルサーバttyサーバuser

直さねば。全体的に大改造なので、次回の更新はいつになるかな。

2019年7月20日土曜日

MochiOS@仮想ファイルシステムの作成part9

MochiOS@仮想ファイルシステムの作成part9

前提知識無しで作るなんちゃって仮想ファイルシステムpart9。

開発日記です。独り言です。

これまでのあらすじ

part 内容
0 仮想ファイルシステムを作りたい宣言をする。
1 ざっくり仮想ファイルシステムの機能を決める。
が、機能呼出し先の仮想ファイルシステムのタスクIDをどう取得するかという問題に気付く。
2 カーネルにタスク名登録機能を実装した。
これでタスク名からタスクIDを取得する事が出来る様になるハズ、なので試したいが試す方法が無い事に気付き、ログ出力タスクの開発を宣言する。
3 ログ出力の為に使うvsnprintf()の仕様を調べる。
4 ログ出力タスクを開発してタスク名からタスクIDの取得機能が正しく動いている事が確認できた。
5 mount機能を実装した。たぶんできてる。
6 FDどうやって管理しようかー。メッセージのやり取り制御を状態遷移で制御しようかー。とか考えて、open機能を実装した。たぶんできてる。
7 openと同じようなシーケンスなので、メッセージとちょっとやる事変えて簡単にwrite機能を実装できちゃった。
8 writeと同じようなシーケンスなので、メッセージとちょっとやる事変えて簡単にread機能を実装できちゃった。

closeの仕様を考える

今回はclose機能を作ります。
仮想ファイルサーバとしては、openもwriteもreadもcloseもあんまりやること変わらないハズ。なので簡単にできるかな~と思っている。
あ、キャッシュなんて何にも考えていませんからね。
(ブログ記事までreadのコピペ)

ユーザタスクmvfsシリアルポートドライバローカルFD->グローバルFD変換close要求( グローバルFD )グローバルFDテーブル参照vfsClose要求( グローバルFD )vfsClose応答( グローバルFD, 処理結果 )グローバルFD解放close応答( 処理結果 )ローカルFD解放ユーザタスクmvfsシリアルポートドライバ

シーケンスの順番は何も変わらず、渡すデータとちょっと間にやる事が変わったくらい。
あーcloseが一番楽だな~。渡すデータ無いし。FD解放するだけでしょ?(データキャッシュしてないから。)

以下、メッセージ仕様。

■ close要求メッセージ

offset size 内容 意味
0x00 4 機能ID 0x0000_0007 close
0x04 4 タイプ(要求/応答) 0x0000_0000 要求
0x08 4 グローバルFD 任意 -

■ close応答メッセージ

offset size 内容 意味
0x00 4 機能ID 0x0000_0007 close
0x04 4 タイプ(要求/応答) 0x0000_0001 応答
0x08 4 処理結果 0x0000_0000
0x0000_0001
成功
失敗

■ vfsClose要求メッセージ

offset size 内容 意味
0x00 4 機能ID 0x0000_0008 vfsClose
0x04 4 タイプ(要求/応答) 0x0000_0000 要求
0x08 4 グローバルFD 任意 -

■ vfsClose応答メッセージ

offset size 内容 意味
0x00 4 機能ID 0x0000_0008 vfsClose
0x04 4 タイプ(要求/応答) 0x0000_0001 応答
0x08 4 グローバルFD 任意 -
0x0C 4 処理結果 0x0000_0000
0x0000_0001
成功
失敗

実装してみた

大体、OpenやWriteやReadと同じような動きなので、あっさり実装。

とりあえず、実行結果をば。
close

何をやっているかというと、下の様なシーケンスでopen -> read -> closeを永遠繰り返すお試しを作ってみました。
確認ポイントは、closeしているので、LocalFDとGlobalFDが再利用されて、必ず1となっているところ(前者は5行目の「fd=1」で、後者は色々な行で出てくる「globalFd=1」で確認できる。)

mttymvfsシリアルポートドライバ1秒ビジーウェイトopen要求( /serial )vfsOpen要求( /serial )vfsOpen応答()open応答()read要求( 1バイト )vfsRead要求( 1バイト )デバイス読込みvfsRead応答()read応答()close要求( )vfsClose要求( )vfsClose応答()close応答()loop[ 無限 ]mttymvfsシリアルポートドライバ

read以上にあっさりcloseを実装してしまった。キャッシュ機能ないからね。

次はどうしようかな。
・作ってきた仮想ファイルシステムの色々な問題を解決していく。
な感じかなぁ。

並行して、ドライバをちゃんと作るためにMochiKernelにスレッド機能を追加とかやりたいので、かなり更新は遅くなりそう。

MochiOS@仮想ファイルシステムの作成part7

MochiOS@仮想ファイルシステムの作成part7

前提知識無しで作るなんちゃって仮想ファイルシステムpart7。

開発日記です。独り言です。

これまでのあらすじ

part 内容
0 仮想ファイルシステムを作りたい宣言をする。
1 ざっくり仮想ファイルシステムの機能を決める。
が、機能呼出し先の仮想ファイルシステムのタスクIDをどう取得するかという問題に気付く。
2 カーネルにタスク名登録機能を実装した。
これでタスク名からタスクIDを取得する事が出来る様になるハズ、なので試したいが試す方法が無い事に気付き、ログ出力タスクの開発を宣言する。
3 ログ出力の為に使うvsnprintf()の仕様を調べる。
4 ログ出力タスクを開発してタスク名からタスクIDの取得機能が正しく動いている事が確認できた。
5 mount機能を実装した。たぶんできてる。
6 FDどうやって管理しようかー。メッセージのやり取り制御を状態遷移で制御しようかー。とか考えて、open機能を実装した。たぶんできてる。

writeの仕様を考える

今回はwrite機能を作ります。
仮想ファイルサーバとしては、openもwriteもあんまりやること変わらないハズ。なので簡単にできるかな~と思っている。
あ、キャッシュなんて何にも考えていませんからね。

ユーザタスクmvfsシリアルポートドライバローカルFDテーブル参照write要求( グローバルFD, アドレス, データ, データサイズ )グローバルFDテーブル参照vfsWrite要求( グローバルFD, アドレス, データ, データサイズ )デバイス書込みvfsWrite応答write応答書込みアドレス更新ユーザタスクmvfsシリアルポートドライバ

シーケンスの順番は何も変わらず、渡すデータとちょっと間にやる事が変わったくらい。
(こうやってシーケンスにしてみると良く分かるのだけど、データのコピー回数の多さ。マイクロカーネルだとメッセージパッシングが主なデータのやり取りとなる(?)わけだけど、4回のデータコピー(ユーザタスク→カーネル→mvfs→カーネル→シリアルポートドライバ)が走るので性能が落ちる。)

以下、メッセージ仕様。

■ write要求メッセージ

offset size 内容 意味
0x00 4 機能ID 0x0000_0003 write
0x04 4 タイプ(要求/応答) 0x0000_0000 要求
0x08 4 グローバルFD 任意 -
0x0C 8 アドレス 任意 -
0x14 4 データサイズ 1~24,064 -
0x18 1~24,064 データ 任意 -

なぜ24,064かというと、現在のMochiKernelで送信可能なメッセージの最大長が24,576byteなので、そこから-512byte(ヘッダとかも含めるので)減らした。適当。
そもそも、なんで24,576にしたんだっけ…

■ write応答メッセージ

offset size 内容 意味
0x00 4 機能ID 0x0000_0003 write
0x04 4 タイプ(要求/応答) 0x0000_0001 応答
0x08 4 処理結果 0x0000_0000
0x0000_0001
成功
失敗
0x0C 4 書込み実施サイズ 0~24,064 -

■ vfsWrite要求メッセージ

offset size 内容 意味
0x00 4 機能ID 0x0000_0004 vfsWrite
0x04 4 タイプ(要求/応答) 0x0000_0000 要求
0x08 4 グローバルFD 任意 -
0x0C 8 アドレス 任意 -
0x14 4 データサイズ 1~24,064 -
0x18 1~24,064 データ 任意 -

■ vfsWrite応答メッセージ

offset size 内容 意味
0x00 4 機能ID 0x0000_0004 vfsWrite
0x04 4 タイプ(要求/応答) 0x0000_0001 応答
0x08 4 グローバルFD 任意 -
0x0C 4 処理結果 0x0000_0000
0x0000_0001
成功
失敗
0x10 4 書込み実施サイズ 0~24,064 -

実装してみた

大体、Openと同じような動きなので、あっさり実装。
(とはいえ、mountもopenもwriteもかなり適当に実装しているので、だいぶ改造やリファクタリングしていかなきゃならない。いずれそれをやる予定。)

とりあえず、実行結果をば。
write実装した画面

何をやっているかというと、

mttymvfsシリアルポートドライバwrite要求( "tes" )vfsWrite要求( "tes" )デバイス書込みvfsWrite応答write応答write要求( "tes" )vfsWrite要求( "tes" )デバイス書込みvfsWrite応答write応答mttymvfsシリアルポートドライバ

こんな感じ。
mttyはサーバタイプで、ラインディシプリンとかセッション管理とかそういうのを実装していこうと思っているプロセスです。今回は、このmttyが「/serial」ファイルをオープンして(上図では省略)二回「tes」という3バイトのデータをwriteしています。
シリアルポートドライバは、vfsWriteを受け取ったら、そのデータを1バイトづつ転送レジスタに書き込むようにしました。
(本当は、転送レジスタの空きがあるかチェックしたり、FIFOいっぱいだったら割込み待って書き込むとか必要なんだけど、ちょっと試したいだけだったので省略。真面目にやると、割込み待ちとメッセージ待ちの両方を行わせる事が現状できないので、カーネルの機能を追加しないといけない。)

qemu上で動かしているので「-serial telnet::4444,server」オプションを使う事で、telnet接続でシリアルポートに接続させることができるようにしています。

次!read。ほぼ、writeのコピペでいける気がする。テキトーに。

MochiOS@仮想ファイルシステムの作成part8

MochiOS@仮想ファイルシステムの作成part8

前提知識無しで作るなんちゃって仮想ファイルシステムpart8。

開発日記です。独り言です。

これまでのあらすじ

part 内容
0 仮想ファイルシステムを作りたい宣言をする。
1 ざっくり仮想ファイルシステムの機能を決める。
が、機能呼出し先の仮想ファイルシステムのタスクIDをどう取得するかという問題に気付く。
2 カーネルにタスク名登録機能を実装した。
これでタスク名からタスクIDを取得する事が出来る様になるハズ、なので試したいが試す方法が無い事に気付き、ログ出力タスクの開発を宣言する。
3 ログ出力の為に使うvsnprintf()の仕様を調べる。
4 ログ出力タスクを開発してタスク名からタスクIDの取得機能が正しく動いている事が確認できた。
5 mount機能を実装した。たぶんできてる。
6 FDどうやって管理しようかー。メッセージのやり取り制御を状態遷移で制御しようかー。とか考えて、open機能を実装した。たぶんできてる。
7 openと同じようなシーケンスなので、メッセージとちょっとやる事変えて簡単にwrite機能を実装できちゃった。

readの仕様を考える

今回はread機能を作ります。
仮想ファイルサーバとしては、openもwriteもreadもあんまりやること変わらないハズ。なので簡単にできるかな~と思っている。
あ、キャッシュなんて何にも考えていませんからね。
(ブログ記事までwriteのコピペ)

ユーザタスクmvfsシリアルポートドライバローカルFDテーブル参照read要求( グローバルFD, アドレス, データサイズ )グローバルFDテーブル参照vfsRead要求( グローバルFD, アドレス, データサイズ )デバイス読み込みvfsRead応答( グローバルFD, 処理結果, データ, データサイズ )read応答( 処理結果, データ, データサイズ )読込みアドレス更新ユーザタスクmvfsシリアルポートドライバ

シーケンスの順番は何も変わらず、渡すデータとちょっと間にやる事が変わったくらい。

以下、メッセージ仕様。

■ read要求メッセージ

offset size 内容 意味
0x00 4 機能ID 0x0000_0005 read
0x04 4 タイプ(要求/応答) 0x0000_0000 要求
0x08 4 グローバルFD 任意 -
0x0C 8 アドレス 任意 -
0x14 4 データサイズ 1~24,064 -

なぜ24,064かというと、現在のMochiKernelで送信可能なメッセージの最大長が24,576byteなので、そこから-512byte(ヘッダとかも含めるので)減らした。適当。
そもそも、なんで24,576にしたんだっけ…
(writeとおんなじ。)

■ read応答メッセージ

offset size 内容 意味
0x00 4 機能ID 0x0000_0005 read
0x04 4 タイプ(要求/応答) 0x0000_0001 応答
0x08 4 処理結果 0x0000_0000
0x0000_0001
成功
失敗
0x0C 4 読込み実施サイズ 0~24,064 -
0x10 0~24,064 データ 任意 -

■ vfsRead要求メッセージ

offset size 内容 意味
0x00 4 機能ID 0x0000_0006 vfsRead
0x04 4 タイプ(要求/応答) 0x0000_0000 要求
0x08 4 グローバルFD 任意 -
0x0C 8 アドレス 任意 -
0x14 4 データサイズ 1~24,064 -

■ vfsRead応答メッセージ

offset size 内容 意味
0x00 4 機能ID 0x0000_0006 vfsRead
0x04 4 タイプ(要求/応答) 0x0000_0001 応答
0x08 4 グローバルFD 任意 -
0x0C 4 処理結果 0x0000_0000
0x0000_0001
成功
失敗
0x10 4 読込み実施サイズ 0~24,064 -
0x14 0~24,064 データ 任意 -

実装してみた

大体、OpenやWriteと同じような動きなので、あっさり実装。

とりあえず、実行結果をば。
enter image description here

今回はちょっと動画でご紹介。
上は画面、下はシリアルポート入出力のウィンドウ。

最初にシリアルポート側で"testes"が出ていますが、前回のwrite機能実装でお試ししてみたもの。今回はその後に「aadekita!!!」を入力してやって、それをエコーしています。

ユーザタスクmvfsシリアルポートドライバ1秒ビジーウェイトread要求( 1バイト )vfsRead要求( 1バイト )デバイス読込みvfsRead応答()read応答()write要求( 読み込んだデータ )vfsWrite要求( 読み込んだデータ )デバイス書込みvfsWrite応答()write応答()loop[ 無限 ]ユーザタスクmvfsシリアルポートドライバ

1秒ビジーウェイトしているのは、ドライバ側で割込み待ちができない(現状、MochiKernelではメッセージ待ちと割込み待ちを同時に行えない。)ので仕方なく(CPUを労わる為に)。

write以上にあっさりreadを実装してしまった。
次はもっと簡単で、closeを実装する。キャッシングないからね。

2019年7月3日水曜日

MochiOS@仮想ファイルシステムの作成part6

MochiOS@仮想ファイルシステムの作成part6

前提知識無しで作るなんちゃって仮想ファイルシステムpart6。

開発日記です。独り言です。

これまでのあらすじ

part 内容
0 仮想ファイルシステムを作りたい宣言をする。
1 ざっくり仮想ファイルシステムの機能を決める。
が、機能呼出し先の仮想ファイルシステムのタスクIDをどう取得するかという問題に気付く。
2 カーネルにタスク名登録機能を実装した。
これでタスク名からタスクIDを取得する事が出来る様になるハズ、なので試したいが試す方法が無い事に気付き、ログ出力タスクの開発を宣言する。
3 ログ出力の為に使うvsnprintf()の仕様を調べる。
4 ログ出力タスクを開発してタスク名からタスクIDの取得機能が正しく動いている事が確認できた。
5 mount()機能を実装した。たぶんできてる。

openの仕様を考える

とりあえず、必要なのはパスよね。
あと、読書きフラグ。。。あるけど、今は忘れよ、うん。後ね後。
で、openしたらファイルディスクリプタ(FD)を払い出す。大体、FDはプロセス毎に1からなので、プロセス毎にFDを払い出す事にする。

あー、MochiKernelのメッセージパッシングはメッセージ送信元タスクIDしか取れないので、プロセスIDを取れるようにしないとだ。。
(どこかでMochiKernelの概要を書かねばと思っているのだけど、ここでさらっとご紹介。MochiKernelではカーネル上の1つのコンテキストをタスクという名前で扱う。つまるところ、タスクはスレッドと同じ意味。プロセスは複数のスレッド(タスク)から構成されるのは普通と一緒。スレッドIDはプロセス内ローカル値だがタスクIDはグローバル値という違いがある)

mountされたファイルをopenした時、そのファイルをmountしたドライバはopenされたタイミングで何か初期化をしたいかもしれない。
なので、openメッセージを横流しする。横流しといってもメッセージはそのままでなくて、新しい識別子を切ることとしよう。
パラメータはopenしてきたPIDと払い出されたFDを組み合わせた値とパスとしとく。

ユーザタスクmvfsシリアルポートドライバopen( "/serial" )FD払い出しvfsOpen( PID, FD, "/serial" )ユーザタスクmvfsシリアルポートドライバ

以下、メッセージ仕様。

■ open要求メッセージ

offset size 内容 意味
0x00 4 機能ID 0x0000_0001 open
0x04 4 タイプ(要求/応答) 0x0000_0000 要求
0x08 4 ローカルFD※ 任意 -
0x08 1024 絶対パス(\0含む) 任意 -

■ open応答メッセージ

offset size 内容 意味
0x00 4 機能ID 0x0000_0001 open
0x04 4 タイプ(要求/応答) 0x0000_0001 応答
0x08 4 処理結果 0x0000_0000
0x0000_0001
成功
失敗
0x0C 4 グローバルFD※ 任意 -

■ vfsOpen要求メッセージ

offset size 内容 意味
0x00 4 機能ID 0x0000_0002 vfsOpen
0x04 4 タイプ(要求/応答) 0x0000_0000 要求
0x08 4 PID 任意 -
0x0c 4 グローバルFD※ 任意 -
0x10 1024 絶対パス(\0含む) 任意 -

■ vfsOpen応答メッセージ

offset size 内容 意味
0x00 4 機能ID 0x0000_0002 vfsOpen
0x04 4 タイプ(要求/応答) 0x0000_0001 応答
0x08 4 処理結果 0x0000_0000
0x0000_0001
成功
失敗

※ 詳細は下記の「FD(ファイルディスクリプタ)の実装方法を考える」を参照

制御方法を考える

なんだかちょっとしたシーケンスが出来てしまったので、状態遷移表を用いた制御を行う。
その為に、MLib(自作の便利ライブラリ)に状態遷移管理機能を実装してそれを使うことにする。
詳細は割愛。ライブラリはここ(https://github.com/MasterMochi/MLib/commit/4135b1b0a1cd7d0617405e38e9b997b3bc3bf7fb)でコミットした。

状態遷移はこんな感じ。上のシーケンスから状態遷移記述に落としただけ。

状態 初期状態 vfsOpen待ち
イベント # 01 02
open要求 01 Task0101
→2
-
vfsOpen応答 02 - Task0202
→1

タスク概要はこんな感じ。エラー処理やその時の遷移はここでは割愛。

タスク名 処理概要
Task0101 1. FD払い出し
2. mountタスクへvfsOpen要求を送信
Task0202 1. oepn要求元タスクへopen応答を送信

FD(ファイルディスクリプタ)の実装方法を考える

ファイルディスクリプタって、各プロセス毎に一意の値じゃない?単純に考えると、仮想ファイルサーバは「プロセス(PID)」毎にFDテーブルを持たなきゃならない。PIDをキーにFDテーブルを持たなきゃならないわけだ。
PIDをインデックスとしたテーブルにすれば簡単にできそうだけど、PID分を全部用意しとかなきゃならないってのはなかなかメモリ容量を使いそう。

なので、各プロセス用のFDテーブルと仮想ファイルサーバ用のFDテーブルを持つこととする。
仮想ファイルサーバはプロセス毎にFDを管理するんじゃなくて、単純に一個のFDテーブルを持つ様にする。そうすればFDの払い出しは、0から順に空いているFD使えばいいので難しい事を考える必要がなくなる。
各プロセスは自分用のFDテーブルを管理しておいて、その用途は仮想ファイルサーバのFDを変換するだけにしておく。そうすれば、0からの各プロセス毎に一意なFDを使用できる。
ローカルFDテーブルの操作は、仮想ファイルサーバが提供するライブラリでやってしまえば、こんな仕組みはユーザに隠蔽することができる。

便宜上、各プロセス毎のFDをローカルFD、仮想ファイルサーバのFDをグローバルFDなんて名前にしておく。

ユーザタスクmvfsシリアルポートドライバローカルFD[0]払い出しopen( "/serial", ローカルFD=0 )グローバルFD[190]払い出しグローバルFD[190]=0vfsOpen( PID, グローバルFD=190, "/serial" )190ローカルFD[0]=190ユーザタスクmvfsシリアルポートドライバ

ユーザタスクがローカルFD=0のreadをしたければ、自身のFDテーブルを用いてローカルFDからグローバルFDに変換して、仮想ファイルサーバにグローバルFD=190のreadを出せばいい。

実装してみた

かなりやっつけだけど実装した。

ttyサーバ君を作って、シリアルポートドライバ君がMountする「/serial」を二回連続でOpenさせています。詳細な説明は割愛!

Rust@naked関数

Rust@naked関数 multiboot仕様でブートローダを自作せずGRUBから自作カーネル(もどき)を起動できたので、起動情報も色々受け取りたい。multiboot準拠していれば、起動直前にブートローダがレジスタEAXにマジック値を...