2016-12-08 15 views
1

次のコードを参照してください。プロセスに関連付けられたターミナル名をCで確実に見つける方法は?

#include <stdio.h> 
#include <unistd.h> 

int main() 
{ 
    printf("ttyname(0): %s\n", ttyname(0)); 
    printf("ttyname(1): %s\n", ttyname(1)); 
    printf("ttyname(2): %s\n", ttyname(2)); 
    printf("ctermid(NULL): %s\n", ctermid(NULL)); 

    /* Sleep for sometime so that we can manually run the ps command to 
    * see the terminal associated with the process. */ 
    sleep(10); 

    return 0; 
} 

これをコンパイルして実行します。

$ gcc foo.c 
$ ./a.out 
ttyname(0): /dev/pts/3 
ttyname(1): /dev/pts/3 
ttyname(2): /dev/pts/3 
ctermid(NULL): /dev/tty 

別の端末では、psコマンドを実行して端末名を確認します。

$ ps -ef | grep a.out | grep -v grep 
coder  1498 1473 0 19:19 pts/3 00:00:00 ./a.out 

これまでのところすべてが良いです。私のプログラムは端末を正しく表示します。

しかし、stdin、stdout、およびstderrが次のようにリダイレクトされると、私のプログラムは端末情報を出力できません。別の端末で

$ ./a.out </dev/null> foo.txt 2> /dev/null 

、私はpsを実行し、私は確かに/dev/pts/3は、彼が処理withtに関連していることがわかります。

$ ps -ef | grep a.out | grep -v grep 
coder  1536 1473 0 19:22 pts/3 00:00:00 ./a.out 

しかし./a.out終了した後、私はfoo.txtで、その出力を確認し、私はこの情報が取り込まれ表示されません。

$ cat foo.txt 
ttyname(0): (null) 
ttyname(1): (null) 
ttyname(2): (null) 
ctermid(NULL): /dev/tty 

標準入力時にttyname()はどんな意味のある情報を提供していないので、stdoutとstderrがリダイレクトされるとctermid() always returns /dev/tty以来、私は確実にプロセスに対応する端末を決定するために何ができるのでしょうか?標準のUnixまたはLinuxシステムで動作するソリューションを理想的に探していますが、それが不可能な場合は、Linux固有のソリューションも問題ありません。

+0

stdin/out/errを/ dev/nullにリダイレクトした後、それがまだ端末に接続されていると思いますか? – KevinDTimm

+0

@KevinDTimmまだ端末に取り付けられているとは思わない。それは私の質問ではありません。私は、stdin、stdout、stderrがリダイレクトされたときに端末に接続されていないことを完全に認識しています。しかしプロセスはまだ端末に関連しています( 'ps'出力から見ることができます)。プロセスがまだ端末に関連付けられている場合、Cコードを使用してプロセス内からその端末名を取得するにはどうすればよいですか?これは私の質問です。 –

+0

Gotcha - checking – KevinDTimm

答えて

1

標準入力、標準出力だけでなく、標準エラー出力が

をリダイレクトされたときに私のプログラムは、まあ、はい、指定した上で開かれている端末装置の(a)の名前を返しますttyname()出力に端末情報を失敗しますファイル記述子。ファイルディスクリプタが端末を参照していない場合、そのようなデバイスはありません。 ttyname()は、この場合にはNULLを返し、指定されたファイル記述子が端末に関連付けられていないファイルを返すように文書化されています。

プロセスに関連付けられた端末を確実に判断するにはどうすればよいですか?

まず、プロセスに関連する「ターミナル」が何であるかを判断する必要があります。原理的には、ファイル記述子0,1、および2、さらに多くの場合、すべてが異なる端末デバイスに接続される可能性があります。 なしがプロセスの端末を制御している可能性があります。これはおそらくあなたが実際に探しているものだと思います。

プロセスは、それがあれば、ctermid()によって返された文字列で指定されたデバイスをオープンするべきで、その標準ストリームのリダイレクトの独立したアクセス(それが1を持っていると仮定)その制御端末にしたい場合。 glibc ctermid()は常に"/dev/tty"を返します。デバイスは通常、アクセスプロセスの制御端末の同義語として機能するため、無関係です。

ただし、制御端末を含むデバイスののプロセスに依存しない名前を判別するための移植性の高い、信頼できる方法はありません。カーネルは、本質的に、ファイルシステムに存在し、ユーザ空間プロセスの便宜のために提供されるデバイス名の点では機能しません。さらに、任意の所与の装置は、原則として、それを参照する複数のファイル名を有することができる。

Linuxの場合、には、プロセスの制御端末のメジャーおよびマイナーデバイス番号/proc/self/statから取得できます。原則として、あなたは、これらの番号を解凍することができますし、どちらか

  • は、一致するデバイスファイルを見つけるために/devファイルシステムをスキャンし、おそらく/proc/devices、または

  • からの助けを借りて、対応する従来のファイル名に変換しますその名前を報告する。

前者は安価ですが、やや投機的です。後者は、成功すると、存在するデバイスファイルの名前を返し、確実に目的のデバイスを参照します。

https://unix.stackexchange.com/questions/151812/get-device-node-by-major-minor-numbers-pairの推奨事項をチェックすることもできますが、少なくとも一部は私のシステムでは動作しません。

+0

"*プロセスに関連付けられた端末*"は[ps(1)]マニュアルページの逐語的な引用です](https://linux.die.net/man/1/ps)。そこでは、 '/ proc/*/stat'によって報告されているように、制御端末を指しています。 –

関連する問題