当前位置 : 主页 > 网络编程 > 其它编程 >

[APUE]信号

来源:互联网 收集:自由互联 发布时间:2023-07-02
信号是软件中断是软件层次上对硬件中断的一种模拟原理上一个进程收到一个信号与cpu收到一个中断请求是一样的。信号提供了一种处理异步事件的方法。为什么说 信号是软件中断是软
信号是软件中断是软件层次上对硬件中断的一种模拟原理上一个进程收到一个信号与cpu收到一个中断请求是一样的。信号提供了一种处理异步事件的方法。为什么说

信号是软件中断是软件层次上对硬件中断的一种模拟原理上一个进程收到一个信号与cpu收到一个中断请求是一样的。信号提供了一种处理异步事件的方法。

为什么说信号提供了一种处理异步事件的方法因为一个进程不必通过任何操作来等待信号的到达事实上进程也不知道信号到底是什么时候到达。

1、同步和异步

当一个进程A存在一个必须执行的操作点同时该操作点与另一个进程B的某个操作点存在因果时序关系则A相对B为同步。反之为异步。

1A相对B同步未必B相对A同步。2AB两个进程之间必须存在操作点之间的因果关系才叫同步。如果说两个进程抢打印机则不叫同步。虽然可能存在某个操作点上的相互影响。虽然他们之间可能出现阻塞。但和同步异步没联系。3A相对B同步则一定存在一个严格按照请求等待接受的时序过程进行。这种工作在软件设计时是显式存在的即你在代码中可以看到。4同步和异步都是相对的。在不同的尺度下可能产生变化。

2、信号的概念

每个信号都有一个名字这些名字都以SIG开头。

在头文件中这些信号都被定义成正整数。不存在编号为0的信号kill函数对信号编号为0有特殊的应用。

当某个信号出现时可以要求内核按照下列三种方式之一进行处理信号的处理

1忽略信号SIG_IGN。有两种信号SIGKILL和SIGSTOP不能被忽略它们向超级用户提供了使进程终止或停止的可靠方法。

2捕捉信号程序员为某信号注册处理函数。为做到这一点要通知内核在某种信号发生时调用一个用户函数。不能捕捉SIGKILL和SIGSTOP信号。

3执行系统默认动作(SIG_DFL)。针对大多数信号的系统默认动作是终止进程。

3、函数signal

#includevoid (*signal(int signo,void (*func)(int)))(int);//signo信号名func信号处理函数。当进程收到signo信号就会异步调用func函数//返回值若成功返回以前的信号处理配置若出错返回SIG_ERR

从signal函数的限制不改变信号的处理方式就不能确定信号的当前处理方式。

进程创建当一个进程调用fork其子进程继承父进程的信号处理方式。

4、可重入函数

可重入函数主要用于多任务环境中一个可重入的函数简单来说就是可以被中断的函数也就是说可以在这个函数执行的任何时刻中断它转入OS调度下去执行另外一段代码而返回控制时不会出现什么错误而不可重入的函数由于使用了一些系统资源比如全局变量区中断向量表等所以它如果被中断的话可能会出现问题这类函数是不能运行在多任务环境下的。

满足下列条件的函数多数是不可重入的 1) 函数体内使用了静态的数据结构 2) 函数体内调用了malloc()或者free()函数 3) 函数体内调用了标准I/O函数。 若在信号处理程序中调用一个非可重入函数则其结果是不可预知的。 5、函数killraisealarmpause kill函数将信号发送给进程或进程组raise函数则允许进程向自身发送信号。

int kill(pid_t pid,int signo);int raise(int sugno);//两个函数返回值若成功返回0若出错返回-1

调用raise(sig)等价于调用kill(getpid(), sig)。

kill的pid参数有四种可能

pid > 0: 将该信号发送给进程ID为pid的进程

pid 0: 将该信号发送给与发送进程属于同一进程组的所有进程而且发送进程具有向这些进程发送信号的权限。

pid <0: 将该信号发送给其进程组ID等于pid的绝对值而且发送进程具有向其发送信号的权限。

pid -1:将该信号发送给发送进程有权限向他们发送信号的系统上的所有进程。

使用alarm函数可以设置一个计时器在将来某个指定的时间该计时器会超时。当计时器超时时产生SIGALRM信号。如果不忽略或不捕捉此信号则其默认动作是终止调用该alarm函数的进程。每个进程只能有一个闹钟时间。

unsigned int alarm(unsigned int seconds);//返回值0或者以前设置的时钟的余留秒数

pause函数使调用进程挂起直到捕捉到一个信号。只有执行了一个信号处理程序并从其返回时pause才返回。在这种情况下pause返回-1并将errno设置为EINTR。

int pause(void);//返回值-1erron设置为EINTR

6、信号集

需要一个类型来表示信号的集合以便某些函数运用这种数据结构。但是信号的数目一般比整形的位数大当然只要可能大在设计的时候就必须考虑所以系统定义了sigset_t类型来表示信号集以下是处理信号集的一些函数

intsigemptyset(sigset_t *set); //初始化信号集清除所有信号intsigfillset(sigset_t *set); //初始化信号集使其包含所有信号 intsigaddset(sigset_t *set, int signum); //增加信号signo intsigdelset(sigset_t *set, int signum); //清除信号signo //4个函数返回值成功返回0出错返回-1intsigismember(const sigset_t *set, int signum); //判定信号signo是否属于信号集set //返回值若真返回1假返回0出错返回-1

 

转:https://www.cnblogs.com/kona/p/4650320.html

网友评论