3

これが私のコードです:

#include<stdio.h>
#include<stdlib.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<fcntl.h>
#include<unistd.h>
#include<errno.h>
int main(int argc,char *argv[])
{
  int oldfd;
  int newfd;
  if(argc!=2)
  {
    printf("Usgae : %s file_name\n",argv[0]);
    exit(0);
  }
 oldfd=open(argv[1],O_RDWR|O_APPEND,S_IRWXU); // Opening the file in Read/Write mode
 if (-1 == oldfd)
 {
  perror("Error opening file");
  exit(0);
 }
 close(1); // closing stdout 
 newfd=dup(oldfd); //Now this newfd holds the value 1 
 close(oldfd); //closing the oldfd
 printf("\nStack Overflow"); //Now this printf will print content into the file as stdout closed already
 close(newfd);// closing newfd 
 return 0;
}

私が実際にやろうとしているのは、write() システム コールの代わりに printf() を使用して、「スタック オーバーフロー」をファイルに出力することです。

コンテンツをファイルに出力していません。しかし、私が観察したことの1つは、コードを削除すると:

 close(newfd)

期待どおりに内容をファイルに出力しています。しかし、私はその理由を理解できません。内容を印刷してから、newfd を閉じるだけです。

これの理由は何ですか?

4

3 に答える 3

5

ここで実際に起こっていることは、printfの出力がバッファリングされ、すぐに fd 1 に送信されないことです。代わりに、バッファは から戻った後、C ランタイムによってファイル記述子 1 にフラッシュされますmain。の場合はclose(newfd)、終了時にランタイムによって実行される自動フラッシュを効果的に妨害しています。

fflush(stdout)の前に明示的にした場合close(newfd)、出力はファイルに表示されます。

ところで、特定のファイル記述子をリダイレクトしたい場合は、dup2(oldfd, 1)fd 1 を の複製にしoldfd、以前に開いていた場合は fd 1 を閉じる別のシステム コールがあります。

于 2011-12-06T06:44:39.940 に答える
0

ファイル記述子を直接使用している場合は、printf. 基になるファイル記述子を stdio レイヤーの下から変更することは、危険を伴うようです。

次のように変更した場合printf:

write(newfd, "\nStack Overflow", 15);

そうすれば、おそらく期待どおりの出力が得られます(自分であるかどうかに関係close(newfd)なく)。

于 2011-12-06T06:46:11.613 に答える
0

close, write,openは、主にLinux カーネル内で行われるシステム コールです。したがって、アプリケーションの観点からは、それらは基本的なアトミック操作です。

printfおよびfprintfこれらの (およびその他の) システムコールの上に構築された標準ライブラリ関数です。

exitする前(たとえば から戻るmain)、標準ライブラリと環境 (特に をcrt*.o呼び出すコード) は、 atexitmainによって登録された関数を実行しています。そして、標準 I/O は (一種の)終了時にfflushへの呼び出しを登録しています。したがって、終了時に-ed です。メインの記述子の場合、そのフラッシュは失敗し、何もしません。stdoutfflushclose

stdioraw write-s と同じ書き込み記述子を混在させるべきではないと思います。またはの使用を検討してくださいfdopenfreopen

于 2011-12-06T06:49:43.190 に答える