3

RTOS/OS を使用しない小規模な組み込みシステムは、動的/共有ライブラリを使用しますか。私の理解では、それを使用するのは非常に難しく、生産的ではありません。

静的ライブラリに存在する API を複数回呼び出す場合。API コードはマクロ展開のようにすべての呼び出し場所に配置されますか、またはコード/テキストはすべての呼び出しで共通になりますか。コード/テキストが一般的になると思います。

複数のAPIを持つ.cファイルの静的ライブラリを作成し、それをメインファイルと静的にリンクし、メインファイルで1つのAPIのみが呼び出された場合、私の質問はライブラリ全体が最終的な.binに含まれているか、またはのみ含まれているかです特定の API コード。

上記の質問から、私は基礎自体が欠けていると推測できるので、誰でもこれらをブラッシュアップするための関連リンクを提供してください。

よろしく
[編集]

私は次のことを試しました

add.c モジュール

`int addition(int a,int b)`  
`{`  
`int result;`  
`result = a + b;`  
`return result;`  
`}`

`size addition.o`   
23        0       0      23      17 addition.o    

multiplication.c モジュール

`int multiplication(int a, int b)`  
`{`  
`int result;`  
`result = a * b;`  
`return result;`  
`}`
`size multiplication.o`  
21        0       0      21      15 multiplication.o  

両方のオブジェクトファイルを作成し、アーカイブに入れます

ar cr libarith.a addition.o multiplication.o   

次に、メイン アプリケーションの
example.c モジュール に静的にリンクします

`#include "header.h"`  
`#include <stdio.h>`  
`1:int main()`  
`2:{`  
`3:int result;`  
`4:result = addition(1,2);`  
`5:printf("addition result is : %d\n",result);`  
`6:result = multiplication(3,2);`  
`7:printf("multiplication result is :  %d\n",result);`  
`8:return 0;`  
`9:}`

gcc -static example.c -L. -larith -o example  

size of example  
511141     1928    7052  520121   7efb9 example  

example.c の 6 行目をコメントし
、再度
gcc -static example.c -L をリンクしました。-larith -o example 例
のサイズ
511109 1928 7052 520089 7ef99 example
上記の 2 つの 32 バイトの差
は追加を意味します。o は例に含まれていません

以下のように、addimulation.c と multiplication.c の両方のモジュールを addmult.c としてマージしました。
int addition(int a,int b)
{
int result;
result = a + b;
return result;
}
int multiplication(int a, int b)
{
int result;
result = a * b;
return result;
}

オブジェクトファイルを作成し、
以前のアーカイブを削除したことを行う前にアーカイブに入れました
ar cr libarith.a addmult.oは、example.c gcc -static example.c -L
の行番号 6 をコメント化しました。
-larith -o 例
size example
511093 1928 7052 520073 7ef89 example
uncommented line number of example.c
size example 511141 1928 7052 520121 7efb9 example

私の質問は、両方の関数が呼び出された場合、最終的なテキストサイズは同じですが、1つの関数のみが呼び出された場合、16の違いがありますが、乗算.oサイズは23であるため、間違いなく含まれていませんが、16を正当化する方法.基本的なもの自体が欠けている場合は?

4

3 に答える 3

5

実行時にライブラリを動的にロードしてリンクするには、ロード/リンク操作を実行するコードが必要です。通常、その機能はオペレーティング システムの一部です。さらに、ある種の大容量ストレージのないシステムでは、動的にリンクされたコードはいずれにしてもメモリ内に存在する必要があり、静的にリンクされている可能性があるため、動的リンクには利点がありません。

質問の 2 番目の部分に答えると、静的ライブラリは単にアーカイブ内のオブジェクト ファイルのコレクションです。リンカーは、実行可能ファイル全体で参照されているシンボルを解決するために必要なオブジェクト コードのみを抽出してリンクします。一部のスマート リンカは、オブジェクト ファイル内の未使用の関数を破棄できますが、それに頼るべきではありません。

したがって、静的ライブラリをリンクしても、未使用のコードがすべてライブラリに含まれているわけではありません。おそらく、すべてのライブラリ ファイルのサイズと実行可能バイナリのサイズを比較すると、実行可能ファイルがリンクされたライブラリのサイズの合計よりもはるかに小さいことがわかります。また、リンカーには、どのコードがインクルードされているか、相互参照出力機能がある場合は、どのコードが何を参照しているか、または何によって参照されているかを正確に伝えるマップ ファイルを作成するオプションがあります。

独自の静的ライブラリ、または独自の非ライブラリ コードを構築している場合は、オブジェクト ファイル レベルで適切な粒度を確保するために費用がかかります。たとえば、オブジェクト ファイルに 2 つの関数 (1 つは使用済み、もう 1 つは未使用) が含まれている場合、ほとんどのリンカーは両方を含めるしかありませんが、関数が別々のコンパイル ユニット (ソース ファイル) で定義されている場合、それらは別々のオブジェクト ファイルになります。 (ライブラリに照合された場合でも)個別にリンクできます。

于 2012-07-29T10:14:03.003 に答える
3

