歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> SHELL編程 >> shell實現Unix進程間信息交換的幾種方法

shell實現Unix進程間信息交換的幾種方法

日期:2017/2/27 17:43:50   编辑:SHELL編程

  本文將介紹在SCO OpenServer5.0.5系統中使用shell語言來實現進程間信息交換的幾種方法: 
  
  使用命名管道實現進程間信息交換 
  
  使用kill命令和trap語句實現進程間信息交換 
  
  使用點命令“.”實現進程間信息交換 
  
  使用export語句實現父進程對子進程的信息傳遞 
  
  一、使用命名管道
  命名管道是一種先進先出(FIFO)的數據結構,它允許兩個進程通過管道聯接實現信息交換。在Unix系統中,命名管道是一種特殊類型的文件,因此可以對命名管道進行讀寫操作;當然,同樣也會有讀寫和執行等權限的限制。 
  
  通過下面的命令可以創建一個命名管道:
  /etc/mknod pipe_name p 
  
  其中“pipe_name”是要創建的命名管道的名字,參數p 必須出現在命名管道名字之後。 
  
  命名管道文件被創建後,一些進程就可以不斷地將信息寫入命名管道文件裡,而另一些進程也可以不斷地從命名管道文件中讀取信息。對命名管道文件的讀寫操作是可以同時進行的。下面的例子顯示命名管道的工作過程。 
  
  進程A、B、C中運行的程序只是一條簡單的echo命令,它們不斷地把信息寫入到命名管道文件/tmp/pipe1中。與此同時,程序中的“read msg” 命令不斷地從命名管道文件/tmp/pipe1中讀取這些信息,從而實現這些進程間的信息交換。 
  
  程序執行時,首先創建命名管道文件,此時程序處於等待狀態,直到A、B、C進程中某一個進程往命名管道中寫入信息時,程序才繼續往下執行。使用rm命令可以刪除命名管道文件從而清除已設置的命名管道。 
  
  下面是一個用於記錄考勤的例子: 
  
  在主機上運行的程序/tmp/text產生命名管道/tmp/pipe1,並不斷地從命名管道中讀取信息送屏幕上顯示。 
  
  /tmp/text程序:
  if [ ! -p /tmp/pipe1 ]
  then
   /etc/mknode /tmp/pipe1 p
  fi
  while :
  do
   read msg
   if [ “$msg" = “" ]
   then
  continue
   else
  echo “$msg"
   fi
  done < /tmp/pipe1
  
  在終端上運行的是雇員簽到程序/tmp/text1。每個雇員在任何一台終端上鍵入自己的名字或代碼,程序/tmp/text1將把這個名字連同當時的簽到時間送入命名管道。 
  
  /tmp/text1程序:
  tty=‘who am I | awk ‘{print $2}’’
    while :
    do
     echo “Enter your name: \c" > /dev/$tty
     read name
     today=‘date’
     echo “$name\t$today"
     done > /tmp/pipe1
  
  當雇員從終端上輸入自己的姓名後,運行/tmp/text程序的主機將顯示類似下面的結果: 
  
  wang Thu Jan 28 09:29:26 BTJ 1999
  he Thu Jan 28 09:29:26 BTJ 1999
  cheng Thu Jan 28 09:30:26 BTJ 1999
  zhang Thu Jan 28 09:31:26 BTJ 1999
  
  二、使用kill命令和trap語句
  在Unix系統中,當檢測到一個異常的內部狀態,或者硬件及外部設備發出請求,或者執行某些指令時,將會向系統中的進程發出信號報告事件產生。當進程捕獲到這些信號後,系統便轉去執行預先設定的默認程序,完成指定的動作;這些預先設定的默認程序稱之為信號的系統陷阱。 
  
  在shell中,使用trap語句為信號設置新的陷阱。當shell 捕獲到一個信號時(信號11除外,因為shell本身要利用這個信號進行內存分配),它將這個信號傳遞給所有當前正在執行的程序(父程序和子程序),並分別執行父程序和子程序中已設置的信號陷阱。一旦陷阱程序執行結束,便返回中斷點,繼續執行原來的程序流程。 
  
  trap語句的基本格式:
  trap command_list signal_list
  
  command_list: 由一個或多個命令(或命令組)構成的命令列表。當命令列表中含有多個命令時要用單引號或雙引號括起來,並且各命令間要用分號隔開。 
  
  signal_list:由一個或多個信號值構成的信號列表,各信號值間要用空格分開。 
  
  在一個shell程序(父程序)中重新設置信號的陷阱並不改變被這個程序所調用的子程序中同名信號的陷阱。同樣,在子程序中設置的信號陷阱也不影響父程序中同名信號的陷阱。 
  
  shell在讀取trap語句時,要掃描一次命令列表,以便設置陷阱。在捕獲信號後,shell再次掃描命令列表,執行已設置好的陷阱程序(命令或命令組)。因此,如果命令列表中含有變量置換或命令置換表達式,shell在第一次掃描命令列表時就會用當前的變量值或命令結果置換這些表達式,使得在捕獲到信號而去執行陷阱程序時,陷阱程序已經不是原來設置的陷阱程序了。為了避免這種情況發生,使用單引號而不是使用雙引號把trap語句中含有變量置換或命令置換表達式的命令列表括起來;因為單引號可以消除所有字符的特殊含義,這樣避免了shell在第一次掃描時執行任何置換或替代操作,直到命令列表被執行時才進行置換或替代。 
  
  向一個程序或進程傳遞信號方法很多,比如在程序執行時按下Ctrl+c鍵或Del鍵,將向程序傳遞一個SIGINT信號,執行該信號的系統陷阱將終止程序執行。使用kill命令傳遞信號是shell語言編程中最為常用的方法。 
  
  kill命令的基本格式是:
  kill [ - signal ] PID 
  
  通常kill命令用來終止一個進程。但如果使用了帶有短劃線“-”的信號作為參數時,kill命令就發送該信號給PID指示的一個或多個進程,而不是終止進程。當trap語句捕獲到這個信號後便執行設定的信號陷阱程序,實現進程間的相互通訊。 
  
  下面的例子顯示了程序master和slave1、slave2間如何利用信號機制實現相互通訊的。首先在後台運行程序slave1和slave2,然後運行程序master。在文件/tmp/pro_list中記錄了這三個程序的進程號。 
  
  程序slave1首先設置信號15的陷阱,然後把自己的當前進程寫入文件/tmp/pro_list;在獲得master進程號後,進入循環狀態。當接收到master發出的信號15時,執行陷阱程序,顯示相關信息後,向master發出信號15。 
  
  程序slave2執行情況與slave1相似。 
  
  程序master也是首先設置信號15的陷阱,然後把自己的當前進程寫入文件/tmp/pro_list。在取得所有slave程序進程號後,向這些slave程序發出信號15,然後進入循環等待。當接收到slave1或slave2發出的信號15時,執行陷阱程序,顯示相關信息,殺死所有slave進程,清空文件/tmp/pro_list,然後退出。 
  
  程序/tmp/slave1:
  slave() {
   echo “slave1 has received sighal from master"
   echo “Request master to kill slave1 process"
   kill -15 $master_pid
  }
  trap slave 15
  echo “slave1_pid $$" >> /tmp/pro_list
  sleep 1
  while :
  do
   master_pid=‘awk ’$1 ~/master/
    {print $2}‘/tmp/pro_list’
   if [ “$master_pid" != “" ]
   then break
   fi
  done
  while :
  do
   sleep 1
  done
  
    程序/tmp/slave2:
  slave() {
   echo “slave2 has received sighal from master"
   echo “Request master to kill slave2 process"
   kill -15 $master_pid
  }
  trap slave 15
  echo “slave2_pid $$" >> /tmp/pro_list
  sleep 1
  while :
  do
   master_pid=‘awk ’$1 ~/master/ 
    {print $2}‘/tmp/pro_list’
   if [ “$master_pid" != “" ]
   then break
   fi
  done
  while :
  do
   sleep 1
  done
  
    程序/tmp/master:
  kill_slave() {
     echo “Master has received signals
        from slave processes"
     echo “End all slave processes"
     kill -9 $slave_list
  >/tmp/pro_list
    exit 0
  }
  trap kill_slave 15
  echo “master_pid $$" >> /tmp/pro_list
  sleep 1
  slave_list=‘awk ’$1 ~/slave/ 
     {print $2}‘/tmp/pro_list’
  echo “Current slave processes are:"
  echo “$slave_list"
  kill -15 $slave_list
  while :
  do
   sleep 1
  done
  
    執行程序:
  $ cd /tmp
  $ ./slave1&
  15638
  $ ./slave2&
  16831
  $ ./master
  Current slave processes are:
  15638
  16831
  slave1 has received signal 15 from master
  Request master to kill slave1 process
  slave2 has received signal 15 from master
  Request master to kill slave2 process
  Master has received signals from slave processes
  End all slave processes
  15638 Killed
  16831 Killed
  $
  
  三、使用點命令“.”
  “.”點命令是shell的一個內部命令,它從指定的shell 文件中讀入所有命令語句並在當前進程中執行。 因此當多個shell進程(父子進程或無關進程均可)共享一組變量值時,就可以
Copyright © Linux教程網 All Rights Reserved