私が投稿しました質問Wine で実行ファイル (PDF ビューア) を複数のプロセスで独立して実行する方法について (独立とは、プロセス間で通信が行われないことを意味し、並列コンピューティングではない)。ある会社の PDF エディタ (ビューアの拡張版) ではそれができないと聞きました。
質問
- では、実行可能ファイルが複数のプロセスで独立して実行可能または実行不可能になる原因は何でしょうか?
- それはプログラム自体、あるいは何らかのライブラリによって実装されているのでしょうか?
- OS ではそれが実現できないのでしょうか?
答え1
これはほぼ確実にプログラム自体によって実装されており、最も基本的なプログラムを除いて OS が強制することはおそらく不可能です。
ただし、プログラムがすでに実行中であると判断する方法を知っていて、その方法に影響を与えることができる場合は、実行可能ファイルに新しいプロセスを起動させる (または起動させない) ことができます。
Emacs などの一部のアプリケーションでは、これが特に簡単に行えます。Emacs を実行する標準的な方法は、呼び出しごとに新しいプロセスを起動することです。ただし、Emacs をサーバー モードで明示的に実行し、emacsclient
既存のサーバーに新しいファイルにアクセスするように明示的に指示するために を実行することもできます。
反対の例として、Firefox では新しいプロセスを強制的に起動するコマンドライン オプションが提供されています-no-remote
が、デフォルトでは、可能な場合は既に実行中のプロセスと対話します。
多くのシンプルな自家製アプリケーションは、単に を照会するだけで、そのアプリケーションの別のバージョンがすでに実行されているかどうかを確認しますps
。これは、さまざまな方法で回避できます。業務用ソフトウェアの問題は、特定のアプリケーションがすでに使用されているかどうかをどのように判断するかをユーザーがほとんど知らないことです。実行可能ファイルがやり取りするすべての開いているファイルを検査できる Unix でも、アプリケーションが実行中であるという事実を記録する責任があるのはどれか (ある場合) を判断できるという保証はありません。
答え2
プロセスはプログラムのインスタンスです。プログラムは複数回インスタンス化できます。つまり、同じ実行可能コードをロードして複数のプロセスを作成できます。私は次の一文を引用したい。Linuxカーネルを理解するダニエル・P・ボベットとマルコ・チェザーティ著:
プログラムとプロセスを区別することが重要です。複数のプロセスが同じプログラムを実行する可能性があります。同時に同じプロセスが複数のプログラムを実行できる順次。
基本的に、これはプログラムが走るいくつかのインスタンスでは、1つのインスタンスは一度に1つの実行可能コードしかロードできません。したがって、そこから出発して、次のように言うことができます。何もないプログラムが複数のインスタンスで実行されるのを防ぎます。これを禁止する理由はまったくありません。もちろん、これらのプロセスは実行コード以外を共有しません。メモリ ページ、ファイル記述子 (同一のファイルに関係する場合もあります) などは、プロセス間で完全に独立しています。
Unix ライクなシステムに関しては、もう 1 つの点が私にとって重要に思えます (同じ本) :
Unix系オペレーティングシステムはプロセス/カーネルモデル。各プロセスは、それがマシン上の唯一のプロセスであるという幻想を抱いている、オペレーティング システム サービスへの排他的アクセス権を持ちます。
実際、これがUnixシステムがマルチプロセス/マルチプログラミングである理由であり、少なくともこの機能のベースとなっているポリシーです。したがって、この事実により、プロセスがネイティブに知っているまったく同じコードを実行している別のプロセスが、別の CPU で待機しているか、作業中であることを示します。
しかし、各プロセスは1つのことを認識しています。それは、システムがカーネルによって実行されており、プロセスがCPUで作業している間、カーネルのサービスがプロセスによって自由に利用できるということです。これにより、プロセスはクエリ同じ実行可能ファイルのインスタンスとして実行されている他のプロセスについてカーネルに通知します。最初に思いつく解決策は、/proc
仮想ファイルシステムを読み取ることです。この FS は、ユーザー/アプリケーションとカーネル間のインターフェイスのように機能します (これらのファイルはカーネル構造とデータを表しているため)。このファイルシステムでは、各プロセスにディレクトリ (PID で名前が付けられます) が割り当てられ、このディレクトリ内に というリンクがありますexe
。たとえば、私のbash
プロセスのディレクトリ (PID 22343) は次のとおりです。
lrwxrwxrwx /proc/22343/exe -> /bin/bash*
これで、ファイルシステムを参照すると、同じ実行可能コードを実行しているプロセス、つまり、リンクがexe
同じ実行可能ファイルをターゲットとするプロセスを見つけることができます。
ただし、すべての Unix システムが同じ方法で実装されているわけではないため/proc
、開発者は、ほぼすべての Unix システムが理解できる通常のファイルに依存する、より移植性の高いソリューションを使用することを目指しています。.pid
ファイルは通常、このために存在します。
ほとんどの場合、これらのファイルは にあります/run
。たとえば、次のようになります。
-rw-r--r-- /run/acpid.pid
-rw-r--r-- /run/atd.pid
-rw-r--r-- /run/crond.pid
これらのファイルは、それが属するアプリケーションによって作成され、プログラムのインスタンスが実行中かどうかのマーカーとして使用されます。通常、このファイルの内容は、実行中のプロセスの PID で作成されます。この場合、acpid
PID 1503 のプロセスが実行中であり、これがまさに PID ファイルの内容です。
同じプログラムのすべてのプロセスは同じ実行コードを共有するため、定数 (少なくとも値) を共有します。このため、各インスタンスが PID ファイルの検索場所を認識していれば、単一インスタンス プログラムのプログラミングは非常に簡単です。
if (the pid file exists) then
send a signal to the running process or just bring it on the foreground
exit since the work is going to be handled by the already-running process
else
actually start the program, the first instance
endif
最初のケースでシグナルを使用するのは、私が最もよく目にする動作ですが、アプリケーションでより高度な IPC (ソケット、メッセージ キューなど) を使用する場合は、それを使用して、ユーザーが実行する必要がある何かを要求したことをアプリケーションに通知できます。