web-dev-qa-db-ja.com

stdinへの書き込みとstdoutからの読み取り(UNIX / LINUX / Cプログラミング)

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

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

#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;
}
16
Tim

読み取り専用またはその逆とマークされたファイルに書き込もうとすると、writeおよびreadが-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はすべて同じファイル記述子の複製であり、読み取りおよび書き込み用に開かれます。

14
Dave
read(STDIN_FILENO, message, 20); 
write(STDOUT_FILENO, message, 20);

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

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

2
Ed Heal

予想どおり-stdinは入力の起点であるターミナルを指し、stdoutは出力の起点であるターミナルを指します。それらは両方とも同じ場所を指しているので、それらは交換可能です(この場合)?

1
Avery3R

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

myapp < input > output

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

あなたがそれに心を向けるならば、あなたは明白に混乱するどんなやり方でもすることができます。 ;)

1
Peter Lawrey

Stdinにメッセージを書き込みたい場合は、現在のttyを開き、writeシステムコールを呼び出して、このfdにメッセージを書き込むことができます。

string console_cmd = "hello";
string tty = ttyname(STDIN_FILENO);
int fd = open(tty.c_str(), O_WRONLY);
write(fd, console_cmd.c_str(), console_cmd.size());

同様に、標準出力から読み取ります。

0
vinllen

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

一般に、パスワードを読み取る端末を探していて、stdinが(ttyではなく)リダイレクトされていない限り、stdoutまたはstderrから読み取ることはお勧めしません。そして、私はstdinに書き込まないことをお勧めします-これは危険であり、ユーザーが書き込まれることを予期していないファイルを破壊する可能性があります!