Linux でファイルを実行するときに「そのようなファイルまたはディレクトリはありません」というプロンプトが表示される理由を深く理解する

Linux でファイルを実行するときに「そのようなファイルまたはディレクトリはありません」というプロンプトが表示される理由を深く理解する

1 背景

最近、ZC706-ARM 開発ボードの Linux システムでコンパイル システム (apt をサポートしていない) を構築する方法を研究しています。たまたま、会社に ubunut システム (apt をサポート) を搭載した Nvidia ARM 開発ボードがあることを知りました。このとき、Nvidia ボードでコンパイルされたプログラムは ZC706 ボードで実行できるのではないかというアイデアが浮かびました。

2 プロセス

NVIDIAの開発ボードでは、gcc acがa.outを生成し、それをZC706にコピーして実行すると、「そのようなファイルまたはディレクトリはありません」と表示されます。

以前遭遇した理由は次のとおりです。

  • ファイル自体が存在しないか、ファイルが破損しています
  • 実行権限がありません (chmod 777 xxx)
  • システムビット番号がプログラムビット番号と異なります

しかし、以下のプロセスの後、ZC706 には xx プログラム用の指定されたローダーがないことが判明しました。

1. ファイルの破損やその他の問題を排除する --> コピー検証を再生成する
2. プログラムの権限の問題を解消する --> chmod 777 xx && ls -all
3. unanme -a でアーキテクチャの問題を排除する
4. readelf fileなどのコマンドを使用して、正常に実行されたファイルと誤って実行されたファイルの違いを比較します。

検証プロセス:

a.out は NVIDIA gcc でコンパイルされており、zc706 には上記の問題があります | b.out は x86 ubunut でクロスコンパイルされており、正常に実行できます

その後、Googleで調べたところ、ローダーでもこの現象が発生する可能性があることがわかりました。以下から、両者の違いは主にインタープリターにあることがわかります。

解決:

1. コンパイラとライブラリの関係を統一する

2. ソフトリンク ln -s /lib/ld-linux.so.3 /lib/ld-linux-armhf.so.3 を作成します。

3. プログラムをコンパイルするときに、-staticオプションを追加してプログラムを静的にリンクします。つまり、動的ライブラリを使用しません。

root@tegra-ubuntu:~# readelf -h a.out
ELF ヘッダー:
 マジック: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
 クラス: ELF32
 データ: 2の補数、リトルエンディアン
 バージョン: 1 (現在)
 OS/ABI: UNIX - System V
 ABI バージョン: 0
 タイプ: EXEC (実行可能ファイル)
 マシン: ARM
 バージョン: 0x1
 エントリポイントアドレス: 0x8315
 プログラムヘッダーの開始: 52 (ファイル内のバイト数)
 セクション ヘッダーの開始: 4500 (ファイル内のバイト数)
 フラグ: 0x5000402、エントリ ポイントあり、バージョン 5 EABI、ハード フロート ABI
 このヘッダーのサイズ: 52 (バイト)
 プログラムヘッダーのサイズ: 32 (バイト)
 プログラムヘッダーの数: 9
 セクション ヘッダーのサイズ: 40 (バイト)
 セクションヘッダーの数: 30
 セクション ヘッダー文字列テーブル インデックス: 27
root@tegra-ubuntu:~# readelf -h b.out
ELF ヘッダー:
 マジック: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
 クラス: ELF32
 データ: 2の補数、リトルエンディアン
 バージョン: 1 (現在)
 OS/ABI: UNIX - System V
 ABI バージョン: 0
 タイプ: EXEC (実行可能ファイル)
 マシン: ARM
 バージョン: 0x1
 エントリポイントアドレス: 0x86bc
 プログラムヘッダーの開始: 52 (ファイル内のバイト数)
 セクション ヘッダーの開始: 4136 (ファイル内のバイト数)
 フラグ: 0x5000202、エントリ ポイントあり、バージョン 5 EABI、ソフト フロート ABI
 このヘッダーのサイズ: 52 (バイト)
 プログラムヘッダーのサイズ: 32 (バイト)
 プログラムヘッダーの数: 8
 セクション ヘッダーのサイズ: 40 (バイト)
 セクションヘッダーの数: 31
 セクション ヘッダー文字列テーブル インデックス: 28
root@tegra-ubuntu:~# readelf -l helloworld | grep インタープリター
readelf: エラー: 'helloworld': そのようなファイルはありません
root@tegra-ubuntu:~# readelf -l a.out | grep インタープリター
   [プログラムインタープリターを要求しています: /lib/ld-linux-armhf.so.3]
root@tegra-ubuntu:~# readelf -l b.out | grep インタープリター
   [プログラムインタープリターを要求しています: /lib/ld-linux.so.3] 

3 ldローダーの紹介

Linux は、この ld-linux.so* (仮想マシン x86 上の Ubuntu は ld-linux.so2 を使用) を使用して、他のライブラリ (実際にはこれは単なるリンク) を読み込みます。したがって、このライブラリは linux/lib に配置する必要があります。その他の場合、共有ライブラリは通常、システムのデフォルトの検索パスでもある /lib パスに配置されます。

