もしかしたら開発室附属雑記帳

計算機の明後日を考える「もしかしたら開発室」の雑文(又は下書き)コーナー

全体表示

[ リスト | 詳細 ]

記事検索
検索

全8ページ

[1] [2] [3] [4] [5] [6] [7] [8]

[ 次のページ ]

以前から予告していました通り、Yahoo!ジオシティーズのサービス終了に伴い、メインサイトを移転しました。


本日、旧アドレスから新アドレスへの転送設定を入れましたので以前のアドレスでは直接ページ参照できなくなりました。今後は上記アドレスから閲覧して頂くようお願いいたします。


で、今度はこのブログなんですが…こっちも2019/12/15いっぱいでサービス終了らしいんですよね。

今のところ今後の方針は未定です。メインサイトの更新作業が少しやりやすくなったので、ブログサービスを使わずそっちに記事ページを追加していくスタイルでも良いような気がしてきましたし。一方、また1社に色々集約しておくとサービス終了時に面倒なことになるので、その対策として別のブログサービスに移行することも検討しています。

Scrapstick関連が書きかけで情けない状態になっているのが少々心残りですが…場所がとっちらかっててもしょうがないので、こっちはブツ公開後にリポジトリの方へ文章を集約して書いてく方針にしようと思います。

開く コメント(0)

開く トラックバック(0)

長らく開発を続けている割りに今まで殆ど情報を出してこなかったのですが、さすがにモチベーションがアレ気味になってきたので、今回はプロジェクトの現況や概要について、かなり掘り下げて書いてみようと思います。

今着手しているのはOSの方です。名前は「Scrapstick(スクラップスティック)」と言います。Slapstickの書き間違いではありません。

「ソフト・ハードを問わないモジュール実装と高いモジュール可換性を実現する、新しいコンピュータシステムの開発」なんて掲げていますが、これ使って何がやりたいかというと、気軽にハードウェアの世界と戯れることができる環境と、そんな環境用に書いたコードを将来にわたって(何かしらの簡単な方法で)動かすことができる仕組みを両立させたい…というものです。

