2023-11-18

鉄道のホームにあるホームドアが閉まる途中で異常を検知した場合の挙動

最近は鉄道のホームにホームドアが設置されるようになってきました。しかも車両のドア位置の関係で、ドアといういうより、ロープが上下するような方式があります。JR西日本が大阪駅などで設置しているものです。ドアであっても、ロープであっても、閉めている最中に異常を検出したとしたら、例えば何かを挟み込んだとセンサーが検出したら、いったん開くように動くのが普通ではないかと思います。

 

しかし開くといっても、全て開く必要はないのではないでしょうか。異常を検出した所だけ開いて、後は閉じても構わないのではないでしょうか。もし異常が起きていいない箇所も開いてしまうと、駆け込み乗車をしようとしている人が突進する可能性があるのではないかと思います。

 

先日ホームで電車を待っていたら、異常を検出したらしく、閉まりかけているホームドアが途中で開きはじめたのを目撃しました。しかも異常がない(と思われる)ところも含めて全てが開きました。 どのような挙動が望ましいと言えるのか不明ですが、ホームドアの動作方式は現在進行中という印象です。

2023-11-16

「The BSD Packet Filer: A New Architecture for User-level Packet Capture」を読んでみました

MOPDを調べようとしたら、BPFが使われているので、横道にそれてしまうようですが、BPFを理解するのを先に済ませることにしました。マニュアル「BPF(4)」を読むことも必要かと思いますが、そもそもBPFって結局何なのかを知るには大元となる論文を読むのがよさそうです。それは、1993年のWinter USENIXにおける「The BSD Packet Filter: A New Architecture for User-level Packet Capture」(Steven McCanne and Van Jacobson)との事なので、読んでみました。

 

論文の中に次のような記述がありました。

 A packet filter is simply a boolean valued function on a packet. If the value of the function is true he kernel copies the packet for the application: if it is false the packet is ignored.


これを読んで、成程そういう事かと思いました。BPFについて調べはじめた当初、Webを検索すると、何かというと「仮想マシン」の話が出てきました。何故BPFと仮想マシンが結びつくのだろうと思いましたが、論文を読んで納得しました。

 

BPFについて何を理解したら「わかった」という事になるのかという点では、いろいろと意見が別れるところだと思います。しかしMOPDを理解するためのBPFという意味では、「わかった」という事にしても構わないと思います。

2023-11-14

「BPF(BSD packet Filter)」は「パケットをフィルタリングする」だけが目的ではないような気がする

MOPDを調査するために、BPFを調べる必要を感じたので、先にそちらを見ています。ウィキペディアの「Berkeley Packet Filter」には、概要として最初に以下のような事が書かれています。

 BPFはデータリンク層へのrawインターフェイスを提供し、生のリンク層パケットの送信と受信を可能にする。

 

BPFの「PF」は「Packet Filter」なんですから、上記した記述はもっともだと思います。しかしBPFの目的はそれだけではないような気がします。ウィキペディアの概要を読み進めると、次のような記述が現れます。

この機能を利用することで、オペレーティングシステムのカーネルからプロセスへの不要なパケットのコピーが回避され、パフォーマンスが大幅に向上する。


ネットワークのパケットを送受するのはカーネル内部ですが、それをユーザプログラム側が操作しようとすると、カーネルとユーザ側の遷移が数多く発生します。そのままでは性能に悪影響を及ぼしてしまうため、特別な仕組みが用意され、それが「BPF」なのでしょう。当初の目的がネットワークのパケットをフィルタリングして、必要なものだけをユーザプログラム側で操作したかったという事なのではないかと思いますが、その為の仕組みの有用性に注目が集まっているという事のように思います。


Linuxでは「eBPF」という拡張がなされており、ウィキペディアでは「eBPFプログラムをさまざまなTracepointにアタッチする用途など、ネットワーク以外の目的でも使用できる」と書かれているように、もはやネットワークに限った技術ではなくなっているようです。しかも旧来の「BPF」との互換性はないようなので、だったら名前を「eBPF」としないで、別の名前にしたら良かったのではないかと思いますが、そうもいかなかったのかもしれません。


2023-11-13

The Icon Programming Language

