あなたが知らないかもしれないバグの場所の方法を共有する

皆さんこんにちは、チャウダーです。

組み込み Linux の開発では、gdb を使用してコア ファイルをデバッグすることは、プログラムのクラッシュを特定する効果的な方法です。この方法については、前回の記事「埋め込みセグメント障害のデバッグ方法3つまとめ!」でも簡単に紹介しました。

一部の知識は、使用されない前に簡単に理解できます。実際に使うときは、詳しく学んでください。最近、実際の作業でgdbを使用してコアファイルをデバッグしました.いくつかの問題に遭遇したので、それらをまとめて共有します.

この記事では、いくつかのポイントを共有します。

  • コアファイルとは何ですか?

  • フォアグラウンド プロセスはどのようにコア ファイルを生成しますか?

  • バックグラウンド プロセスはどのようにコア ファイルを生成しますか?

  • コアファイルをデバッグするには?

  • クラッシュ スタックの有用な情報が限られている理由として考えられるのは?

コアファイルとは何ですか?

Linux では、プログラムがクラッシュすると、通常、指定されたディレクトリにコア ファイルが生成されます。コア ファイルは単なるメモリ イメージ (およびデバッグ情報) であり、主にデバッグに使用されます。

フォアグラウンド プロセスはどのようにコア ファイルを生成しますか?

実際には、プログラムはフォアグラウンドまたはバックグラウンドで実行できます。フォアグラウンドとバックグラウンドでプログラムを実行するためのコア ファイルを生成する方法には、いくつかの違いがあります。

フォアグラウンド プロセス: 一般的に言えば、ユーザーが ./ を使用してシェルで実行するプログラムはすべてフォアグラウンド プログラムです. フォアグラウンド プログラムは、ユーザーが制御でき、プログラムの実行中にユーザーと対話できます. 実行の優先度はわずかです.フォアグラウンド プログラムの実行中、ユーザーは ctrl+c を使用してプログラムを終了できます。

コア ファイル構成の基本的なコマンド:

ulimit -c   # 查看core文件是否打开
ulimit -a   # 也可以查看core文件是否打开
ulimit -c 0 # 禁止产生core文件
ulimit -c unlimited  #设置core文件大小为不限制大小
ulimit -c 1024   #限制产生的core文件的大小不能超过1024KB

コアファイルのダンプファイルディレクトリと命名規則を設定できます。

/proc/sys/kernel/core_uses_pid を構成することにより、生成されたコア ファイルのファイル名に拡張子として pid を追加するかどうかを制御できます。

フォーマットされたコア ファイルの格納場所またはファイル名は、/proc/sys/kernel/core_pattern を構成することで設定できます。

例えば:

  • コアファイルのファイル名に拡張子 pid を付けるかどうかを設定する

echo "1" > /proc/sys/kernel/core_uses_pid
  • フォーマットされたコア ファイルの保存場所またはファイル名を設定する

echo "/var/core-%e-%p-%t" > /proc/sys/kernel/core_pattern

パラメータ %e、%p、および %t の意味は次のとおりです。

%p - insert pid into filename 添加pid
%u - insert current uid into filename 添加当前uid
%g - insert current gid into filename 添加当前gid
%s - insert signal that caused the coredump into the filename 添加导致产生core的信号
%t - insert UNIX time that the coredump occurred into filename 添加core文件生成时的unix时间
%h - insert hostname where the coredump happened into filename 添加主机名
%e - insert coredumping executable name into filename 添加可执行程序名

実際の操作を開始しましょう。

コア ファイルが開いているかどうかを確認し、コア ファイルのサイズを無制限のサイズに設定します。

4e26aa1979c003236c45ed0850ca7d9a.png

フォーマットされたコア ファイルの保存場所またはファイル名を設定します。

7069c2cd9b5ed11f516e1e194975e2e8.png

テストコード:

#include <stdio.h>

int main(int argc, char **argv)
{
    printf("==================segmentation fault test==================\n");

    int *p = NULL;
    *p = 1234;

    return 0;
}

テスト プログラムを実行して、コア ファイルを生成します。

a69dfc52daece1aabceb82f86019f1a9.png

バックグラウンド プロセスはどのようにコア ファイルを生成しますか?

バックグラウンド プログラムがコア ファイルを生成する方法は、フォアグラウンド プログラムとは異なります。数日前に知ったのですが、私たちのデバイスのプログラムは、起動時に自動的にバックグラウンドで実行されるように設定されており、プログラムがクラッシュすると、コア ファイルが生成されません。後でいくつかの情報を確認したところ、バックグラウンド プログラムがコア ファイルを開く方法が異なることに気付きました。

