本文将介绍在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进程(父子进程或无关进程均可)共享一组变量值时,就可以将这些变量赋值语句定义到一个shell文件里,并在需要这些变量值的程序中使用点语句来引用这个shell文件,从而实现变量值共享(对这些变量值的修改仅涉及到这个shell文件)。但要注意的是,这个shell文件不能包括含有位置参数的语句,即不能接受$1、$2等命令行参数。 
下面是一个在超市中发布每日商品价格的示范程序片段。发布每日商品价格统一由程序/tmp/jiage来执行,它为每种商品价格赋值,并把相应的赋值语句写入文件/tmp/jiagebiao中。在各终端上运行的收款程序/tmp/shoukuan将读入文件 /tmp/jiagebiao中所有赋值语句并在当前进程中执行,从而获取在程序/tmp/jiage中设定的价格。 
价格设定程序/tmp/jiage: 
echo “Enter the price of chicken, 
  duck and fish: \c" 
read chicken duck fish 
exec 3>/tmp/jiagebiao 
echo “chicken_price=$chicken" >&3 
echo “duck_price=$duck" >&3 
echo “fish_price=$fish" >&3 
执行/tmp/jiage程序后,文件/tmp/jiagebiao中将有如下内容: 
chicken_price=5.4 
duck_price=2.5 
fish_price=4.2 
收款程序/tmp/shoukuan: 
. /tmp/jiagebiao 
count=0 
while : 
do 
echo “Enter the trade name and 
 quantities or input q to sum: \c" 