MOPDの構造を調べるには、BPFを知る必要があるようです。その原理は「The BSD Packet Filter: A New Architecture for User-level Packet Capture 」という1993年に発表された論文に遡るようなので、入手しました。その論文の最後にある参照文献には、次のような記述がありました。

 [3] GRISWOLD, R. E., AND GRISWOLD, M. T. The Icon Programming Language. Prentice Hall, Inc., Englewood Cliffs, NJ, 1983.

 

Iconという言語は、あまり知られていないかと思います。今日ではテキスト処理と言ったら、PythonやPerlなどが使われると思いますが、まだAWKくらいしか選択肢が無かった頃に、SNOBOLやIconという言語を耳にすることがありました(それでもメジャーとは言い難かったと思いますが)。

 

公式サイトはありますが、今でも活動が続いているのか否かはわかりません。『The Icon Programming Language Third Edition』という書籍があり、ずいぶん前に購入しました。今でも捨てずに持っています。寄附金を募っていたようなので、ほんの僅かな金額ですが送りました。そうしたら礼状が返ってきて、感激した記憶があります。


BPFがIconをどう使っているのか詳細は不明ですが、論文には以下のような記述がありました。

 A very different application of BPF has been its incorporation into a variant of the Icon Programming Language [3].

 

Iconの公式サイトにはFreeBSDやLinux用のバイナリも置いてあります。Pythonが大流行している今日において、Iconを使う必要性があるのか何とも言えませんが、ちょっと勉強してみるのも悪くないかなと考えています。

2023-11-10

VMware Workstation 17 PlayerでUbuntu 22.04 LTSをインストールしようとすると、とても遅い

Ubuntu 22.04 LTSの環境をVMware Workstation 17 Player 17.5.0 build-22583795で作ろうとしたら、インストールするのが酷く遅くて、途中で断念しました。同様の作業をVirtualBox 7.0.12 r159484 (Qt5.15.2)でも行いましたが、順調で、特に問題は起きませんでした。VMplayerを使うと、異常に遅いのは、何か設定の問題なのでしょうか。

 

Webを検索したら「Windows 10 VM Slow in Ubuntu 22.04 Host Workstation Pro 16.2.4 build-20089737」という記事を見つけました。同じような現象を抱えている人はいるようで、解決策もあるようなのですが、VMware Workstation Playerでは、同じ解決策が適用できないようです。

 

 リプライには「I don't see this option with VMware Player. Any hints?」という発言があり、私と同じ(と思われる)問題を抱えている人がいるようです。しかし解決策は提示されていません。


どうもVMware側に何か問題があるのではないかと思いますが、WMware Playerでの解決策が見つかりません。

2023-11-09

mopdの実装を調査するためにmopd/mopd.cを読んでみました。オリジナルのmopd-2.5.3が各OSの実装で変更されており、似たような変更を加えていますが、統一化が図られている訳ではないようです。 

  • mopd.cを見ると、MOPD(8)では説明されていないオプションが実装されています。ただしOpenBSD版のMOPD(8)では、そのオプションの説明が加えられています。またNetBSD版では、-sという新しいオプションが追加されています。
  • オリジナル版では、大域変数Programを用いて、argv[0]からプログラム名を得ています。ところが他の実装では、関数getprogname()や変数__prognameを利用するように変更が加えられています。
  • デーモンとして動作させるため、オリジナル版ではfork()を呼び出したりしていますが、他の実装ではdaemon()を利用するように変更が加えられています。

 

オリジナル版も他の実装にも、以下のような処理があります。このロジックならば、ForegroundFlagが指定されておらず、DebugFlagが指定されている場合に、このメッセージが出力されるという事です。しかしメッセージの「not running as daemon」と、ForegroudFlagが指定されていないという状態とが、整合していない気がします。

if ((!ForegroundFlag) && DebugFlag) {
    fprintf(stdout, "%s: not running as daemon, -d given.\n", Program);
}


MOPD(8)では、SEE ALSOにbpf(4)が記載されています。BPFというのはBerkeley Packet Filterの事だという事しか知らないので、勉強しておこうと思います。

2023-11-07

mopd/process.hのバリエーション

mopdの実装を学ぶため、mopdに置いてあるファイルを一つずつ見ていくことにしました。おそらく、ソースを読むために必要となる派生的な技術に手を出す必要が出てくると思いますが、それもこれも勉強だと思います。短期間に全力疾走して解析を終えることにはならないでしょうから、長期に亘ることを意識して、TW5で情報を整理しながら進めていこうと思います。


