2009年3月19日星期四

[转]UNIX进程(Process)及信号(signal)

UNIX系统程序设计-7-编程语言-电脑网络-搜狐社区: "第七章:UNIX进程(Process)及信号(signal)

在进程执行过程中,如果出现什么事件(event),系统将会给进程一个信号。进程可以在得到这个信号后做些适当的处理。
还是与以前一样,咱们先来个小程序吧。

/* slot.c */
#include <stdio.h>
#include <signal.h>

int x[3];
long kin;

int kekka();
int main( int argc , char *argv[] )
{
srand( getpid() ); /* 设定随机数的种子数 */
signal( SIGKILL , kekka ); /* 当Ctrl+C按下时,执行kekka函数 */
kin = atoi( argv[1] ); /* 取得赌注数目 */

printf('press Ctrl+C to stop maching !\n');
while(1)
{
x[0]=rand()%10;
x[1]=rand()%10;
x[2]=rand()%10;
printf('%d %d %d\n',x[0],x[1],x[2]);
fflush( stdout );
}
return 0;
}
int kekka()
{
if( x[0]==x[1] && x[1]==x[2] )
printf('Great , you won %d \n' , kin*3000);
else
printf('You lost %d\n',kin);
exit(0); /* 游戏结束。退出程序 */
}

执行方法:
%./slot 100

执行后。画面上会出现一排排的数字。当你按下Ctrl+C的时候,程序得到信号,跳转至kekka()函数入,判断随机数。然后退出程序。
这里有这样一个新函数。是我们在UNIX程序设计中时常用得到的。

#include <signal.h>
int ( *signal( int sig , void (*func()) ))();
返回值: 成功时:进程中断地址
错误时:SIG_ERR

这个函数挺不好懂呵。解释解释。它的意思是,当收到SIG这个信号时,跳转至func()这个函数处继续执行。
int sig这个参数其实好办。下面我们会给出一个表。将其所有的参数一并列出。这是在头文件中#define的,代表各种不同的信号。
void ( * func() )
这个参数是一个函数指针。意思是在SIG信号被传给进程后,所要执行的部分。
此外,func()这个参数还可以为如下值:
SIG_DEL 系统的默认动作
SIG_IGN 忽略这个信号。

signal作用只有一次,当一个信号发生,触发signal动作的之后,signal就不起作用了。比方说,在上例中,如果你把所有的exit(0)全去掉(不退出程序),程序会进入无限循环中。你按一次Ctrl+C,signal执行一次,显示出结果。然后继续循环,生成随机数,输出。你再按Ctrl+C,signal就不好使了。
如果需要重复使用signal()函数,可以考虑在signal调用的动作函数中再加一个signal,比方说在上例的程序中再加一个 signal( SIGKILL , kekka );

加了signal这个函数后,整个程序如果没收到信号,则正常执行。否则跳转至signal中指定的func()函数处继续。
当然,我们不可能,也没有必要去为每一个信号指定一个动作。当未指定动作的信号发生的时候,系统会执行默认的动作。比方说我们知道:当Ctrl+C按下的时候,正常默认的动作是结束程序。但是,Ctrl+C按下时,发生的信号是SIGKILL,如果你为SIGKILL这个信号指定了一个动作的话,系统将去执行你指定的这个动作,而不管原来默认的了。
打个比方让大家更容易懂一些:
比方说:你在睡午觉。突然来了一个美女(帅哥)(Ctrl+C)让你陪她/他去逛街购物共进晚餐……(此处删去若干字),你正常的默认的动作是马上起来陪她出去玩(程序中止)。但是你妈说不许去,你妈说你得在家擦窗户,你只好留在家擦窗户(signal()指定的动作)。擦完窗户之后你可以选择陪美女去逛街(默认动作,Ctrl+C的埸合是退出程序,即上例程序中的exit(0)),可以选择继续睡觉(回到原来中断的地方继续执行,上例程序中如果没有exit(0),便会回到中断处继续执行)。
(大哥。打个比方嘛。干嘛拿臭鸡蛋砸我……)

signal种类非常多,在此不一一列出。

使用这个函数,你可以防止用户按下Ctrl+C结束程序。还可以做很多其它的事——只有你想不到的,没有C做不到的。

注意:根据UNIX系统的不同,signal的定义是不一样的。比方说,有的老式UNIX工作站上SIGINT是按下del键后发生的信号,而有些机型上刚是按下Ctrl+Z发生的。在使用时要注意。"

1 条评论:

PENGYCHAN 说...
此评论已被作者删除。