目次
環境
- VMware® Workstation 16 Pro (バージョン: 16.1.2 ビルド-17966106)
- ubuntu-22.04.2-デスクトップ-amd64
問題の状況
- 数百万の同時実行でサーバー プログラムを実行していると、プログラムが実行され、次のようにレポートが実行されます:セグメンテーション違反 (コアがダンプされました)により、プログラムが異常終了します。
ソリューション_
- 最初のステップは、コア ダンプ ファイルの生成パスとサイズ制限を決定することです。次に、GDB などのデバッガーを使用してコア ダンプ ファイルとスタック トレース情報を分析し、コード内の「セグメンテーション違反」の原因を修正します。
原因分析
1. セグメンテーション違反とは何ですか?
- セグメンテーション フォールト (セグメンテーション フォールト) は、通常、無効なメモリ アドレスにアクセスしたときに発生する一般的なプログラム エラーです。プログラムがそのプログラムに属していないメモリ セグメントにアクセスしようとすると、オペレーティング システムはセグメント フォールトと呼ばれる信号 (SIGSEGV (セグメント フォールト信号)) をプログラムに送信します。
2. セグメンテーションエラーが発生する可能性があります
- メモリ アクセス エラー:最も一般的な原因の 1 つは、プログラムが無効なメモリ アドレスまたは初期化されていないポインタにアクセスしようとした場合です。これは、コード エラー、バッファ オーバーフロー、メモリの範囲外などが原因である可能性があります。システムがアクセスを許可されていないメモリ領域にプログラムがアクセスしようとすると、オペレーティング システムはセグメンテーション フォールトをスローします。
- 無効な命令または操作:もう 1 つの一般的な原因は、プログラムが無効な命令または操作を実行することです。これは、コンパイル エラー、間違ったコード ロジック、アーキテクチャの非互換性などが原因である可能性があります。セグメンテーション フォールトは、プロセッサが無効な命令または操作を実行しようとすると発生します。
- 動的メモリ割り当ての問題:
malloc
や など の動的メモリ割り当てを使用する 場合new
、メモリ リーク、解放されたメモリの繰り返しの解放、または解放されたメモリへのアクセスなどの問題により、セグメンテーション違反が発生する可能性があります。これらの問題は、不適切なメモリ管理によって発生する可能性があります。- スタック オーバーフロー:無限の再帰呼び出しや多数のローカル変数の使用によるスタック オーバーフローなど、プログラムのスタック領域が許容範囲を超えると、セグメンテーション フォールトが発生します。
- ライブラリまたは依存関係の問題:セグメンテーション違反は、壊れたライブラリ、互換性のないバージョン、または依存関係の欠落を使用することによって発生することがあります。ライブラリの誤用や構成の問題により、セグメンテーション違反が発生する可能性があります。
- ハードウェアの問題:まれではありますが、メモリ破損などのハードウェア障害によって、プログラムがセグメンテーション違反を報告し、コア ダンプを生成する場合もあります。
3. コアはどこにダンプされますか?
- プログラムにセグメンテーション違反が発生すると、オペレーティング システムは
core
または というコア ダンプ ファイルを生成しますcore.<进程ID>
。このファイルには、プログラムがクラッシュしたときのメモリ イメージやその他の関連情報が含まれています。このコア ファイルは通常、現在の作業ディレクトリにダンプされます。- しかし、コアファイルはプログラムの作業ディレクトリに生成されません。以下の解決策を参照してください...
解決策
1. OSのコアダンプファイル生成設定を確認します。
- コマンドを使用して、
ulimit -a
現在のコア ダンプ ファイル サイズ制限およびその他の制限情報を表示します。- 出力内の「コア ファイル サイズ」フィールドを探します。赤いボックスは、
0
コア ファイルの生成が現在無効になっていることを意味します。この制限を変更して、コア ダンプ ファイルの生成を有効にすることができます。
2.「コア ファイル サイズ」フィールドの制限を変更して、コア ダンプ ファイルの生成を有効にします。
ulimit -c unlimited
コマンドulimit
を使用してコア ファイルのサイズ制限を無制限に設定できますが、コマンドで設定したパラメータは現在のシェル プロセス、つまり現在のセッションでのみ有効です。ターミナル ウィンドウを閉じると、設定はデフォルトにリセットされます。したがって、この変更は永続的なものではありません。(推奨されません)- コア ファイルの生成サイズ制限をシステム レベルで永続的に変更する場合は、オペレーティング システムの構成を変更する必要があります。
/etc/security/limits.conf
コア ファイルのサイズ制限は、ファイルを変更することで設定できます 。次の 2 行を追加または変更します。
- * ソフトコア無制限
- *ハードコア無制限
- 仮想マシンを再起動し、システム パラメータ設定をリロードして、変更が確実に有効になるようにします(再起動コマンド: sudo reboot )。
3. あまり言うことはありません。直接テストしてください
- サーバー プログラムはもう実行したくありません。時間がかかりすぎるため、テスト クリを直接書きます。コードは次のとおりです。
- テスト チェストナットの実行後、プロジェクト ディレクトリにコア ファイルは生成されません。
4. コアファイルの生成パスを決定します。
- Linux カーネルには、
kernel.core_pattern
コア ダンプ ファイルを生成するときにファイル名とパス モードを指定するためのパラメーターがあり、関連する構成ファイルは であるという情報を見つけます/proc/sys/kernel/core_pattern
。ただし、Linux では、sysctl
コマンドを使用してコア ダンプ ファイルの生成パス制限を調査および変更できます。- 次に、
sysctl kernel.core_pattern
コマンドを使用して、現在のコア ダンプ ファイルの生成パスを表示します。次の行が出力されます。
- kernel.core_pattern = |/usr/share/apport/apport -p%p -s%s -c%c -d%d -P%P -u%u -g%g -- %E
- 上記の行は何を意味しますか? 説明は次のとおりです。
|/usr/share/apport/apport
: 特別なコア ダンプ ハンドラー (コア ダンプ ハンドラー) であり、障害を収集して報告するためのツールです。プロセスがシグナルSIGSEGV
または同様のシグナルを受信すると、カーネルはkernel.core_pattern
で指定されたハンドラーを使用してコア ダンプ ファイルを処理します。%p
: プロセスID。%s
: 現在実行中のスレッドの ID。%c
: コア ダンプ ファイルを生成する信号コード。%d
: シーケンス番号。同じディレクトリ内で生成されるコア ダンプ ファイルの一意の名前を保証するために使用されます。%P
: 親プロセスID。%u
: ユーザー名。%g
: グループ名。%E
: コア ダンプ ファイルを生成した実行可能ファイルのフル パス。- 具体的には、
/usr/share/apport/apport
クラッシュや障害に関する情報を収集し、対応するエラー レポートを生成する Ubuntu システム用のツールです。
5. コアファイルの生成パスを変更する
- これは、コマンドを使用して
sudo sysctl -w kernel.core_pattern=<path_to_directory>/core
目的のパスに復元できます。<path_to_directory>
有効なディレクトリ パスであることを確認してください 。例えば
- sudo sysctl -w kernel.core_pattern=core
- 再コンパイルすると、
core.<进程ID>
カレントディレクトリに生成されるコアダンプファイルは次のようになります- 注:
kernel.core_pattern
上記の方法で変更された値は実行時にのみ有効になり、永続的ではありません。システムの再起動後、変更はデフォルト値にリセットされます。- 最後のセクション「外部知識」について学ぶことができます。
6. デバッグ ツール gdb を使用して、コア ファイルをロードして分析します。
- コア ファイルを生成します。gccでコンパイルする場合は、必ず -g コマンドを追加してください。
- コア ファイルをロードします。gdbコマンド ラインを使用してコア ファイルをロードし、コア ファイルをデバッグ環境にロードします。
- gdb <実行可能ファイルへのパス> <コア ファイルへのパス>
- スタック トレースを表示する: gdb を実行した後、
bt
コマンド ( またはbacktrace
) を使用してスタック トレースを表示します。スタック トレースには、クラッシュ時のプログラムの関数呼び出しチェーンが表示されます。
- (gdb)bt
- 変数の値を確認する:
- (gdb) 変数名を出力する
- 特定のフレームにジャンプする:コマンドを使用して
frame
スタック フレーム間を移動し、特定のフレームのスタック情報を表示します。フレーム番号は通常、0 から始まる逆順に割り当てられます。つまり、最下位のフレームには 0 の番号が付けられます。
- (gdb) フレーム フレーム番号
- 原因の分析:スタック バックトレースと変数値を分析すると、プログラム クラッシュの原因を特定するのに役立ちます。通常、最下位のスタック フレームが元のクラッシュの場所を示します。
- 操作は次のとおりです。 *P は初期化されないことに注意してください。
余分な知識
1. /proc/sys/kernel/core_patternに書き込み権限を追加できますか?
- 答えはいいえだ。デフォルトの権限は次のとおりです (所有者には読み取りおよび書き込み権限があり、グループ ユーザーとその他のユーザーには読み取り権限のみがあります)。
- ファイルの場合
/proc/sys/kernel/core_pattern
、読み取り権限を直接追加することはできません。これは、/proc
ディレクトリとその下のファイルがprocfs
、カーネルおよびプロセス情報へのアクセスを提供するために使用される仮想ファイル システム ( ) の一部であり、そのアクセス許可と所有権がカーネルによって制御され、Linux ファイル システムのアクセス許可モデルによって制限されないためです。 。- ディレクトリでは
/proc
、各ファイルとディレクトリの権限は通常読み取り専用に設定されており、ユーザーは自分の権限を直接変更することはできません。これは、提供される情報の整合性と一貫性を確保し、カーネルとプロセスの状態への不正な変更を防ぐためです。- したがって、通常の
chmod
コマンドなど を使用して/proc/sys/kernel/core_pattern
、読み取り権限を直接追加したり、その権限を変更したりする方法はありません。次のようなコマンドを実行しようとするとエラーが発生します。
- sudo chmod +w /proc/sys/kernel/core_pattern
- 「操作は許可されていません」または「操作は許可されていません」などのエラー メッセージが表示されます。
2.システムを再起動すると、
/proc/sys/kernel/core_pattern
ファイルへの変更がデフォルトにリセットされるのはなぜですか?
- これは、
/proc/sys/
ディレクトリ内のファイルがカーネルの起動時に動的に生成され、その値がカーネル パラメーターまたはその他のシステム設定から取得されるためです。システムの再起動時に、これらのファイルはデフォルト値または特定の構成ファイルで指定された値で再ロードされます。
3.
/proc/sys/kernel/core_pattern
ファイルを永続的に変更するにはどうすればよいですか? (これには問題があります)
/etc/sysctl.conf
ファイルを編集します: (この方法はあまり適切ではありません。システムを再起動するたびに、 sudo sysctl -p コマンドを実行して /proc/sys/kernel/core_pattern の値を変更する必要があります)
/etc/sysctl.conf
次のようにファイルを編集して、コア ダンプ ファイル スキーマへの変更をファイルに追加 できます 。
- kernel.core_pattern = コア
- ファイルを保存して終了した後、次のコマンドを使用して設定を再ロードし、新しいコア ダンプ ファイル モードを有効にします。
- sudo sysctl -p
- システム起動スクリプトの作成および編集:システム起動時にコア ダンプ ファイル モードを目的の値に設定するスクリプトを作成できます。スクリプトを
/etc/init.d/
ディレクトリなどの適切な場所に配置し、システム起動時に実行されるように設定します。(テストしても無駄でした)
- 起動スクリプト ファイルの作成:選択したディレクトリに新しいファイルを作成します。
- sudo vim /etc/init.d/my_startup_script.sh
- 起動スクリプトを作成します。スクリプトに次の内容を追加し、正常に保存して終了します。
- #!/bin/bash
- echo "コア" >> /proc/sys/kernel/core_pattern
- 0番出口
- スクリプトの実行権限を与える:以下のコマンドを使用して起動スクリプトファイルに実行権限を与えます。
- sudo chmod +x /etc/init.d/my_startup_script.sh
- 起動スクリプトの実行を構成する:起動スクリプトをシステムの起動プロセスに追加して、システム起動時に確実に実行されるようにします。
- sudo update-rc.d my_startup_script.sh のデフォルト
- スクリプトの起動を無効にするには、次のコマンドを使用できます (学習)
- sudo update-rc.d -f my_startup_script.sh 削除
知らせ
/proc/sys/kernel/core_pattern
ファイルのアクセス許可とコンテンツの変更は機密性の高い操作であり、システムの安定性とセキュリティに影響を与える可能性があることに注意してください 。常に注意を払い、加えた変更の影響を必ず理解してください。