Tank Shell游戏编写之六: 后台运行及信号的发送和接受

一个游戏肯定是多个进程(线程)进行的, 例如我们在控制自己的坦克的同时, 敌方坦克肯定需要自主随机的移动,这就需要将其放到后台中。 

将一个进程放到后台很简单,执行脚本时,只需在指令末尾加 & 符号即可。 

[root@NCTEST ~]# ping baidu.com > /dev/null  &
[1] 16313
[root@NCTEST ~]# ping baidu.com > /dev/null  &
[2] 16316
[root@NCTEST ~]# ps aux | grep ping      
root     16313  0.0  0.0 109576  1032 pts/2    S    13:28   0:00 ping baidu.com     # 可以看到有两个运行在后台的ping进程
root     16316  0.0  0.0 109576  1020 pts/2    S    13:28   0:00 ping baidu.com
root     16320  0.0  0.0 103252   848 pts/2    R+   13:28   0:00 grep ping
[root@NCTEST ~]# 
[root@NCTEST ~]# jobs     #查看当前进程下的运行在后台的子进程
[1]-  Running                 ping baidu.com > /dev/null &
[2]+  Running                 ping baidu.com > /dev/null &
[root@NCTEST ~]# kill %1  #结束后台子进程的方式
[root@NCTEST ~]# kill %2
[1]-  Terminated              ping baidu.com > /dev/null
[2]+  Terminated              ping baidu.com > /dev/null
[root@NCTEST ~]# jobs
[root@NCTEST ~]# 

对于此游戏而言,关于后台运行的知识点以上足以, 更多相关的内容请参考链接:https://www.ibm.com/developerworks/cn/linux/l-cn-nohup/

(或参考收录:http://www.cnblogs.com/gipagod/p/9121255.html)

一个进程放入后台后, 我们是无法直接控制的, 例如敌方坦克被击中后,如何通知其终止移动,并显示爆炸图案? 这就需要信号的发送和接收了,简单点说,放到后台的进程会一直在监听某个信号,一旦有信号发送过来就会执行制定好的动作,这样就方便被前台进程控制了。

 一般现在的Linux中都会有64种信号,如下, 但前32中一般都已由默认动作,例如我们通常用的CTRL+C组合键终止进程时其实发送的是SIGINT(2)信号等,因此不建议自定义使用,只有在我们需要对已存在信号动作进行修改时才会用到,例如忽略CTRL+C操作等等。

[root@NCTEST ~]# kill -l 
 1) SIGHUP     2) SIGINT     3) SIGQUIT     4) SIGILL     5) SIGTRAP
 6) SIGABRT     7) SIGBUS     8) SIGFPE     9) SIGKILL    10) SIGUSR1
11) SIGSEGV    12) SIGUSR2    13) SIGPIPE    14) SIGALRM    15) SIGTERM
16) SIGSTKFLT    17) SIGCHLD    18) SIGCONT    19) SIGSTOP    20) SIGTSTP
21) SIGTTIN    22) SIGTTOU    23) SIGURG    24) SIGXCPU    25) SIGXFSZ
26) SIGVTALRM    27) SIGPROF    28) SIGWINCH    29) SIGIO    30) SIGPWR
31) SIGSYS    34) SIGRTMIN    35) SIGRTMIN+1    36) SIGRTMIN+2    37) SIGRTMIN+3
38) SIGRTMIN+4    39) SIGRTMIN+5    40) SIGRTMIN+6    41) SIGRTMIN+7    42) SIGRTMIN+8
43) SIGRTMIN+9    44) SIGRTMIN+10    45) SIGRTMIN+11    46) SIGRTMIN+12    47) SIGRTMIN+13
48) SIGRTMIN+14    49) SIGRTMIN+15    50) SIGRTMAX-14    51) SIGRTMAX-13    52) SIGRTMAX-12
53) SIGRTMAX-11    54) SIGRTMAX-10    55) SIGRTMAX-9    56) SIGRTMAX-8    57) SIGRTMAX-7
58) SIGRTMAX-6    59) SIGRTMAX-5    60) SIGRTMAX-4    61) SIGRTMAX-3    62) SIGRTMAX-2
63) SIGRTMAX-1    64) SIGRTMAX    

下面介绍一下它的使用,首先是接受方, 接收方使用trap指令来监听信号,语法如下:

trap 'commands' signal-list   # 监听到信号后执行commands
trap '' signal-list           # 忽略信号,不执行任何操作,主要用来屏蔽某些已有默认动作的信号,例如SIGINT等
trap  signal-list             # 采取信号默认动作(用处不大)

对于发送发,我们使用kill指令来实现:

kill  -signal  ProcessID

kill的参数中需要一个ProcessID,也就是我们放到后台运行进程的ID,这个ID我们可以通过变量 $! 来获取, 它的作用是存储最近一次放到后台运行的进程的ID:

[root@GipagodHost ~]# ping gipagod.com >/dev/null &
[1] 7903
[root@GipagodHost ~]# echo $!
7903
[root@GipagodHost ~]# ping gipagod.com >/dev/null &
[2] 7904
[root@GipagodHost ~]# echo $!
7904
[root@GipagodHost ~]# ps aux | grep ping
root      7903  0.0  0.1 111636  1036 pts/1    S    14:34   0:00 ping gipagod.com
root      7904  0.0  0.1 111636  1032 pts/1    S    14:34   0:00 ping gipagod.com
root      7906  0.0  0.0 105368   884 pts/1    S+   14:34   0:00 grep ping

我们需要在每次后台运行一个进程后,立刻用一个变量存储器, 用一段测试代码来加深以上两个知识点的理解:

f_print_signal(){
    echo "I have received the signal, number is $1"
}

f_bg_func(){
    local v_stop=0   # 定义个局部变量
    trap "f_print_signal 40" 40 # 监听了三个信号
    trap "f_print_signal 50" 50
    trap "f_print_signal 45; v_stop=1" 45  # 打印信号数字的同时将v_stop置1,终止下面的while循环,即此结束了此后台进程的运行
    
    while [[ $v_stop -eq 0 ]]  # 当接收到45信号后,v_stop被置1, 不在符合循环条件,终止循环
    do
        sleep 1
    done
    echo GOODBYE
}

f_bg_func &
v_bg_pid=$!  # 存储后台进程的Process ID

while :
do
    read  v_input
    kill -$v_input $v_bg_pid   # 向后台进程发送信号
done

展示:

[root@GipagodHost ~]# sh Tank6_1.sh 
40
I have received the signal, number is 40
50
I have received the signal, number is 50
50
I have received the signal, number is 50
40
I have received the signal, number is 40
45
I have received the signal, number is 45
GOODBYE
40
Tank6_1.sh: line 25: kill: (14171) - No such process    # 45信号已经终止了后台进程的运行

猜你喜欢

转载自www.cnblogs.com/gipagod/p/9120793.html
今日推荐