21

私は、プログラムがファイル記述子を引数として (通常は exec 呼び出しの親から) 受け取り、ファイルから読み取り、ファイル記述子に書き込む割り当てに取り組んでいました。私のテストでは、プログラムが機能することに気付きました。ファイル記述子として 0、1、または 2 を使用してもエラーは発生しません。標準入力に書き込んで画面に表示できることを除いて、それは私にとって理にかなっています。

これについての説明はありますか?stdin/stdoutには何らかの保護があるといつも思っていました.fprintfをstdinに、またはfgetsをstdoutから実行することはできません。

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
    char message[20];
    read(STDOUT_FILENO, message, 20);
    write(STDIN_FILENO, message, 20);

    return 0;
}
4

6 に答える 6

19

読み取り専用とマークされたファイルに書き込もうとしたり、その逆を試みたりするとwriteread-1 が返されて失敗します。この特定のケースでは、stdin と stdout は実際には同じファイルです。本質的に、プログラムが実行される前に (リダイレクトを行わない場合)、シェルは次のようになります。

  if(!fork()){
       <close all fd's>
       int fd = open("/dev/tty1", O_RDWR);
       dup(fd);
       dup(fd);
       execvp("name", argv);
  }

したがって、stdin、out、および err はすべて同じファイル記述子の複製であり、読み取りおよび書き込み用に開かれています。

于 2011-10-06T20:41:42.177 に答える
3
read(STDIN_FILENO, message, 20); 
write(STDOUT_FILENO, message, 20);

動作するはずです。注 - stdout は stdin とは別の場所になる場合があります (コマンドライン上であっても)。別のプロセスからの出力を stdin としてプロセスにフィードしたり、stdin/stdout をファイルに配置したりできます。

fprintf/fgets にはバッファがあるため、システム コールの数が減ります。

于 2011-09-12T06:05:22.387 に答える
1

UNIXでプログラムを実行する場合

myapp < input > output

/ proc / {pid} / fd / 1を開いてそこから読み取り、/ proc / {pid} / fd / 0を開いて書き込み、たとえばにコピーoutputすることができinputます。(これを行うためのより簡単な方法があるかもしれませんが、私はそれが機能することを知っています)

気をつければ、わかりにくいことなら何でもできます。;)

于 2011-09-12T07:35:03.360 に答える
1

最良の推測 - stdin は入力の送信元である端末を指し、stdout は出力の送信先である端末を指します。どちらも同じ場所を指しているので、交換可能ですか (この場合)?

于 2011-09-12T05:58:47.593 に答える
1

ファイル記述子 0、1、および 2 がすべて読み取りと書き込みの両方で開かれている可能性が非常に高く (実際、それらはすべて、同じ基本的な「開いているファイルの説明」を参照している)、その場合、あなたがしていることはうまくいきます。しかし、私の知る限り、保証はありませんので、うまくいかない可能性もあります。私はPOSIXのどこかで、プログラムがシェルによって呼び出されたときにstderrが端末に接続されている場合、それは読み書き可能であるはずであると指定していると信じていますが、すぐに参照を見つけることができません..

一般に、パスワードを読み取る端末を探していて、stdin が (tty ではなく) リダイレクトされている場合を除き、stdout または stderr から読み取らないことをお勧めします。また、stdin には絶対に書き込まないことをお勧めします。これは危険であり、ユーザーが書き込みを予期していなかったファイルを上書きしてしまう可能性があります。

于 2011-09-12T13:10:34.447 に答える