バックグラウンドプロセス: バックグラウンドプロセスはデーモンプロセスとも呼ばれ, システムのバックグラウンドで実行される特別なプロセスです. 制御端末から独立しており, 定期的に特定のタスクを実行したり, 特定のイベントが処理されるのを待ったりします.バックグラウンド プロセスは、端末によって制御されないことです。通常、ログ管理プロセス rsyslogd、データベース サービス myspld などのシステム サービスとして使用されます。もちろん、一部のユーザー プログラムはバックグラウンドで実行する必要があり、通常は /etc/ini.d/ に配置されます。フォルダーを選択して、スタートアップを自動的に設定します。

ulimit コマンドにはアクションの範囲があります. Ulimit は、現在のシェル プロセスとその派生子プロセスを制限します. したがって、ulimit によるコアサイズの変更は、現在のシェルで開始された子プロセスのみを対象とし、他のシェルで開始されたプロセスには影響しません.

そのため、コアダンプを生成するためのパラメータを設定すると、現在のシェルが直接実行しているプロセスがクラッシュしたときに、コアは正常に生成されますが、バックグラウンドで自己起動するプログラムは生成されません。 booted 自己起動であり、クラッシュを送信するタイミングも予測できないため、この方法ではコアダンプ ファイルを正しくキャプチャできません。

バックグラウンド プロセスのコア ダンプ ファイルを生成するには、次のようなプロセス コードでコア ダンプ機能を有効にする必要があります。

左右にスワイプしてすべてのコードを表示 >>>

// 公众号:嵌入式大杂烩
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/resource.h>

#define SHELL_CMD_CONF_CORE_FILE    "echo /var/core-%e-%p-%t > /proc/sys/kernel/core_pattern"
#define SHELL_CMD_DEL_CORE_FILE     "rm -f /var/core*"

static int enable_core_dump(void)
{
    int ret = -1;
    int resource = RLIMIT_CORE;
    struct rlimit rlim;

    rlim.rlim_cur = 1 ? RLIM_INFINITY : 0;
    rlim.rlim_max = 1 ? RLIM_INFINITY : 0;

    system(SHELL_CMD_DEL_CORE_FILE);

    if (0 != setrlimit(resource, &rlim))
    {
        printf("setrlimit error!\n");
        return -1;
    }
    else
    {
        system(SHELL_CMD_CONF_CORE_FILE);
        printf("SHELL_CMD_CONF_CORE_FILE\n");
        return 0;
    }

    return ret;
}

int main(int argc, char **argv)
{
    enable_core_dump();

    printf("==================segmentation fault test==================\n");

    int *p = NULL;
    *p = 1234;

    return 0;
}

起動時にバックグラウンドでプログラムを実行します。

開発ボードの /etc/init.d/ ディレクトリに新しいファイル S100Test を作成します。

#!/bin/sh
cd /home
./test

プログラムを自動起動するように設定するには、前回の記事「自動起動するプログラムの分析」を参照してください。

デバイスを再起動すると、プログラムがクラッシュしたときにコア ファイルを生成できます。

dbe8f4929d6b49adf3eb30008bba1811.png 780abcb074021f986568d8b955a8a994.png

コアファイルをデバッグしていますか?

コア ファイルを PC に転送し、arm-linux-gnueabihf-gdb を使用してテスト プログラムをデバッグします。

arm-linux-gnueabihf-gdb test
core-file core-test-190-119
17568fa7648ebc3ed829ce344c883b12.png 4581a48816913581867ca8d00b6fe1e2.png

限定的なクラッシュ スタック情報?

このデモは比較的単純で、問題をすばやく特定できます。実際には、プログラムは多くの動的ライブラリに依存することになりますが、このとき、デバッグ時にライブラリの検索パスを設定する必要があります。

これらのライブラリは、ボード上のライブラリに対応している必要があります。ボード上のライブラリを使用することをお勧めします。ボードで使用するライブラリは、PC 上の特定のパスに配置できます。たとえば、/home/LinuxZn/lib のパスに配置します。

gdb に入ると、次のコマンドを入力してライブラリ情報を設定および表示できます。

set solib-search-path /home/LinuxZn/lib
info sharedlibrary
7775dbfd474305b3020af331e712ddd0.png

ライブラリ情報を読み込んだ後でも、意味のあるクラッシュ スタックが表示されないことがあります。

確認することが 2 つあります。

  • アプリケーションがコンパイル時に -g オプションを指定しなかったため、実行可能プログラムのデバッグ情報がありませんでした。

  • ボード上の libc ライブラリのバージョンは、クロス コンパイラで使用される libc ライブラリのバージョンと一致しません。

そうでない場合は、クロス コンパイラで使用される libc ライブラリをボードに更新できます。

参考:

https://baijiahao.baidu.com/s?id=1661025717994426637&wfr=spider&for=pc
https://blog.csdn.net/lhl_blog/article/details/106542754

以上が今回の分かち合いです。

2e8e23c5c479880163c6cb4b2c61ffc7.jpeg

679745bc2c76713bdecacce0036b4409.jpeg

おすすめ

転載: blog.csdn.net/weiqifa0/article/details/129869869