read trade$count quantity$count 
eval a=\$trade$count 
if [ “$a" = “q" ] 
then if [ $count -gt 0 ] 
then 
count=‘expr $count - 1’ 
fi 
break 
fi 
count=‘expr $count + 1 ’ 
done 
echo “\n‘date’" 
echo “trade name\tquantity\tsum" 
while [ “$count" -ge 0 ] 
do 
 eval trade=“\${trade$count}" 
 eval trade_price=“${trade}_price" 
 eval danjia=\${$trade_price} 
 eval quantity=“\${quantity$count}" 
 sum=‘echo “scale=2; $danjia 
 *$quantity"|bc’ 
 echo “$trade\t\t$quantity\t\t$sum" 
 count=‘expr $count - 1 ’ 
done 
在终端上执行程序/tmp/shoukuan将有如下显示: 
Enter the trade name and quantities 
or input q to sum: chicken 2 
Enter the trade name and quantities 
or input q to sum: fish 3 
Enter the trade name and quantities 
or input q to sum: duck 4 
Enter the trade name and quantities 
 or input q to sum: q 
Thu Jan 28 09:29:29 BJT 1999: 
duck 4 10 
fish 3 12.6 
chicken 2 10.8 
四、使用export语句

通常shell变量是局部变量,无论是通过赋值操作还是通过命令赋值,其变量值只在当前进程中有效。但是经过export语句说明的shell变量就成为一个全局性变量,其变量名和变量值可以传递给子进程及其后代进程。在子进程中可以修改这个变量的值,但并不影响这个变量在父进程中的取值。 
下面的例子中,父进程(/tmp/text)将赋值后的变量 pro_name传递给子进程(/tmp/text_child),在子进程中对变量pro_name所赋的新值并不影响父进程中该变量的值。 
/tmp/text程序: 
pro_name=“PARENT" 
echo “The variable pro_name is 
$pro_name in parent process" 
export pro_name 
/tmp/text_child 
echo “The variable pro_name is 
$pro_name after retund to parent process" 
/tmp/text_child程序: 
echo“The variable pro_name ($pro_name) is 
 transmited to child process" 
pro_name=“CHILD" 
echo “To change the variable pro_name to 
  $pro_name in child process" 
执行程序/tmp/text: 
$ /tmp/text 
The variable pro_name is PARENT in parent process 
The variable pro_name (PARENT) 
is transmited to child process 
To change the variable pro_name to CHILD in child process 
The variable pro_name is PARENT after retund to parent process 

Shell实现Unix进程间信息交换的几种方法的更多相关文章

  1. linux进程后台运行的几种方法 - nohup/setsid/&

    linux进程后台运行的几种方法 - nohup/setsid/& [转载]   我们经常会碰到这样的问题,用 telnet/ssh 登录了远程的 Linux 服务器,运行了一些耗时较长的任务 ...

  2. 去除inline-block元素间间距的N种方法-zhangxinxu

    张鑫旭原文:点这里进入原文 另外附上大漠老师的如何解决inline-block元素的空白间距地址!!! 去除inline-block元素间间距的N种方法: 一.现象描述 真正意义上的inline-bl ...

  3. vue-learning:31 - component - 组件间通信的6种方法

    vue组件间通信的6种方法 父子组件通信 prop / $emit 嵌套组件 $attrs / $liteners 后代组件通信 provide / inject 组件实例引用 $root / $pa ...

  4. UNIX 进程间通讯(IPC)概念(Posix,System V IPC)

     IPC(Inter-Process Communication,进程间通讯)可以有三种信息共享方式(随文件系统,随内核,随共享内存).(当然这里虽然说是进程间通讯,其实也是可以和线程相通的). 相对 ...

  5. Linux进程间通讯的几种方式的特点和优缺点,和适用场合

    http://blog.csdn.net/jeffcjl/article/details/5523569 由于不同的进程运行在各自不同的内存空间中.一方对于变量的修改另一方是无法感知的.因此.进程之间 ...

  6. linux进程间通讯的几种方式的特点和优缺点

    # 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用.进程的亲缘关系通常是指父子进程关系.# 有名管道 (named pipe) : 有名管道也是 ...

  7. zabbix3.0.4使用shell脚本和zabbix自带模板两种方法添加对指定进程和端口的监控

    zabbix3.0.4添加对进程的监控: 方法一:通过自定义命令进行监控 主要思路: 通过 ps -ef|grep sdk-push-1.0.0.jar |grep -v grep|wc -l 这个命 ...

  8. linux进程后台运行的几种方法

    转载:http://hi.baidu.com/ntuxmzvdpzbnuxq/item/79131b93f606a348f0421562 我 们经常会碰到这样的问题,用 telnet/ssh 登录了远 ...

  9. Linux 的shell 字符串截取很有用。有八种方法。

    一 Linux 的字符串截取很有用.有八种方法. 假设有变量 var=http://www.linuxidc.com/123.htm 1  # 号截取,删除左边字符,保留右边字符. echo ${va ...

随机推荐

  1. HDU 2457 DNA repair(AC自动机+DP)题解

    题意:给你几个模式串,问你主串最少改几个字符能够使主串不包含模式串 思路:从昨天中午开始研究,研究到现在终于看懂了.既然是多模匹配,我们是要用到AC自动机的.我们把主串放到AC自动机上跑,并保证不出现 ...

  2. postman中如何使用OAuth

    https://learning.getpostman.com/docs/postman/sending_api_requests/authorization/ Authorization The a ...

  3. 自动生成makefile

    原文  http://www.laruence.com/2009/11/18/1154.html 作为Linux下的程序开发人员,大家一定都遇到过Makefile,用make命令来编译自己写的程序确实 ...

  4. R中的sample函数

    今天介绍一些运算函数,它们的使用很简单,没有什么难度,但是也会用的着. 在医学统计学或者流行病学里的现场调查.样本选择经常会提到一个词:随机抽样.随机抽样是为了保证各比较组之间均衡性的一个很重要的方法 ...

  5. python 获取昨天今天明天日期

    import datetime today = datetime.date.today() yesterday = today - datetime.timedelta(days = ) tomorr ...

  6. MySQL —— 基本查询方法

    MySQL —— 简单查询与按条件查询 在MySQL中从数据表中查询数据的基本语句时select语句.  select语句基本语法格式:      select 查询内容       from 表名  ...

  7. 排序算法总结(基于Java实现)

    前言 下面会讲到一些简单的排序算法(均基于java实现),并给出实现和效率分析. 使用的基类如下: 注意:抽象函数应为public的,我就不改代码了 public abstract class Sor ...

  8. c#在winform中用DataGridView实现分页效果

    public partial class Form11 : Form { public Form11() { InitializeComponent(); } private int Inum = 1 ...

  9. HDU 4751 Divide Groups (2-SAT)

    题意 给定一个有向图,问是否能够分成两个有向完全图. 思路 裸的2-sat--我们设一个完全图为0,另一个完全图为1,对于一个点对(u, v),如果u.v不是双向连通则它们两个不能在一组,即u和v至少 ...

  10. js数字进制转换

    其他进制转十进制: 使用 parseInt()函数,parseInt解析一个字符串参数,并返回一个指定基数的整数 ,用法如下: parseInt(string, radix); 以二进制为例,用法如下 ...