「あるOSの中でアプリどうしが通信しているのと、バス上で相互接続されたデバイスどうしが通信してるのって、細かい点は抜きにしてもやってること自体は似たようなもんだろ?」という点に着目して、

  • じゃあそれぞれ区別せずにまぜこぜで通信できるよな仕組みを作ってやれば良くね?
  • いっそ通信相手を(作者ではなく)利用者側都合で自由に差し替えられるようになってりゃ便利じゃね?
  • これ使えば、ハードべったりなコードがあったとしても、必要に応じてハード部をエミュレータへ簡単に差し替えられるので、実機無くなっても動かせるっしょ?
  • なんならこの仕組みにシェル(ユーザコンソール)でも付けてしまえばOSの代わりになるじゃねーか?

  • …といった発想の元に実装を進めています。OSだけでなくバスプロトコルの開発も視野に入れているのは、ネタの根本がこういったソフト / ハード界面みたいなところにある為です(まぁ単独のバスとして使えるもの方はいつ着手できるかわかりませんが…)。当然、カーネルレベルでのPOSIX互換なんて一切取る気もありません。


    通信相手がソフト実装かハード実装かを区別しない…ということから察しがつく方もいらっしゃると思いますが、このシステムで扱う通信は「バスアクセス」を抽象化したものです。ユーザモードにおけるコードフェッチやデータエリアのR/W、I/O操作に割り込み等々、大凡全てのバスアクセスがシステム管轄の通信として扱われます(!!)。当然マジメにそんなことしてたら死ぬほど遅くなるので、特定の条件を満たした場合に限ってカーネルを介さず直接ページアクセスできるようにする等の工夫を入れて、実用的な速度で動作するようにしています。また、バスに発行可能なアクセスのサイズは可変長としているので、ブロックI/O的な使い方で通信コスト(発行回数)を減らすことも可能です。この辺は、システムコール的なものを持たせない設計(HLT等、プロセッサ機能に絡む内容以外のカーネルとの対話は、全て通信経由で行う必要がある)などと絡んでいる所でもあるのですが…細かい話はいずれ。

    前掲の話ではハードモジュールをソフトモジュール(エミュレータ)で置き換えることだけ触れましたが、当然逆も可能です。つまり、元々ソフト実装モジュールだったものをハード実装のアクセラレータに、呼出元コードを弄ることなく利用者都合で自由に切り換えることができます。例えば、元々通信を伴うものや演算系等、処理の粒度が大きく、かつ各々一回の呼出で完結できるようなタイプの処理であれば威力を発揮できるはずです。特に、前述した直接アクセスの条件を満たしていればカーネルを介在せずに直接レジスタを叩くことができるので、大幅な高速化が期待できます。あまりにもソフト間通信コストが問題になった場合は、FPGAボードとかと組み合わせてこういう逃げ道もありますよということで…。

    この辺をさらに発展させると、

  • 「デバイスドライバ」の概念は必ずしも必要ではなくなる。同時アクセス時の調停機能と、ハードウェアI/FをAPIが定めるI/Fに見せかける機能を持つエミュレータだったのだ…と解釈できるので、いずれも必要無ければ無くて良い。
  • デバドラが通常階層構造になっているように、エミュレータを多段に繋いでも良い。つまり、各エミュレータ段で直接叩いたつもりのレジスタが、実は他のモジュールでエミュレートされた代物だった…というのを多段に繰り返しても良い。
  • これより、わざわざ抽象化レイヤや共通APIを作らなくても上手くいく可能性が出てくる。例えば、機能Aの実現に使えるハードウェアが5種類位あるとして、作者側は手持ちにあわせてどれか1つのI/Fに合わせたコードを書けば良い。利用者側は、手持ちに合わせて、I/F変換のエミュレータを探すなり(単独では揃わなくとも、多段にすれば揃う可能性が高まる)、作るなり(必ずしもフル機能を作る必要は無く、そのアプリが動く程度のザルいものでOK)すれば良い。恐らく、ユースケースが固まっておらずI/Fが乱立しがちな新規分野だったり、共通APIに集約する動機も無いようなニッチ分野で特に効果的。
  • メモリアクセスが通信である以上、メモリだと思って通信した相手が「本物のメモリ」である必要は無い。即ち、ディスクドライブ等を使ってエミュレートできる(メモリマップドディスク的な)。これより外部ストレージ・メモリ空間上の揮発 / 不揮発メモリ等々を全て等価に扱える。ごくごく自然に仮想記憶が実現できるとでも言うべきか。バス空間上に「ファイルシステム」をマップすることさえ可能。
  • CPUエミュレータを経由して他機種のマシン語で書かれたコードを実行しても、実機向けに書かれたコードと全く同等に扱える。バスアクセスを通信として使うので、通信相手から見ればどっちだろうと差異は無い。極端な話、例えばx64 PC上で、SPARC向けに書かれたアプリケーションが、68000向けに書かれたTCP/IPスタックとARM-v6向けに書かれたモデムドライバと実機モデムを経由して通信を行い、Z80向けに書かれたV9958を使うコンソールに結果を出力…なんてことも、ごくごく自然に行える。CPUエミュレータの多段も可(CPUエミュレータを別のCPUエミュレータ上で動かしたりできる)。
  • これをハードレイヤにも適用すると、ヘテロジニアスなマルチプロセッサ環境を自然に扱える。前述の通り、バスアクセスさえ発行できれば実行コンテキストのアーキテクチャは問わない為。DMAの処遇についても同様。但し、当然ながらカーネル側でも専用の対応が必要。
  • 所用の通信さえ実現できれば良いので、最終的に、Scrapstickの殆どの機能をハードウェア化したアーキテクチャのマシンを作ることも可能かもしれない(ただの浪漫)。

  • といったように、結構面白いプラットフォームになりそうです。「互換性の担保をエミュレータに押しつける」点や、それを利用して「新しく作る部分では互換性を無視して好き放題できるようにする」という思想については、使い方や目的は違えど、とても古のOSASKっぽい所だと思います(当然ですが、コレには多々強い影響を受けて育ちましたので…)。うまくいけば、コンピュータシステムの組み方・あり方を大きく変えることができるシステムに発展できるかもしれません。例えば、枯れた分野のハードウェアはよりインテリジェントなI/Fを持つ方向に進化することが簡単になるし…ストレージがファイルシステムを話すとか…、新たな分野ではI/Fの試行錯誤がより気軽に行えるようになるはずです(I/Fが固まるより前に生まれた徒花たちを、エミュレータさえ書けば後世にも使い続けることができる可能性が高まる。よって、書き捨てることに後ろめたさが無くなる)。


    ここまでは割と美味い話ばっかり書いてきましたが、当然、この方式によるデメリットもあります。

    先程からもちょこちょこ触れているように、まずは性能上の問題です。バスアクセス全てをカーネル管轄の通信として扱う以上、このコストがとんでもないことになるであろう予測が立ちます。前述したように、通常のコードフェッチやメモリの読み書き程度であれば、カーネルを介さず直接アクセスできるような細工を入れ込んではあるのですが、モジュール間通信部分はどう転んでもカーネル経由です。単段であればUnix系で言うところのパイプを介したプロセス間通信レベル + αで済むと考えられますが、エミュレータを多段で組むような状況下では各モジュール境界でそれぞれ通信が起きるので、マイクロカーネルでサーバ間通信が多発しているような状況 + α程度を覚悟しておくべきと思います。また、作成者都合で通信相手を限定できない(利用者側で勝手にエミュレータへ差し替えられる / 多段にできる)ことから、時間制約が厳しかったりリアルタイム性を保証しなければ動かない用途には不向きです。こういった性能上の懸念については、いくつか代替の腹案はあるのですが、当面は利便性の代償としてあきらめる方向で考えています。ただ、このシステムの中であっても、極力依存する外部モジュールを減らせばベアメタルに近い性能を出すことは可能と思われるので、必要であればその辺を駆使して乗り切ってほしいところです。

    次はこの通信方式に関する点です。モジュール間通信の界面は所定のバスアクセスの形で行う必要があるため、既存のシステムで良く見られる関数呼出スタイルのAPI / ライブラリを、そのまま別モジュールとして切り出すことができません。どうしてもやりたければ、呼出元にラッパ関数を噛ませて、その中で通信を発行する形にする必要があります。これはシステムコールをCから呼ぶラッパ等と同種といえば同種ですが、差し替え可能にしたい部分は全てこの形式にしておく必要があるため、他のシステム用に書いたコードをScrapstickへ移植する場合などはこの点をよく意識しておかないと、折角のメリットが全く得られないハメになるかもしれません。


    システムの概要をざっくり書いてしまうとこんな感じです。じゃあ後はどこまで形になってるのか…という話なのですが…、以前の記事にも書いたように、現在はWindows上で動く版(以下Win32版と呼びます)を書いていまして、その上でI/Fの確認などの実験を重ねています。流石に記事当時よりも実験が進み、Win32版内蔵のQuark D1000エミュレータ( + α相当。i386をFlatモデル固定にして命令を減らしたようなヤツ)上でCで書いた実験アプリを走らせて機能や使い勝手を確認できたりする状態です。詳細は後述しますが、ようやく長年の懸念事項があらかた片づき、今後システムの大改造を伴うような手戻りは無いであろう段階まで来たので、あと2〜3機能程、ユースケースとして実現性を確認しておきたい大物が上手くいけば(ハマらなければ)公開に踏み切れると思います。

    前述の記事でも少し触れていますが、実機版が完成した暁には、何らかのシリアル通信I/F経由でそのまま協調動作できるようになる予定です。ようはバスアクセスをシステム間でまたいで伝達することができれば、相手方が持つアドレス空間の一部(公開されている領域)をローカルに(仮想的に)マッピングしてアクセスできることを利用して、実機版で走るアプリからWin32版のウィンドウマネージャを叩き、ウィンドウを生成してボタン操作やら入出力やらを受け付けたり、逆にWin32版で走るアプリから実機版のI/Oエリアを叩いたりすることなどに使えます(当然、実機のシェル代わりや各種デバッグにも使えます)。最初に公開するのはこのWin32版の予定です。こっちだけだと魅力半減ですが、どういうものかは伝わるかなぁ…と。

    (以下、2018/12/29修正)

    流石に時間かかりすぎじゃねーの…という話なんですが、実は2012〜15年にかけて作っていた代物(1回だけ人目に出したことがあります)を一旦放棄したりと、結構大きな手戻りを何度もやらかしてしまっています(実験的要素しかないので仕方ない部分ではあるのですが…もどかしい)。本稿で書いたことのうちの大半は、この放棄したものでも仕組みとしては実現できる構造だったのですが、一言で言ってしまうと「プラットフォーム性」とでも表現できるでしょうか、使い勝手上の難があった為、その仕組みのままI/F類を整備する気になれず、本格的な実験(特に、発展に書いたような部分の確認)にまで至れませんでした。

    この「プラットフォーム性」について具体的に言うと、例えば、自分が書いたコードを他の人にも手軽に使ってもらえるように、或いは他の方が作ってくれたコードを手元で手軽に使えるように…というのは当然ですし、システムを使い込んだ際にスケールしないようでは困りますし(例えばシステムが扱うアドレス空間。フラット・固定長でスケールする訳が無い)、何がどこにあるのかわからずとっちらかったり、システムの扱いが複雑怪奇になりすぎても困ります。この辺り、割とUnix(当初の)やPlan9辺りはバランスが良いんですよねぇ(そしてSmalltalk、テメーはダメだ)。

    これらを本来やりたいことと両立して実現できる仕組みに組み上げるのがなかなか厄介で、さりとてノウハウも無いので何度も作っては壊しして進めているような状態です。現在の実装についても、大枠となるブレイクスルーは2017年前半までに得られたのですが、やはり使ってみるとどうしても気になる点が次々出てきて、最近まで長期スパンで大改造を繰り返し行っていた位ですので…。そしてこの部分こそ、システムの根幹を成す「Scrapstickバス」です。少々毛色は違いますが、UnixやPlan9で言うところのファイルシステムみたいな立ち位置ですかね。これまで「カーネル管轄の通信」と書いていたのは、このバス上で扱う通信のことです。こいつの概要も書いておきたいところですが、ちょっと長くなりすぎたので年明け以降にでも別途改めて書くことにします。

    それでは皆様よいお年を。

    開く コメント(0)

    本体サイトの方ですが、ホスティングに使用しているYahoo!ジオシティーズが2019/03/31でサービスを終了するとの報がありましたので、これを機にGitHub Pagesへ移転することにしました。新しいアドレスは下記の通りです。


    恐れ入りますが、お暇な時にでもブックマーク・リンクの更新をして頂けると有り難いです。フォルダ構成もそのまま維持していますので、直リンクの場合は頭だけ差し替える形でご対応下さい。サービス終了までの間は両サイトの内容を同期しておきますので、ぼちぼちで結構です。また、このブログや掲示板については移転せず現行のままです。

    --

    しかし、他のホスティングサービスが終了していくのを横目に見続けてきましたが、とうとう自分にもお鉢が回ってきました…。元々ジオシティーズ自体じわじわ提供機能を減らしていて(直接喰らったものだけでも、独自メールサービス、初期に掲示板として使っていたジオボード、果てはカウンタ、ゲストブック、ジオログ等々)長期に渡る撤退戦のような状況でしたので、一ユーザとしてはやっぱり…というか、寧ろよくここまで持ちこたえたなという印象です。

    そういや上記消えた機能を列挙しながら思い出しましたが、ジオのアカウントは当初自分専用のメアドが欲しくて作って、せっかくだから作ったソフト公開するようにしようかみたいな感じでサイトを開設した記憶があります(尤も、メールの方は数年持たずサービス終了してしまいましたが…)。サイト開設は2001年だったと記憶しているので、約17年ですねぇ。当時中学生だった私ももう三十路ですよ…時の流れは恐ろしい…。しかしまぁ、それだけの期間同一アドレスで細々と成果物を公開し続けることができたのを幸運と見るべきなのかもしれません(実は、一度古い番地表記アドレスの旧システムからID表記アドレスの新システムへ移行させられたのですが、現時点でも古いアドレスからの転送が残り続けています)。おかげさまで、あんなニッチな代物しか置いてないサイトなのに、今に至るまでコンスタントに誰かしら見て下さっているようですので。

    ただ一方で、今の形式のままやるのもどうなのかなぁという気がしています。というのも、やり方を変えずに版数管理やら整合性やらを含めてちゃんとやろうとすると、間違いなく続けられないと思うので、そこはテクノロジに頼って解決したいという思いはずっとあって、例えば文章をブログに上げたりはその一環だったりした訳です。一方、ソフトの方はこれまでの蓄積(lzh/zip配布で公開した代物)が多い分、前との整合性の兼ね合いもあって、1個だけ試しにGitHubで公開して以降は元のアーカイブ配布に戻していました。いちいちアーカイブ作って周辺ページを手打ちで書き換える現行スタイルよりは、Readmeを説明ページ代わりにした上でgitの日常操作のままアップできるGitHubの方がラクではあるので、折角だからこれを機にスタイルを改めたい感情の方が勝ってきました。

    そこで今後、新規で公開するソフト・ハード等はGitHubGitLabにリポジトリを作るようにして、サイトの成果物公開機能については概ねアーカイブにしてしまおうかと考えています(つまり、移行先に持っていきディレクトリ構造も維持するが、これ以上の更新はしない)。まだ更新・修正を続ける意志があるものについても公開リポジトリ作ってそちらへ移管しようかと考えていますが、既存のReadmeはShift-JISのせいでGitHub上から上手く表示できない問題があったり、ローカルリポジトリのファイル配置がリリースと異なるものがあったり、残念なコミットログを晒すのに抵抗があったりと、そのまま公開できる状況ではないものが多いので、暇をみつけてぼちぼちやることになりそうです。これはまだ公開してない代物にも言えることです。まぁReadmeの文字コードはともかく、他は気取って使おうと思わなきゃいいだけの話なんでしょうけど…でも抵抗あるなぁ。

    また、文章については当面このブログをメインに考えていますが、Yahoo!ブログはWiki文法使用時のクセが強く、特に(よく使う)箇条書きが隠し機能になってたり、それを無理やり使う場合は工夫しないと書式が崩れたりするので、ちゃんとした文章を書く場合は、何らかの静的サイトジェネレータを使ったシステムに移行するかもしれません。本体サイトの既存の記事については、修正がなければこのままにする予定です(つまり、移行先に持っていきディレクトリ構造も維持するが、更新はしない)。電脳文庫関連はアクティブなので(そうは見えないのが心苦しいですが)、前述の通りに更新を継続する予定です。こちらについては近々近況を追記しようと思います。

    さらに、前回の反省もあって、試運転さんのアドバイスも参考に、質問や記載ミス・バグのレポートのための雛型の準備と、連絡手段を追加(各リポジトリのIssuesを使用する運用に)してみました。後者の手段を使うと私宛にメールが飛ぶので、ジャンクメール判定さえされなければ見落とす可能性は低いはずです。雛型はについてはひとまずこのサイトのリポジトリに作成しておきましたが、このままではGitHubアカウントを持っている方しかやりとりできない・雛型を使えない為、掲示板からでも雛型を参照できるように別途リンクを貼っていこうと考えています(リポジトリを新設するものについては、Readmeを仕立て直す際にリンクを張るなど)。お気軽にお使い下さい。

    今後のやり方は少々変わりますが、趣味の成果物置き場としての立ち位置は変わらず、ましてや現在あるファイルの配置はそのままで、これからも細く続けていく所存です。移転後も引き続き宜しくお願いいたします。

    --

    オマケで、ジオからの移転先としてGitHub Pages / GitLab Pagesを検討している方向けのメモなど。

  • GitHub Pagesについて、masterブランチを使わない方法は古い説明なので、無視して良いと思います。
  • GitLab PagesはCI機能の一環として実装されているようです。このため、ただリポジトリ上のファイルを公開するだけでもこれのように、実質何もしないスクリプトをリポジトリに突っ込んでおく必要があるようです。
  • また、GitLab Pagesは./publicフォルダ以下のファイルを公開するので、これのようにリポジトリ内の全ファイルを./publicフォルダへコピーするスクリプトにしておくと、GitHub Pagesと同じファイル配置のリポジトリ(rootにindex.htmlを置く)にすることができるようです。
  • Shift-JIS / EUC-JP等のファイルは文字化けするようです(HTTPヘッダか何かで強制的にUTF-8だと通知している??)。各ファイルをUTF-8に変換してしまえば問題ありません。
  • 通信がHTTPS化される為、カウンタ等、外部サイトのコンテンツがブラウザにブロックされる場合があります。相手がHTTPS対応サービスであれば、リンクのアドレスを変更するなりして表示できるように対応すべきです。
  • どちらも、Pushしてから反映されるまでに少々時間がかかります(特にGitLab)。
  • privateリポジトリにしなければコミットログが公開される為、いちいち更新履歴をページ内に書かず、そちらを直接参照させる運用もできるかもしれません(個人的にやりたい)。
  • 見慣れた自サイトに広告が出ないのはチョット嬉しい。
  • 開く コメント(0)

    開く トラックバック(0)

    表題の件です。

    具体的に言うと、Win10 1709以降で、前回セッションを再起動・シャットダウンで終わらせる際、起動したままになっていたアプリの内一部が、次回ログインする際勝手に立ち上がる…というものです。全てのアプリが自動起動の対象となるわけではないようなのですが、少なくともVisualStudioとタスクマネージャは該当しました。

    これに関する日本語の情報としては、この辺を辿った先などで色々な手を使った回避策が紹介されていますが、どうもその後、この機能を正規に無効化する手段が用意されたようです(下記最初のページのコメントによると、1709では2018/02/01のKB4058258以降。1803では最初から)。
    参考までに、日本語環境でのスクショを上げておきます。以下の設定をOFFにすることで、スタートメニュー経由などから普通にシャットダウン操作を行っても、前述のアプリが自動起動することはなくなりました。

    イメージ 1


    尚、Explorerで開いていたフォルダウィンドウをログイン時に復元する機能については、Win95の頃から元々ある別の機能なので、上記オプションの埒外です。こちらは今までどおり、独立してフォルダオプションから設定できますので、必要に応じて設定すると良いと思います(すべてのコントロール パネル項目 > エクスプローラーのオプション > 表示 > 詳細設定: > ログオン時に以前のフォルダー ウィンドウを表示する)。

    本当はこんなところに書かないで上記スレッドに追記してあげれば良いのでしょうけど、該当するスレッドが軒並み2018/02にロックされていた為、できませんでした。スレッドによっては、対策がリリースされて暫く経過してからロックされていたものもありましたので、せめて最新の情報に更新してからロックしてほしかったなぁという気がします。

    開く コメント(0)

    開く トラックバック(0)

    随分前になりますが、Windows8.1で「親指の友」が動かない件(原因と対策)という記事の中で、「Windows 8.1以降では旧来の親指シフトドライバで必要な通知が飛ばなくなった」という趣旨の記述をしていたのですが、別件を発端とする調査の結果、これが一部事実と異なることがわかりました。

    既に当時調査を行った機体もWin10化してしまっているので、再度Win8.1で確認し直すことはできないのですが、少なくともWin10(1709)では、以下の挙動が確認できました。

  • x86版かつPS/2接続のキーボードに紐付くドライバ宛には、正しくIME状態の通知が行われるように見える
    これは、Windows付属KB211用ドライバ(親指シフト PS/2 キーボード)のモード同期処理が正しく動作することを意味します(ストアアプリ相手であってもOKでした)。同じ仕組みを利用する初代親指の友ドライバも正しく動作する可能性が高いです。

  • x64版ではIME状態の通知を受け取る部分の処理が消されているらしく、IME状態の通知を行っても何も起こらない
    つまり、Windows付属の親指シフトキーボードドライバ(FMV-KB211用)を入れても、キーボード側の入力モードがずれます。
    調査手法の都合上、そもそも通知を飛ばす機能自体が生きているのかどうかの確認は行えていません。

  • USB接続のキーボードに紐付くドライバ宛には、一切のIME状態通知が行われない。もしくは、キーボードクラスドライバのインスタンス番号が先頭以外のキーボードに紐付くドライバ宛には、一切のIME状態通知が行われない(この調査のみ、Win10 1803 x86)。
    調査手法・手持ち機材の都合上、どちらが正解なのか確認できていません(USB接続 かつ インスタンス番号先頭の場合や、PS/2接続 かつ インスタンス番号が先頭以外の場合が確認できていません)。

  • また、x86版側の挙動については、Win XP(SP3)環境でも相違ないことが確認できました。x64版XPは環境が無い為不明です。XPでの挙動から察するに、8.1でも上記と同様の動作だった可能性が高いと考えられます(勿論、一時的におかしくなっていたのが後に修正された可能性もゼロでは無いですが…)。

    もし、当時その記事(や、その続きの記事)をご覧になり、Win7からのアップグレードを控えられたり、或いはそれを機に(Windows標準ドライバが同じ機能に依存している)KB211等のキーボードを予備役にしてしまった方等がいらっしゃいましたら、大変申し訳ないです。お詫びして訂正します。少なくとも現行Win10のx86版(32bit版)をお使いであれば、PS/2接続など特定の条件下で通知に依存するドライバも正しく動作するようですので、お試しください。

    また、旧Oyayusbyに付属する説明書等には「WindowsはカナロックLEDの制御を行わない」と書いていましたが、これも誤りで、正確には「カナロックLEDの制御自体は今(Win10 1709/1803 x86/x64)でも行われるが、IMEの状態や実際の入力状況とは特に連動しておらず、IME OFF状態でカナロック操作(Ctrl + Shift + カタカナひらがな)を行った時にトグルする以外は挙動不審(IME OFFでLED点灯状態なのに入力は英字…なども普通に起こる)」というものでした。重ねて訂正いたします。尚、これはカナロックLEDが存在すると通知したUSB HIDキーボード(ようはOyayusby)での挙動なので、AXキーボードなど、AT / PS/2接続のものでも同じかどうかは不明です(自分が持つLEDの通知手段が無いので…)。

    以下、前者の件についての詳細を書きます。

    発覚までの経緯と確認内容

    掲示板の方でリクエストがあった、OyayusbyをKB211と組み合わせて使う為のカナロック制御アプリ(Oyayusby Utility)を開発するにあたって実験を行っていた時の話です。グローバルフックの実験が上手くいき、IMEの状態も取れたので、試しにPS/2接続用親指シフトキーボードドライバのモード同期を行う機能を組み込んでテストしようとしていました。

    ここで比較用として、このアプリを走らせない状態での挙動(x86)を確認したところ、意図に反してIME状態の同期が行われてしまったことから、今回の件が発覚しました。具体的には、Windows標準のKB211用親指シフトキーボードドライバ(親指シフト PS/2 キーボード)をインストールし、マウス操作でIMEの入力モードを変化させ(英小⇔かな)、そのモードで正しく入力できるかどうかを確認しました。かなに切り換えると正しく入力できない(対応するキーのJISかなが入力される)挙動を期待していたのですが、実際には正しく追随されてしまった…という訳です。

    原因特定の為に調査を進める過程で、機材の都合からx64版の環境を使用したところ、今度は一切IME状態の同期が行われなかったことから、x64版とx86版で動作が異なることが判明しました。上記実験アプリを使っても同期不可です(この件の詳細は後述します)。本当はJapanistの有無で挙動が異なるかを見ようとしたのですが、こちらは関係無かったようです(2003 / 10共に、あっても無くても挙動は変わりませんでした)。

    さらに、当時記事を書くにあたってテストした環境と近い状態で確認すべく、同一の機体(ASUS T100TA-DK32G。但し、OSはWin8.1ではなく、Win10 1709 x86)にて旧親指の友ドライバのかな入力時同時打鍵が効くか試したところ、こちらは当時と同じで正しく入力できませんでした(つまり、IME状態の通知が来ていない)。当該機体にPS/2ポートは無く、キーボードドックのキーボードはUSB HIDキーボードとして認識されている為、USBキーボード限定で通知が来ていなかった可能性が出てきました。

    そこで、PS/2ポートを持つ機体(Win10 1709 x86)にOyayusby + 初代親指の友ドライバを接続し、初代親指の友ドライバのレイアウトファイルが使用される状況下で同様の調査を行いましたが、やはりUSB HIDキーボード側ではかな入力時の同時打鍵操作が正しく行えませんでした。

    しかし、わざわざIME状態通知を飛ばす側でPS/2キーボードかUSB HIDキーボードかを見て、前者の場合だけ通知を飛ばす…みたいな器用なことをやってるのか甚だ疑問です(できなくはなさそうだが、かなり面倒そうに見える)。特に、T100TA-DK32Gは本体の音量調整ボタンなどもキーボードとして認識されており、キーボードクラスドライバインスタンスはキーボードドック取り付け時点で2つになっています。そこで、キーボードクラスドライバインスタンスの列挙順で先頭のものに決め打ちで通知を飛ばしているのでは? と仮説を立ててみました。キーボードクラスのインスタンス番号とキーボードデバイスの対応は以下のレジストリキー以下で確認できそうです。

    HKLM\SYSTEM\CurrentControlSet\Control\Class\{4d36e96b-e325-11ce-bfc1-08002be10318}

    これまで試して上手くいかなかったキーボードのインスタンス番号はいずれも0001となっており、先頭に他のデバイスが割り当てられている状態でした(PS/2ポートがある機体ではPS/2接続のキーボード。T100TA-DK32Gでは音量調整等のGPIOボタン)。T100TA-DK32G(但し、上述の調査から時間が空いてから実施した為、Win10 1803 x86環境に変更済)で確認する限り、先頭インスタンスのデバイスを削除・再起動することでこの順序の入れ換えができるようでしたので、この操作の後にキーボードドックの初代親指の友ドライバでかな入力が正しく行えるかを見てみました…が、ダメでした。

    改めて確認してみると、

  • 他にもkbdclassのインスタンス列挙に関係してそうなエントリがある

    HKLM\SYSTEM\CurrentControlSet\Services\kbdclass\Enum

    削除・再起動後にここを確認すると、前述のキーと異なり、順序の入れ換えが行えていません(GPIOボタン側が先頭のまま)。
    但し削除後・再起動前に見ると、先頭(0番)にUSBキーボードが来ます(一時的)。

  • 実際にキーボードクラスドライバへ通知を飛ばす際に必要なハンドルを取る手段として、レジストリを参照せずに行う古いやり方がある

    以下のパスをCreateFile()で直接開くことで、該当するキーボードドライバのハンドルを得ることが可能です。

    \\.\Device\KeyboardClass*
    ※(*は0〜)

    削除後・再起動前に、SysinternalsのWinObjで上記オブジェクトが存在するか見ると、KeyboardClass0側が消えていて、KeyboardClass1は残っています。

  • 先の列挙方法も含めた3つとも、列挙される順序は連動して無いように見える
    それぞれ番号がずれる場面があるので(削除後・再起動前)。

  • となっていました。また、GPIOボタン側の削除・再起動を繰り返しても同上でした。PS/2ポートを持つ機体については、そもそもPS/2キーボードを削除したときの挙動が見れなかった為(再起動するまで削除されない・再起動するとPnPで自動的に再インストールされる)、ハンドル側の挙動について上記に当てはまるか不明です。

    上記ハンドルを取る手段については他の方法(Setup API経由での列挙。順序は最初に紹介したレジストリキーと同一でした)よりお手軽ですし、Win2000より前にはSetup APIが存在しなかった為、IME状態通知の歴史(恐らく初期のNTから存在する)を考えると、このオブジェクトを使っている可能性が一番疑わしいのではと考えています。具体的に起こっている状況を想像すると、

    1. システム側のIME状態通知送信部の内部実装が\\.\Device\KeyboardClass0を決め打ちで開いている
    2. KeyboardClass*の割り当て順序にある程度の法則性がある
      例えば、脱着不可なレガシデバイス(PS/2)やルートバスに近い方(GPIOボタン等)から順にハンドル生成される等。

    なんてことになっていて、上記2つより、

    1. PS/2ポートを持つ機体では、このポートが常にKeyboardClass0になっていて、親指シフトキーボード用ドライバの動作に支障がないように働いている
    2. 脱着可能かつUSBポート経由のキーボードドックはGPIOボタンよりオブジェクト生成順序が後ろになり、IME状態通知が来ることはない

    みたいな状況になっている可能性は割と考えられます。このハンドルが具体的にどういう順序で生成されるのか、あるいは現状どのインスタンスと結びついてるかを手軽に見る方法があると良いのですが、前者はざっと調べた限り具体的な情報は見つかりませんでしたし、後者もkd使わないとダメそうなようなので(RS-232Cで2台直結…)、今回これ以上の深追いはあきらめました。

    尚、GPIOボタン側にダミーのフィルタドライバ(IME状態通知が来たときにログ出力等)を仕込めば切り分けは可能ですが、今回はそこまでは実施しませんでした(或いは、キーボードクラスドライバのインスタンスがUSB HIDキーボードしか存在しない機材が手元にあれば良かったのですが…)。

    なんで当時間違えたか

    ひとえに「実験環境の組み方が悪かった(ことに気づかなかった)」という点に尽きます。

    当該Win8.1機(ASUS T100TA-DK32G)は当時の手持ちで唯一となるWin8以降の環境(但し32bit)であり、かつ唯一PS/2ポートを持たない機体でした(これは今でもそうです)。前述の通り、当該機体のUSB HID経由のキーボードドライバには通知が来ないようなので、これを以て「通知が来ないよう変更された」と思ってしまった訳です。

    このドライバは元々PS/2ポートでの使用を前提としていて、複数インスタンスが実行されることは考慮しておらず(一応最低限の行儀は満たしていますので、複数動作させてワークを破壊したりすることは無いです)、この件以前に複数のキーボードクラスが登録された環境での動作や、USBキーボードへのアタッチ動作を確認したことはありませんでした(Oyayusby作る前はUSBキーボードが手元に無かったというのもありますが)。今冷静に考えると「じゃあ真っ先に疑うべきはUSB化 / 複数インスタンス化だったろ」という話なのですが、当時の状況を思い出せる限り確認したり再現実験を行ったりした限り、infの改造でUSBキーボードへのドライバ導入ができることを以て「フィルタドライバから見たキーボードの通信I/Fは同じ」と判断し、IME状態通知が一部のキーボード宛にしか来ないことについては想像が及ばなかったようです…。

    また、残りの環境をWin10化した時点では既にMk-2ドライバしか使用しておらず、旧作ドライバ等のテストも(Win8.1時代の結論より、ハナから使えないと思って)しなかったことや、Win7以前のx64版を常用する機会に恵まれなかったことなど、本件に気づくきっかけを悉く逃していたのも重なってしまいました。

    x64版でIME状態通知を受け付けない件の詳細

    無理やり投げてみても動かなかった…というのは上述の通りですが、じゃあなんで?という話です。

    Windows付属KB211用ドライバで、実際に通知を受けてキーボードへのコマンドを発行しているのは、Windows標準のPS/2ポートドライバ(i8042prt.sys)です。なんでそんなことがわかるのかというと、実は2003 Server頃の古いDDKには、こいつのソースがサンプルとして同封されていた為です(input\pnpi8042として収録)。現在のWDKサンプルには含まれていないようですが、本記事投稿時点ではまだ2003DDKの入手が可能のようですので、見てみたい方はこちらから。

    こいつを見ますと、IME状態通知関連の部分が、軒並み以下のようなifdefで切られています。

    #if defined(_X86_)

    昔読んだときは純粋に「Alpha / MIPS / PowerPC避け」だと解釈したのですが(多分書いた人の意図も同様と思います。i8042prtのPnP対応が行われたのは恐らくWin2000の時で、当時x64版はまだ存在しませんでした)、改めて今見ると、これじゃぁx64版も除外されてしまうのですよねぇ…(x64版は_AMD64_。x86の表記自体はx64を内包する使い方もあるのでマジ紛らわしい…)。

    そもそもx64版とx86版でこの部分の挙動を変える必然性がイマイチ謎ですし(Alpha等の除外については、これらを積んだFMVが無い為…と解釈できます)、x64版にも「親指シフト PS/2 キーボード」のinfエントリやら専用レイアウトファイル(f3ahvoas.dll)やらが含まれているのを考えると、x64版で使えないのは単なるミスで、中の人が誰も気づいてないだけなのでは?…という気がします。

    ついでに言うと、たとえ非IA-32機であってもPS/2ポートを持つ機体ならKB211を差すこともできたでしょうから(しかもこいつはスキャンコード3に対応してたので、これが必要なWSとかでも使えたはずなんですよね)、#if definedで切る必要すらないと思うのですが…やっぱしFMVのオプションという位置づけの対応なんですかねぇ…。

    尚、ソースが見れるのはi8042prt.sysの中身だけなので、送信側がどういう風になっているのかは不明です。現状送信されているのかどうかについても、ダミーのレイアウト / フィルタドライバを差さないと見れないので、こちらでは調べていません。

    あとがき

    思えばこれまでも、Win8対応富士通製ドライバのうち、x86版だけなぜかWin7までのドライバと同じバージョン表記のバイナリ(但しタイムスタンプやサイズは異なる)になっていたり、Win8.1や10にしつこく標準親指シフトドライバが残っているのを確認していたりしたので、そこでちゃんと深追いしておけばもっと早く気づけたのかなという気がしています…。思い込みと切り分けの甘さは今後注意していく所存です。

    しかしながら、このような「割と巨大なブラックボックスを相手にニッチな機能の正確な挙動を調べる」というのを一人の個人だけがやってるのは、どうやっても正確性の面で厳しいのでは? とも感じています。私が用意できる環境には限りがあるので、どうしてもその範囲内で観測できたことしか気づきませんし、その中での調査しかできません。ですので、もし他にも私が思いっきり間違えたことを書いてるような箇所がありましたら、遠慮なくご指摘頂けると幸いです。調査のきっかけは単なる好奇心でだったり必要に迫られたもの(親指絡みではこっちが多いかも)だったりしますが、折角調べたので自分以外の誰かも必要としているなら…と思って掲載しています。間違いがそのままになっているのは不本意ですので、お手元での追試結果が記載内容と違ったりしたら是非教えて頂けると有り難いです。

    開く コメント(2)

    全8ページ

    [1] [2] [3] [4] [5] [6] [7] [8]

    [ 次のページ ]


    .


    プライバシー -  利用規約 -  メディアステートメント -  ガイドライン -  順守事項 -  ご意見・ご要望 -  ヘルプ・お問い合わせ

    Copyright (C) 2019 Yahoo Japan Corporation. All Rights Reserved.

    みんなの更新記事