【Chapter 8*プログラミングまとめ*】gdbトラッキングスタック情報と再確認標準IOとファイルIOの基本的な違い


前に書く
レッスン後の練習問題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を使用します.