Linux 共有ライブラリの検索パスの順序は次のとおりです。
1. ターゲットコードをコンパイルするときに指定する動的ライブラリ検索パス: コンパイル時に -Wl,-rpath=path を指定します。
2. 環境変数 LD_LIBRARY_PATH で指定された動的ライブラリ検索パス
3. 設定ファイル /etc/ld.so.conf で指定された動的ライブラリ検索パス
4. デフォルトの動的ライブラリ検索パス /lib
5. デフォルトの動的ライブラリ検索パスは/usr/libです

知らせ:

1. 一部の開発ボードでは、/etc に ld.so.conf がないことが分かります。このとき、ldconfig を実行すると、「ldconfig: 警告: 開けない設定ファイルを無視します: /etc/ld.so.conf: そのようなファイルまたはディレクトリはありません」というメッセージが表示されます。

解決策: ライブラリを環境変数に追加し、ldconfig -v (/sbin/ldconfig: キャッシュの構築に相対パス `–v' を使用) を実行します。

2. 共有ライブラリは共有オブジェクトを開けません

動的にリンクされているかどうかをテストします。libtest.so がリストされている場合、リンクは正常であるはずです。

現時点では、libtest.so が見つかりません。ダイナミック リンク ライブラリの検索パスに問題があります。したがって、ダイナミック ライブラリの検索場所を上に追加してください。

3 ldconfig コマンドは、主に、デフォルトの検索ディレクトリ (/lib および /usr/lib) とダイナミック ライブラリ構成ファイル /etc/ld.so.conf にリストされているディレクトリで共有可能なダイナミック リンク ライブラリ (形式は前述の lib*.so*) を検索し、ダイナミック ローダー (ld.so) に必要な接続ファイルとキャッシュ ファイルを作成します。

4 LD_LIBRARY_PATH: この環境変数は、ダイナミック リンカーがダイナミック ライブラリをロードできるパスを示します。 root 権限がある場合は、/etc/ld.so.conf ファイルを変更して /sbin/ldconfig を呼び出すことで同じ目的を達成できます。ただし、root 権限がない場合は、bash コマンドを使用して LD_LIBRARY_PATH を出力する方法しか使用できません。

以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • Linux で so または実行可能プログラムの依存ライブラリを表示します
  • Android 用 Linux カーネル ドライバーをテストするために Ubuntu に組み込みの C 実行可能プログラムを実装する

<<:  古典的なJavaScriptの再帰ケースの質問の詳細な分析

>>:  MySQL 8.0.16 winx64 のインストールと設定方法のグラフィックチュートリアル (win10 の場合)

推薦する

WeChatアプレットシングルページアプリケーションルーティングを徹底的に理解するための10分

シングルページアプリケーションの特徴「前提:」Web ページには、クリックするとサイト内の他のページ...

JavaScript の新しい要素トラバーサルプロパティを使用して子要素をトラバースする方法を学びます

目次1. ChildNodes属性のトラバーサル2. 要素シリーズ属性のトラバーサル以前は、chil...

Docker - コンテナマウントディレクトリを変更する3つの方法のまとめ

方法 1: 設定ファイルを変更する (docker サービスを停止する必要があります) 1. doc...

WeChatアプレットはシンプルな手書き署名コンポーネントを実装します

目次背景:必要:効果1. アイデア2. 実装1. ページとスタイル2. 初期化3. クリックすると4...

Vueナンバープレート入力コンポーネントの使い方の詳しい説明

参考までに、シンプルなナンバープレート入力コンポーネント(vue)です。具体的な内容は次のとおりです...

Dockerのインストール方法とDockerの4つのネットワークモードの詳細説明

1. Dockerをインストールするyum -y install docker-ioインストールが完...

Dockerコンテナ内にkibanaトークナイザーをインストールする方法

ステップ: 1. 仮想マシンディレクトリに新しいdocker-compose.ymlファイルを作成し...

nginxフォワードプロキシとリバースプロキシの詳細な説明

目次フォワードプロキシnginx リバースプロキシnginx リバースプロキシ 02リバースプロキシ...

よく使われる HTML 形式のタグ_Powernode Java Academy

1. タイトルHTML では、<h1></h1> から <h6>...

DCL を使用して MySQL でユーザーを管理し、権限を制御する方法

DCL (データ制御言語): データベースのアクセス権とセキュリティ レベルを定義し、ユーザーを作成...

MySQLトリガーはPHPプロジェクトで情報のバックアップ、復元、クリアに使用されます。

例: PHP バックグラウンド コードを通じて、従業員情報を削除したり、削除した従業員情報を復元した...

Javascript サンプル プロジェクトでの虫眼鏡効果の実装プロセス

目次序文事例: JD.com の虫眼鏡効果の模倣オフセットシリーズクライアントシリーズスクロールシリ...

Vueバインディングクラスとバインディングインラインスタイルの実装方法

目次バインディングクラスインラインスタイルのバインディングバインディングクラス方法1:オブジェクト構...

Docker を使用して Django プロジェクトをデプロイする方法の例

また、Dockerを使用してDjangoプロジェクトをデプロイするのも非常に簡単です。とても良いです...

Docker nginxのインストールと設定方法

DockerでNginxイメージをダウンロードする docker プル nginx Docker イ...