DLLのリロードについて への返答

投稿で使用できる特殊コードの説明。(別タブで開きます。)
本名は入力しないようにしましょう。
投稿した後で削除するときに使うパスワードです。返答があった後は削除できません。
返答する人が目安にします。相手が小学生か社会人かで返答の仕方も変わります。
最初の投稿が質問の場合、質問者が解決時にチェックしてください。(以降も追加書き込み・返信は可能です。)
※「過去ログ」について書くときはその過去ログのURLも書いてください。

以下の返答は逆順(新しい順)に並んでいます。

投稿者 魔界の仮面弁士  (社会人) 投稿日時 2011/9/10 18:49:31
試したわけでは無いですが、私の認識としては:

・LoadLibrary 自体は、プロセスに対してマップされる。
・複数スレッドからの同時呼び出しに耐えられるかどうかは DLL 次第。
・同一プロセス上の複数のスレッドからそれぞれ LoadLibrary しても問題は無いが、
 ロードされる DLL のメモリ空間は、呼び出し元スレッドではなく、その親プロセスに配置される。

という認識ですね。


> スレッドを10個立てる場合に
DLL を複数のスレッドから呼び出せるかどうかは、ケースバイケースだと思います。
unlha32.dll などはマルチスレッドでの呼び出しに対応していませんし、一方で、
basp21.dll はマルチスレッド環境での利用を前提に設計されています。


たとえばその DLL がグローバル変数を利用していた場合、その変数は
LoadLibrary もしくは Declare した親プロセスのメモリ空間に配置されるので、
実行時には、親プロセスにとってのグローバル変数と同種の状況に置かれ、
結果としてスレッドセーフとはなりません。(呼び出し元で同期制御が必要)

複数同時に呼び出したいのであれば、マルチスレッドで動作させるのではなく、
マルチプロセスで扱った方が良いでしょう。あるいは、DLL を複数個用意するとか。

とはいえ、その DLL が同時利用不可なリソース(Clipboard や COM ポート等)を操作している場合には、
たとえマルチプロセスで動作させても並列動作とはならず、結局は同期制御が要求されることもあります。


以下はVB 側の話では無いですが、一応参考情報として。
http://support.microsoft.com/kb/118816/ja
http://www.sado.co.jp/system/taka/TLS/default.htm
http://konuma.txt-nifty.com/blog/2005/12/loadlibrary_5427.html
http://ruffnex.oc.to/kenji/text/dll_inj/
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200903/09030026.txt
投稿者 hajime  (社会人) 投稿日時 2011/9/8 07:30:41
魔界の仮面弁士さんありがとうございます。

LoadLibrary/FreeLibraryを使ってみようと思います。
こちらでうまくいかない場合は別プロセスを考えます。

LoadLibrary/FreeLibraryを使用する場合、
スレッドを10個立てる場合に、スレッド毎にLoadLibrary/FreeLibraryを行う必要があるのでしょうか?
この部分の理解に苦しんでおります。

お分かりでしたら、ご教示よろしくお願いいたします。

よろしくお願いいたします。
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2011/9/5 22:41:33
Declare の部分を別プロセスにしてしまうというのは如何でしょうか。
プロセス間通信を行う必要はありますが、EXE が別ならば再起動も簡単に行えるでしょうし。

EXE を分けたくないのであれば、LoadLibrary/FreeLibrary を使って
DLL を動的にロードするという手法もあります。
http://dobon.net/vb/dotnet/links/extractarchive.html
投稿者 hajime  (社会人) 投稿日時 2011/9/5 22:33:23
VB2005を使用しています。

SATAを介してドライブと通信を行っているのですが、
動作させているソフトを立ち上げた状態で、ドライブの電源をOFFし、再度ONすると、
通信が出来なくなります。
この状態で、ソフトを再度立ち上げ直すと通信が出来るようになります。
マイコンピュータ上でもドライブの電源OFF・ON後、認識していることを確認しています。

構成ですが、
VC++で通信用のDLLを作成しています。
VBからは、そのDLLをDeclareで使用しています。
DLLの中には、通信用のSCSIドライバ(客先から入手)があり、
こちらで作成したのは、SCSIドライバの関数を呼び出しているだけです。

客先のアプリケーションは(C?)、ドライブ電源をOFF・ONしてもそのまま使うことが出来るのですが、
こちらで作成した(VB)ソフトでは通信が出来なくなります。

客先からも現在聞くことも出来ない状況で、原因も分からない状態です。
そこで、DLLをリロードのようなことをすればうまくいくのではと思い、色々調べたのですが、
解が見つかりません。

他に原因として推測したのは、ドライブ電源をOFFすると、一度確立したドライブとの通信が切れて、
再度電源をONしたときには、別の通信経路(ID?など変化)してしまっているのではと推測しています。(不明)
また、VC++でのDLL作成方法が悪いのか、VBでの呼び出し方が悪いのか、迷走しています。

DLLのリロードの方法がいいのか悪いのかも分からず、
他の方法などもありましたら、どなたかご教示いただけないでしょうか。

よろしくお願いいたします。