【Chapter 8*プログラミングまとめ*】gdbトラッキングスタック情報と再確認標準IOとファイルIOの基本的な違い
5122 ワード
前に書く
レッスン後の練習問題8-1で、vforkを使用してサブプロセスを作成し、サブプロセスを使用します.exit(0)終了時にはクリーンアッププログラムは実行されず、exit(0)に変更すると終了処理プログラムと標準IOクリーンアッププログラムが実行されます.これは、標準IOのクリーンアッププロセスがどのように実現されるかに関連しています.
1、バッファを洗い流し、バッファデータを出力し、exit(0)の実行結果と同じ2、標準IOストリームを閉じる.サブプロセスはexitの前に親プロセスと同じアドレス空間を共有するため、親プロセス標準IOは閉じられ、出力されない.
ほとんどのUnixシステムexit(0)実装では、プロセスが終了すると、カーネルが開いているすべてのファイル記述子を閉じるため、バッファのみを洗浄します.exit(0)は何度も一挙に行動しません.
私の機械では確かにそうであることを検証し、バッファだけを洗浄し、標準IOを閉じることはありません.
親プロセスが出力されないようにするには、どうすればいいですか?簡単で、exit(0)の前に標準出力を手動でオフにします.
一、標準IOを閉じてセグメントエラーが発生
添付コード:
実行:
はい、間違いは私たちの古い友达です.今度はどうやって彼を取ったか見てください.
二、GDBスタック情報の表示
最近、bt、すなわちbacktraceの略語、遡及の意味を学び、プログラム内のスタックフレームを直接表示することができます.
2.1 core dump機能を開く
coreは何ですか.linuxが提供するcore dumpメカニズムに基づいて、プログラムがクラッシュすると、メモリイメージがディスク、すなわちcoreファイルに転送されます.実行可能ファイルにcoreファイルをデバッグするシンボルテーブル情報があり、gdb+実行可能ファイル+coreを使用してプログラムにエラーが発生したときのスタック状況を復元します.
理論の基礎はここまでですが、coreファイルはどのように生成されますか?ほとんどのシステムはcore dump機能をオフにし、ulimit-aコマンドで表示します.
最初のcore file sizeサイズは0で、この機能がオフであることを示します.どうやって開けますか?簡単です.core file sizeサイズを変更すればいいです.一般にulimit-c umlimitedが用いられる.
設定に成功したら、ulimit-aを表示します.
設定が成功したことを示します.
注意:ulimit-c unlimitedは、現在のプロセスのリソース状況を変更します.プロセスが閉じている場合、他のプロセスがcoreファイルを使用するには、再設定する必要があります.一労永逸の方法はshellの起動スクリプト/etc/bashrcで設定します.記事を参照:https://blog.csdn.net/star_xiong/article/details/43529637
2.2 coreファイルの生成
core dumpを開いた後、gdbを使用すると、実行時にセグメントエラーが発生し、coreファイルをついでに生成できます.
OK、成功しました~現在のパスを見て、coreファイルが多く見つかりました.8-1は実行可能ファイル
2.3トレーススタック
参照先:https://blog.csdn.net/learnhard/article/details/4879834 gdb実行可能ファイル名coreを使用すると、デバッグ状態に入ることができます.
最後から2行目にエラーが表示され、標準IOで発生したエラーをより明確に見るには、returnを続け、btを使用します.
完璧で、全部で2つのスタックフレームで、1つはmain関数で、1つはfcloseで、一般的なライブラリ関数は何の欠点もありません.残りはmainの呼び出しにエラーが発生し、8-1.cの23行目に直接位置決めします.
俺はバカだ!
三、ファイルIOと標準IO
明らかに、fcloseは標準出力ストリームを閉じているが、パラメータはファイル記述子であり、ファイル記述子とストリームが混在しているようだ.
1、ファイル記述子
ファイルIOはファイル記述子、int型に対応し、各プロセスには対応する3つのファイル記述子がある.
定義、範囲0~OPEN_MAX-1間、OPEN_MAXは最大オープンファイル数を表し、一般的に64である.
ファイルIOの操作にはopen,read,write,lseek,close関数があり,ユーザプロセスにバッファを持たない
2、フロー(ファイルポインタ)
標準IO対のストリーム、つまりファイルポインタ、FILE*タイプで、各プロセスには3つの事前定義されたストリームがあります.
で定義され、ユーザー・プロセスではバッファ付きであり、フル・バッファ、ロー・バッファ、バッファなし
標準IOの操作はfopen、fclose、getc/fgetc、gets/fgets、puts/fputs、fread、fwrite、ftell、fseek、printfなど
ストリームに関連付けられたファイル記述子を取得するにはfilenoを使用します.
レッスン後の練習問題8-1で、vforkを使用してサブプロセスを作成し、サブプロセスを使用します.exit(0)終了時にはクリーンアッププログラムは実行されず、exit(0)に変更すると終了処理プログラムと標準IOクリーンアッププログラムが実行されます.これは、標準IOのクリーンアッププロセスがどのように実現されるかに関連しています.
1、バッファを洗い流し、バッファデータを出力し、exit(0)の実行結果と同じ2、標準IOストリームを閉じる.サブプロセスはexitの前に親プロセスと同じアドレス空間を共有するため、親プロセス標準IOは閉じられ、出力されない.
ほとんどのUnixシステムexit(0)実装では、プロセスが終了すると、カーネルが開いているすべてのファイル記述子を閉じるため、バッファのみを洗浄します.exit(0)は何度も一挙に行動しません.
私の機械では確かにそうであることを検証し、バッファだけを洗浄し、標準IOを閉じることはありません.
親プロセスが出力されないようにするには、どうすればいいですか?簡単で、exit(0)の前に標準出力を手動でオフにします.
一、標準IOを閉じてセグメントエラーが発生
添付コード:
// vfork
2
3 #include"apue.h"
4 #include
5
6 int globvar = 6;
7
8 int main(void)
9 {
10 int var;
11 pid_t pid;
12
13 var = 88;
14 printf("before vfork
");
15
16 if((pid=vfork())<0){
17 err_sys(" !
");
18 }
19 else if(pid==0){//
20 globvar++;
21 var++;
22
23 if(fclose(STDOUT_FILENO)!=0){
24 err_sys(" !
");
25 }
26 exit(0);
27 }
28 //
29 printf("pid=%ld,glob=%d,var=%d
",pid,globvar,var);
30
31 return 0;
32 }
実行:
fairy@ubuntu:~/Unix_Code/Chapter8$ ./8-1
before vfork
Segmentation fault
はい、間違いは私たちの古い友达です.今度はどうやって彼を取ったか見てください.
二、GDBスタック情報の表示
最近、bt、すなわちbacktraceの略語、遡及の意味を学び、プログラム内のスタックフレームを直接表示することができます.
2.1 core dump機能を開く
coreは何ですか.linuxが提供するcore dumpメカニズムに基づいて、プログラムがクラッシュすると、メモリイメージがディスク、すなわちcoreファイルに転送されます.実行可能ファイルにcoreファイルをデバッグするシンボルテーブル情報があり、gdb+実行可能ファイル+coreを使用してプログラムにエラーが発生したときのスタック状況を復元します.
理論の基礎はここまでですが、coreファイルはどのように生成されますか?ほとんどのシステムはcore dump機能をオフにし、ulimit-aコマンドで表示します.
fairy@ubuntu:~/Unix_Code/Chapter8$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
...
最初のcore file sizeサイズは0で、この機能がオフであることを示します.どうやって開けますか?簡単です.core file sizeサイズを変更すればいいです.一般にulimit-c umlimitedが用いられる.
ulimit -c 0 core
ulimit -c 100 core 100k
ulimit -c unlimited core
設定に成功したら、ulimit-aを表示します.
fairy@ubuntu:~/Unix_Code/Chapter8$ ulimit -a
core file size (blocks, -c) unlimited
data seg size (kbytes, -d) unlimited
...
設定が成功したことを示します.
注意:ulimit-c unlimitedは、現在のプロセスのリソース状況を変更します.プロセスが閉じている場合、他のプロセスがcoreファイルを使用するには、再設定する必要があります.一労永逸の方法はshellの起動スクリプト/etc/bashrcで設定します.記事を参照:https://blog.csdn.net/star_xiong/article/details/43529637
2.2 coreファイルの生成
core dumpを開いた後、gdbを使用すると、実行時にセグメントエラーが発生し、coreファイルをついでに生成できます.
fairy@ubuntu:~/Unix_Code/Chapter8$ gcc -g 8-1.c -o 8-1
fairy@ubuntu:~/Unix_Code/Chapter8$ ./8-1
before vfork
Segmentation fault
OK、成功しました~現在のパスを見て、coreファイルが多く見つかりました.8-1は実行可能ファイル
fairy@ubuntu:~/Unix_Code/Chapter8$ ls
8-1 8-1.c core
2.3トレーススタック
参照先:https://blog.csdn.net/learnhard/article/details/4879834 gdb実行可能ファイル名coreを使用すると、デバッグ状態に入ることができます.
fairy@ubuntu:~/Unix_Code/Chapter8$ gdb 8-1 core
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
....
[New LWP 3858]
[New LWP 3857]
Core was generated by `./8-1'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 _IO_new_fclose (fp=0x1) at iofclose.c:53
53 iofclose.c: No such file or directory.
---Type to continue, or q to quit---
最後から2行目にエラーが表示され、標準IOで発生したエラーをより明確に見るには、returnを続け、btを使用します.
---Type to continue, or q to quit---return
[Current thread is 1 (LWP 3858)]
(gdb) bt
#0 _IO_new_fclose (fp=0x1) at iofclose.c:53
#1 0x000000000040108b in main () at 8-1.c:23
完璧で、全部で2つのスタックフレームで、1つはmain関数で、1つはfcloseで、一般的なライブラリ関数は何の欠点もありません.残りはmainの呼び出しにエラーが発生し、8-1.cの23行目に直接位置決めします.
23 if(fclose(STDOUT_FILENO)!=0){
24 err_sys(" !
");
25 }
俺はバカだ!
三、ファイルIOと標準IO
明らかに、fcloseは標準出力ストリームを閉じているが、パラメータはファイル記述子であり、ファイル記述子とストリームが混在しているようだ.
1、ファイル記述子
ファイルIOはファイル記述子、int型に対応し、各プロセスには対応する3つのファイル記述子がある.
STDIN_FILENO 0
STDOUT_FILENO 1
STDERR_FILENO 2
定義、範囲0~OPEN_MAX-1間、OPEN_MAXは最大オープンファイル数を表し、一般的に64である.
ファイルIOの操作にはopen,read,write,lseek,close関数があり,ユーザプロセスにバッファを持たない
2、フロー(ファイルポインタ)
標準IO対のストリーム、つまりファイルポインタ、FILE*タイプで、各プロセスには3つの事前定義されたストリームがあります.
stdin
stdout
stderr
で定義され、ユーザー・プロセスではバッファ付きであり、フル・バッファ、ロー・バッファ、バッファなし
標準IOの操作はfopen、fclose、getc/fgetc、gets/fgets、puts/fputs、fread、fwrite、ftell、fseek、printfなど
ストリームに関連付けられたファイル記述子を取得するにはfilenoを使用します.