まず最初にmopd/process.hから見ていきます。このファイルは、コメントを除けば、10数行しかありません。

#ifndef _PROCESS_H_
#define _PROCESS_H_

#ifdef NO__P
void    mopProcessDL (/* FILE *, struct if_info *, u_char *, int *,
                         u_char *, u_char *, int, u_short */);
void    mopProcessRC (/* FILE *, struct if_info *, u_char *, int *,
                         u_char *, u_char *, int, u_short */);
#else
__BEGIN_DECLS
void    mopProcessDL __P((FILE *, struct if_info *, u_char *, int *,
                          u_char *, u_char *, int, u_short));
void    mopProcessRC __P((FILE *, struct if_info *, u_char *, int *,
                          u_char *, u_char *, int, u_short));
__END_DECLS
#endif

#endif _PROCESS_H_

ここで「__BEGIN_DECLS」と「__END_DECLS」のペア、「__P()」というマクロらしきもの、「NO__P」という定義が利用されています。これらが何かを調べるところから始めていきたいと思います。


まず「__BEGIN_DECLS」と「__END_DECLS」は、Web上にある記事「C言語系 / NetBSD1.6における setjmp(), longjmp() の実装(2) (v1)」で説明されていました。同様の説明は他にも見つかったので、それ自体は難しいことは何もありません。ただし調べても不明だったのは、なぜ「extern "C"」を直に記述しないで、これらを使うのかという事です。しかも「8.1 Writing C header files」では、「BEGIN_C_DECLS」と「END_C_DECLS」を使うことにしています。何か歴史的な事情があったのではないかと思うのですが、その経緯がわかりませんでした。


次に「__P()」というマクロは、初期のC言語とANSI Cとのプロトタイプ宣言の違いを吸収するために使うようです。mopd-2.5.3が何時から開発されていたのか、ChangeLogなどがないので、不明ですが、その当時はK&R CとANSI Cの違いを気にする必要があったのでしょう。しかし2023年の今となっては、あまり気にしなくても良さそうです。

 

最後に「NO__P」という定義は、otherOS/Makefileの中で定義されているのを見つけました。rs6000-aix3、sun3-sunos4、sun4-sunos5などの環境下では定義されるようです。多分それらでは「__P()」が存在しないのでしょう。


このファイルがどのように変更されているかを確認してみました。

  • NetBSDでは、「NO__P」の定義を確認している箇所が無くなっていますし、「__P()」も使っていません。
  • OpenBSDでは、NetBSDと同様の対応に加えて、「__BEGIN_DECLS」と「__END_DECLS」も消えています。
  • FreeBSDでは、portsのパッチが増え過ぎないようにしたかったのか、何の変更も加えられていません。
  • Linux版は、NetBSDの変更を取り込んでいるようですが、「NO__P」の定義を確認している箇所が無くなっているものの、「__P()」は残っています。

2023-11-04

mopd-2.5.3の派生

VAXstationなどDEC製品はネットワーク上に存在するマシンから情報を貰ってブートさせることが出来て、これをMOP(Maintenance Operation Protocol)と呼びます。OpenVMSなどDEC製OSであれば当然MOPサーバになれるのですが、NetBSDやLinuxであってもmopdを動かしておけば、MOPサーバとして機能させることが可能です。

 

調べてみると、以下のOSでmopdが動くようです。

 

これらは全て「mopd-2.5.3.tar.gz」という実装から派生していますが、現時点での実装は各々異なっているようです。

  1. NetBSDとOpenBSDは、OSのusr.sbinとして取り込まれており、OSのポリシーに合わせた変更が行われているように見えます。
  2. FreeBSDは、portsとして提供されているので、必要最小限の変更だけで済まされている印象です。
  3. Linuxは、READMEにも書かれていますが、NetBSD版を取り込み、OpenBSD版などの変更を参考にしているようです。
  4. 各OS版とも、オリジナルの「mopd-2.5.3」と構成がほぼ同じになっています。しかしNetBSD版は、mopa.outというコマンドが消えており、mopcopyというコマンドが追加されています。


手持ちのDEC製ワークステーションを生かすために、mopdを準備しようと思っています。どれを使っても構わないとは思いますが、MOPの理解を深めるために、それぞれの変更箇所を詳しく調べてみようと思います。