実際にオペレーティング システムのない組み込みシステムを使用している場合、ハードウェアには基本的に固定されたソフトウェアがあり、物理的な手段 (はんだごてや何かを差し込むなど) によってのみ変更できます。その場合、そのソフトウェアは「裸の鉄」で実行され、OS が提供していることを何らかの形で実行します (物理リソースを管理し、適切なマシン命令によって I/O ポートと直接やり取りします)。

特に、OS を持たない組み込みシステムでは、動的ライブラリを使用することはできません。これは、定義上、これらのライブラリは (組み込みプロセッサ上の) 一部のファイル内にある必要があり、オペレーティング システムを必要とするファイルを保持する必要があるためです。

オペレーティング システムとは何かという正確な定義は、議論の余地があり、あいまいです。ファイルシステムを提供することは、現在のほとんどの OS の役割の 1 つだと思います

共有ライブラリ (または静的ライブラリ) はいくつかのファイル内にあるライブラリであるため、OS なしでは共有ライブラリを使用できません。ファイルを提供するものは、定義上、オペレーティング システムです。

おそらく、クロス開発チェーンを使用して組み込みソフトウェアを開発しているでしょう。ベア メタルで実行するものを取得したい場合、チェーンは最終的に ROM にフラッシュできる単一のバイナリ イメージを提供する必要があります。次に、その ROM をはんだ付けまたはプラグインするか、何らかの形で物理的に転送して、組み込みハードウェア (いくつかのツール)自己完結型プロセッサ全体をフラッシュできます)。

混乱しているかもしれません。オペレーティング システムカーネルLinux カーネルファイル システムsyscallRTOSリンカローダークロスコンパイラマイクロコントローラ共有ライブラリダイナミック リンカなどについて詳しく読む必要があります。

Clifford がコメントで示唆したように、ファイル システムと動的リンカーを備えた組み込みシステムを使用できます。私の見解では、それは初期のオペレーティング システムになると思いますが、それは議論の余地のある定義の問題です。

動的リンカーを作成するのは簡単な作業ではないことに注意してください ( relocationを実行する必要があります)。一般的なELF動的ローダーを作成するか、動的にロードされるモジュールの形式を制限し、特定のld スクリプトを使用してそれらを生成することができます。

于 2012-07-29T09:09:05.277 に答える
2

あなたはすでにあなたが必要とするすべての基本を持っています。オペレーティングシステム、大容量記憶装置(ディスク、ファイルシステムなど)、および共有ライブラリを利用できる複数の/多くの異なるプログラムがなければ、意味がありません。何も保存しないでください。固定されたベアメタル環境で共有ライブラリを使用するのに十分な偽物を作成した場合は、おそらくもう少しコストがかかります。

あなたはコードソースを持っていると言いましたが、どのようにしてこれらのことを学びますか?バイナリを分解して、コンパイラが何をしたかを確認します。1つの除算を使用したため、gccライブラリ全体をリンクしますか?1つの関数を使用したためにCライブラリ全体をリンクしますか(Cライブラリ関数をリンクしようとしても機能しますか?多くの場合、解決する必要のあるオペレーティングシステムへのシステムコールがあります)。非常に単純な関数で単純な除算を使用することから始めます(汎用である必要があります)

unsigned int fun ( unsigned int a, unsigned int b )
{
 return(a/b);
}

固定定数を使用してその関数を呼び出さないでください。また、同じ.cファイルから呼び出さないでください。最良の方法は、その関数をそのまま追加し、そのままにしておくことです。コンパイルしようとしても問題が発生する可能性があります。一度コンパイルすると、逆アセンブルしてコンパイラがそれをどのように処理したかを確認し、gccライブラリ全体が追加されたか、その1つの関数のコードだけが追加されたかを確認します。

古いWebページやリソースは、使用しているツールとは異なり、古くなっている可能性があるため、信頼できません。現在使用しているコンパイラが重要であり、他にはありません。そして、答えはあなたの目の前にあります。

いいえ、ダイナミックライブラリは使用していません。必要な機能は必要に応じてリンクされています。オプティマイザーはいくつかのコードをインライン化することを選択できますが、一般に、各関数のコードは1つの場所にあり、それに対する各呼び出しは呼び出しであり、一般にマクロのようなものではありません。この場合も、オプティマイザはパフォーマンス上の理由で別の方法を選択する場合があります(メモリをあまり消費しない十分に小さい関数であり、関数呼び出しを行うために必要なコードが関数自体に比べて過剰であるほど小さい。また、その関数は同じ最適化である必要がありますスペース、gccの場合、これは同じ.cファイルです。llvmの場合、これはプロジェクト内の任意のコードである可能性があります。

cortex-mなどのベアメタルの例がいくつかあります。 http://github.com/dwelch67質問に答えるのに役立つものが見つかるかもしれません。たとえば、コンパイラが上記のようなパブリック関数を実装し、使用時にインライン化することを確認してください。関数を静的として宣言する場合、オプティマイザーは、インラインの場合、関数をバイナリで実装する必要はありません。たとえば、同じ.cファイルでそのような関数を呼び出す場合

c = fun(10,5);

オプティマイザを使用すると、そのコードが次のように置き換えられる可能性が高くなります。

c = 2;

除算はまったく実行しません。

于 2012-07-30T03:06:00.533 に答える