質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

シェル

シェル(shell)はUnix や Linux 系のOSで使用されるコマンドインタプリタを指します。

Q&A

解決済

4回答

11765閲覧

標準出力というのはプログラム毎にあるのでしょうか?

jimyo

総合スコア243

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

シェル

シェル(shell)はUnix や Linux 系のOSで使用されるコマンドインタプリタを指します。

1グッド

6クリップ

投稿2016/06/09 03:08

あるプログラム中でprintf("teratail\n");のように書いたとします。
このプログラムのコンパイル後のファイル名をprogramとし、そのプログラムがあるディレクトリまでcdコマンドで移動し、./programで実行しました。

このとき画面(ターミナル、端末、コマンドプロンプト)には「teratail」と表示されると思います。

次にこのプログラムをサービスやデーモンなどのように起動させておくとします。
このとき、端末を開いてる時にそのプログラムがprintfするタイミングになっても画面に文字列teratailが現れたりすることはありませんよね?

わたしの印象では直接実行、つまり./programのように端末から能動的に実行したもの以外printfなどの出力は見られないと思うのですが、プログラムが実行したprintf("teratail\n");の出力はどこにいくのでしょうか?

「標準入力・標準出力」などは1つだけしかないと思っていたのですが、プログラムごとに作られる(?)のでしょうか?

わかりにくい説明ですみません。
不明な点があったら指摘していただけるとありがたいです。

また、 もしこの出力を外部からキャッチする方法があるなら教えていただきたいです。

DrqYuto👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

標準出力というのは、プロセスごとに存在します。
具体的に言うと、プロセスごとに存在するファイルディスクリプタの配列の添え字1のデータのことです。
各ファイルディスクリプタは、(1)なんらかのファイルに繋がっている(オープンされている)、(2)どこにも繋がっていない(クローズされている)のどちらかです。

ファイルディスクリプタは、プロセスが生成された時に、親プロセスからコピーされます。

端末のbashから起動したプロセスであれば、bashの標準入力(添え字0)、標準出力(添え字1)、標準エラー出力(添え字2)は、みんなその端末に繋がっており、特に指定していない限り、添え字3以降のファイルディスクリプタはクローズされた状態です。

bashからプログラム起動時に標準出力をリダイレクトした場合は、子プロセス生成後に標準出力をリダイレクト先に繋ぎ直した後で、プログラムに制御を移します。

もちろん、bash自体の標準出力がリダイレクトされている場合は、そのbashから起動されたプログラムもデフォルトでは親のbashと同じ所にリダイレクトされます。親のコピーなので。

デーモンの場合は、デーモンプログラムの初期化処理の中で標準入力等を/dev/nullに繋ぎ直すのが普通です。

ファイルディスクリプタは、プロセスの中のローカルなデータであり、外からコマンドでどうにかすることは出来ないので、他の方の回答にあるように、デバッガでそのプロセス自体を書き換えるしかないです。

投稿2016/06/09 08:10

otn

総合スコア84423

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mao999

2016/06/09 14:51

標準入出力等はプロセス毎に存在するんですね。その仕組み、勉強になりました。
guest

0

「標準入力・標準出力」などは1つだけしかないと思っていたのですが、プログラムごとに作られる(?)のでしょうか?

はい。プログラムごとに作られます。

各プログラムは各々、標準出力を持っています。
デフォルトではディスプレイが出力先として「リダイレクト」されます。

たとえば

./program > log.txt

と実行すると、標準出力の出力内容をlog.txtへ出力することができます。
標準出力をlog.txtのファイルストリームへリダイレクトしたわけです。

「リダイレクト(リダイレクション)」や「パイプライン」なんかを調べてみると
理解が深まると思いますよ。

また、 もしこの出力を外部からキャッチする方法があるなら教えていただきたいです。

単純に結果を取得するなら

$output = shell_exec('./program');

でとれます。

投稿2016/06/09 04:42

wakuwaku

総合スコア386

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

そういえばどうなんだ、と少々気になったので調べてみました。
Linux上でシェルが実行される仕組みを,体系的に理解しよう (bash 中級者への道)- 主に言語とシステム開発に関して
サービス(デーモン)の設定
Linuxでプロセスのデーモン化 - Qiita

tty(ターミナル/実端末)はプログラム実行時に作られるのではなく、
Linuxブート時に指定数のみ生成されます。
古いシステムでは、/etc/inittabの情報をもとに作られます。
pts(仮想端末)はxterm等が起動時に生成されます。

ーーー(下記は間違い。wakuwakuさん、otnさんの回答を要参照)ーーー
プロセスはどの端末から実行されたかという情報を持ちます。
標準入力・標準出力・標準エラー出力は、端末毎に存在します。
プロセスはその端末から入力・出力します。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

デーモン化すると、端末は切り離されます。
ソースコードを見たわけではありませんが、切り離される際に恐らく/dev/nullにつなぎ替えているのではないでしょうか。

端末を任意の端末に繋ぎ直す事も可能です。
コンソールから切れたプロセスを標準出力につなげなおす - 絶品ゆどうふのタレ
既存プロセスの標準出力と標準エラーを奪う - Qiita
gdbのpオプションで、該当プロセスにアタッチして制御していますね。

ただ、デーモン化するとsyslog関数等によってsyslog等のログに出力する事が殆どかと思います。
syslogへ出力されたものを標準出力に出力する方法もあるかと思いますが、
そこまで調べきれてはいません。

投稿2016/06/09 04:15

編集2016/06/09 14:57
mao999

総合スコア111

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

デーモンの場合は、標準入出力はデーモンとして常駐する際に閉じてしまいますので、他プロセスへの影響はありません。

投稿2016/06/09 04:12

maisumakun

総合スコア145121

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問