next up previous contents
Next: 演習課題 Up: Stream Previous: StreamTokenizer

プロセスからのストリーム

Java では、UNIX/C のプログラムを、ある意味では特徴付ける、 fork() , exec() , wait() ... といった、プロセスを生成し、プログラムを実行する 働きをもった一群の関数群を、ほとんど用いません。 なぜなら、Java では、cpuにとって重たい処理であるforkに代わって、軽いThreadが、 言語仕様そのものに組み込まれる形で、全面的に使われるからです。 appletの中では、セキュリティの関係で、自由に他のプログラムを実行することは、 許されません。所が、Javaアプリケーションでは、こうしたことが可能になります。 ただ、この時、他のプログラムは、Thread ではなく、forkで生成されたサブ・プロセス の中で、実行されることになります。今回は、forkで生成されたサブ・プロセス からの入出力をどう扱うかという問題を取り扱ってみましょう。

次のプログラムは、引数に与えたプログラムを実行してその出力を表示するものです。 簡単な実行例を示します。

sparc04$ java Exec who                        <---- who コマンドを実行
pid 5357 status 0
Received sigchild for 5357 exit=0
nakaga-h   pts/0         6月 25 19:08   (lxb4)
maruyama   pts/2         6月 25 20:35   (ews1)
sparc04$ java Exec ls -l *.txt                <---- ls -l *.txt を実行
pid 5328 status 0
Received sigchild for 5328 exit=0
-rw-r--r--   1 maruyama sysadmin   16681  6月 24日  23:46 sw4.txt
sparc04$ java Exec ypcat hosts | grep cronos  <---- ホストcronos の検索
202.11.101.9    cronos

このサンプルの中心部分は、次の行です。

        proc = Runtime.getRuntime().exec(cmd);

ただ、この行のことは、ドキュメントを見て考えればわかります。 実際には、このサンプルで一番苦労したのは、次の2点です。

第一。サブ・プロセスとJavaとの同期がうまく取れません。 そのために、available()というメソッドを使っています。Streamに データが無いときには、sleepで、ちょっと待つことにしています。 第二。先の行で生成されたprocessオブジェクトから、getInputStream()を 使って、InputStreamを獲得するのですが、InputStreamのままでは、 サブ・プロセスの終了が感知できません

        in = new DataInputStream(proc.getInputStream());

というように、DataInputStreamにすると、なぜかわかりませんが、 この問題は解決します。

****************************
** Exec.java 
****************************

     1	import java.lang.* ;
     2	import java.io.* ;
     3	
     4	class Exec {
     5	   Process proc = null ;
     6	   DataInputStream in = null;
     7	
     8	   Exec( String arg[] ){
     9	     try{
    10	       String cmd[] = new String[3] ;
    11	       StringBuffer args = new StringBuffer();
    12	    
    13	        if (arg.length == 0) return ;
    14	        for (int i = 0; i < arg.length; i++) {
    15	            args.append(' ').append(arg[i]);
    16	        }
    17	        cmd[0] = "/usr/bin/ksh";
    18	        cmd[1] = "-c";
    19	        cmd[2] = args.toString();
    20	    
    21	        proc = Runtime.getRuntime().exec(cmd);
    22	        in = new DataInputStream(proc.getInputStream());
    23	    
    24	     } catch ( Exception ex){
    25	        System.err.println("exec: "+ex);
    26	     }
    27	   } 
    28	
    29	   public static void main(String argv[]){
    30	     try {
    31	      Exec d = new Exec(argv);
    32	      String line = null ;
    33	
    34	      int size = 0 ;
    35	      while( true  ){
    36	        if ( d.in.available() > 0 ){
    37	          while( (line = d.in.readLine()) != null ){
    38	                System.out.println(line);
    39	          } 
    40	          break ;
    41	        } else {
    42	          Thread.sleep(200);
    43	        } 
    44	   
    45	      }
    46	     } catch ( Exception ex){
    47	        System.err.println("main:"+ex);
    48	     }
    49	   }
    50	}


maruyama@wakhok.ac.jp