質問
これが私のコードです:
#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を閉じました。
この理由は何ですか?
解決
ここで実際に起こっているのはそれです printf
の出力はバッファリングされており、すぐにFD 1に送信されません。代わりに、バッファーは、から戻った後、Cランタイムによって記述子1をファイルするようにフラッシュされます main
. 。もし、あんたが close(newfd)
, 、出口時の実行時によって実行される自動フラッシュを効果的に妨害しました。
明示的に fflush(stdout)
あなたの前に close(newfd)
, 、出力がファイルに表示されるはずです。
ちなみに、特定のファイル記述子をリダイレクトする場合は、代替システム呼び出しがあります dup2(oldfd, 1)
これにより、FD 1が重複しています oldfd
, 、以前に開いていた場合はFD 1を閉じます。
他のヒント
ファイル記述子を直接使用している場合は、 避ける 次のようなc stdio関数を使用します printf
. 。基礎となるファイル記述子をStdioレイヤーの下から変更することは、危険に満ちているようです。
あなたがあなたを変えるなら printf
以下:
write(newfd, "\nStack Overflow", 15);
それならあなたはおそらくあなたが期待する出力を取得するでしょう(あなたが close(newfd)
か否か)。
close
, write
, open
それは システム呼び出し 主に内部で行われます Linuxカーネル;したがって、アプリケーションの観点から、それらは初等の原子操作です。
printf
と fprintf
これらの(およびその他)syscallsの上に構築された標準的なライブラリ関数です。
前 出口-ing(例:からの戻り main
)、標準のライブラリと環境(特にコードのコード crt*.o
あなたを呼ぶ main
)登録された関数を実行しています atexit;および標準のI/Oは(ソート)の呼び出しを登録しています fflush 終了時に。だから stdout
は fflush
- 出口時にエド。もし、あんたが close
主にその記述子、そのフラッシュは失敗し、何もしません。
混ぜるべきではないと思います stdio
そして生 write
-S同じ書き込み記述子へ。使用を検討してください fdopen
また freopen