信号

信号概念

信号是软件中断。

产生信号的条件有:

(1)当用户按某些终端键时,引发终端产生的信号。如Ctrl+C引发SIGINT。

(2)硬件异常产生信号:除数为0、无效内存的引用等等。

(3)进程调用kill(2)函数可将信号发送给另一个进程或进程组。

(4)用户可用kill(1)命令将信号发送给其他进程。

(5)当检测到某种软件条件已经发生,并应将其通知有关进程时也产生信号。例如SIGURG、SIGPIPE、SIGALRM。

内核处理信号的方式有:

(1)忽略此信号。

(2)捕捉信号。

(3)执行系统默认动作。


signal函数

#include <signal.h>

void (*signal(int signo, void (*func)(int)))(int);


不可靠的信号

在早起的unix版本(例如v7)中,信号是不可靠的。不可靠指的是信号可能会丢失。

早期版本中的一个问题是在进程每次接到信号对其进行处理时,随即将该信号动作复位为默认值。

例如下面代码:

int my_sigint()

{
    signal(SIGINT, my_sigint);
}

signal(SIGINT, my_sigint);

这段代码的一个问题是:从信号发生之后到在信号处理程序中调用signal函数之前这段时间中有一个时间窗口

在此段时间中,可能发生另一次中断信号。第二个信号会导致执行默认动作,而针对中断信号的默认动作是终止该进程。


早期系统的另一个问题时:在进程不希望某种信号发生时,它不能关闭该信号。

再看下面代码:

int sigint_flag;

int my_sigint()
{
    signal(SIGINT, my_sigint);
    sigint_flag = 1;

}

int main()

{
    signal(SIGINT, my_sigint);
    while (sigint_flag == 0)
    pause();

}

这段代码存在的问题是:从测试sigint_flag之后到调用pause之前这段时间中有一个时间窗口,如果在此段时间中发生信号,则此进程在调用pause时入睡,并且长眠不醒。


可重入函数

函数不可重入的原因有:(a)已知它们使用静态数据结构,(b)它们调用malloc或free,或(c)它们是标准I/O函数。


可靠信号术语和语义

当对信号采取了这种动作时,我们说向进程递送了一个信号。在信号产生和递送之间的时间间隔内,称信号是未决的(pending)。

进程可以选用信号递送阻塞。如果为进程产生了一个选择为阻塞的信号,而且对该信号的动作时系统默认动作或捕捉该信号,则为该进程将此信号保持为未决状态,直到该进程(a)对此信号解除了阻塞,或者(b)将此信号的动作更改为忽略。内核在递送一个原来被阻塞的信号给进程时,才决定对它的处理方式。于是进程在信号递送给它之前仍可改变对该信号的动作。


POSIX.1允许系统递送一个信号一次或多次。如果递送该信号多次,则称对这些信号进行了排队。但是除非支持POSIX.1实时拓展,否则大多数unix并不对信号排队,只递送该信号一次。POSIX.1没有规定多个信号的递送顺序。

每个进程都有一个信号屏蔽字,它规定了当前要阻塞递送到该进程的信号集。对于每种可能的信号,该屏蔽字中都有一位与之对应。


kill和raise函数

kill函数将信号发送给进程或进程组。raise函数则允许进程向自身发送信号。

#include <signal.h>

int kill(pid_t pid, int signo);

int raise(int signo);


alarm和pause函数

使用alarm函数可以设置一个计时器,当计时器超时时,产生SIGALRM信号。

#include <unistd.h>

unsigned int alarm(unsigned int seconds);

每个进程只能有一个闹钟时钟。如果在调用alarm时,以前已为该进程设置过闹钟时钟,而且它还没有超时,则将该闹钟时钟的余留值作为本次alarm函数的返回值。

如果有以前为进程登记的尚未超过的闹钟时钟,而且本次调用的seconds值是0,则取消以前的闹钟时钟,其余留值仍作为alarm函数的返回值。


pasue函数使调用进程挂起直至捕捉到一个信号。

#include <unistd.h>

int pause(void);

只有执行了一个信号处理程序并从其返回时,pause才返回。在这种情况下,pause返回-1,并将error设置为EINTR.


信号集

#include <signal.h>

int sigemptyset(sigset_t *set);

int sigfillset(sigset_t *set);

int sigaddset(sigset_t *set);

int sigdelset(sigset_t *set);

int sigismember(const sigset_t *set, int signo);


sigprocmask函数

调用sigprocmask函数可以检测或更改其信号屏蔽字,或者在一个步骤中同时执行这两个操作。

#include <signal.h>

int sigprocmask(int how, const sigset_t *restrict set, sigset_t *restrict oset);

首先,若oset是非空指针,那么进程的当前信号屏蔽字通过oset返回。

其次,若set是一个非空指针,则参数how指示如何修改当前信号屏蔽字。

在调用sigprocmask后如果有任何未决的、不再阻塞的信号,则在sigprocmask返回前,至少会将其中一个信号递送给该进程。


sigpending函数

sigpending函数返回信号集,其中的各个信号对于调用进程是阻塞的而不能递送,因而也一定是当前未决的。

#include <signal.h>

int sigpending(sigset_t *set);


sigaction函数

sigaction函数的功能是检查或修改与指定信号相关联的处理动作。此函数取代了unix早期版本使用的signal函数。

#include <signal.h>

int sigaction(int signo, const struct sigaction *restrict act, struct sigaction *restrict oact);

其中,参数signo是要检测或修改其具体动作的信号编号。若act指针非空,则要修改其动作。如果oact指针非空,则系统经由oact指针返回该信号的上一个动作。

此函数使用下列结构:

struct sigaction {
    void   (*sa_handler)(int);
    sigset_t sa_mask;
    in       sa_flag;
    void     (*sa_sigaction)(int, siginfo_t *, void *);

};

当更改信号动作时,如果sa_handler字段包含一个信号捕捉函数的地址,则sa_mask字段说明了一个信号集,在调用该信号捕捉函数之前,这一信号集要加到进程的信号屏蔽字中。

仅当从信号捕捉函数返回时再将进程的信号屏蔽字复位为原先值。这样,在调用信号处理程序时就能阻塞某些信号。在信号处理程序被调用时,操作系统建立的新信号屏蔽字包括正被递送的信号。

因此保证了在处理一个给定的信号时,如果这种信号再次发生,那么它会被阻塞到对前一个信号的处理结束为止。

一旦对给定的信号设置了一个动作,那么在调用sigaction显式地改变它之前,该设置就一直有效。

act结构的sa_flags字段指定对信号进行处理的各个选项。

sa_sigaction字段是一个替代的信号处理程序,当在sigaction结构中使用了SA_SIGINFO标志时,使用该信号处理程序。


sigsuspend函数

sigsuspend可以在一个原子操作中先恢复信号屏蔽字,再使进程休眠。

#include <signal.h>

int sigsuspend(const sigset_t *sigmask);

将进程的信号屏蔽字设置为sigmask指向的值。在捕捉到一个信号或发生了一个会终止该进程的信号之前,该进程被挂起。如果捕捉到一个信号而且从该信号处理程序返回,则sigsuspend返回,并且将该进程的信号屏蔽字设置为调用sigsuspend之前的值。


abort函数

#include <stdlib.h>

void abort(void);

此函数将SIGABRT信号发送给调用进程。ISO C要求若捕捉到此信号而且相应信号处理程序返回,abort仍不会返回其调用者。如果捕捉到此信号,则信号处理程序不能返回的唯一方法是它调用exit、_exit、_Exit、longjmp或siglongjmp。

让进程捕捉SIGABRT的意图是:在进程终止之前由其执行所需的清理操作。如果进程并不在信号处理程序中终止自己,POSIX.1声明当信号处理程序返回时,abort终止该进程。


sleep函数

sleep函数的可靠实现

static void sig_alrm(int signo)
{
}
unsigned int sleep(unsigned int nsecs)
{
    struct sigaction newact, oldact;
    sigset_t newmask, oldmask, suspmask;
    unsigned int unslept;

    newact.sa_handler = sig_alrm;
    sigemptyset(&newact.sa_mask);
    newact.sa_flags = 0;
    sigaction(SIGALRM, &newact, &oldact);

    sigemptyset(&newmask);
    sigaddset(&newmask, SIGALRM);
    sigprocmask(SIG_BLOCK, &newmask, &oldmask);

    alarm(nescs);

    suspmask = oldmask;
    sigdelset(&suspmask, SIGALRM);
    sigsuspend(&suspmask);

    unslept = alarm(0);
    sigaction(SIGALRM, &oldact, NULL);

    sigprocmask(SIG_SETMASK, &oldmask, NULL);
    return (unslept);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我! 毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip
综合小区管理系统管理系统按照操作主体分为管理员和用户。管理员的功能包括报修管理、车位管理、车位分配管理、出入管理、字典管理、房屋管理、物业费缴纳管理、公告管理、物业人员投诉管理、我的私信管理、物业人员管理、用户管理、管理员管理。用户的功能包括管理部门以及部门岗位信息,管理招聘信息,培训信息,薪资信息等。该系统采用了Mysql数据库,Java语言,Spring Boot框架等技术进行编程实现。 综合小区管理系统管理系统可以提高综合小区管理系统信息管理问题的解决效率,优化综合小区管理系统信息处理流程,保证综合小区管理系统信息数据的安全,它是一个非常可靠,非常安全的应用程序。 管理员权限操作的功能包括管理公告,管理综合小区管理系统信息,包括出入管理,报修管理,报修管理,物业费缴纳等,可以管理操作员。 出入管理界面,管理员在出入管理界面中可以对界面中显示,可以对招聘信息的招聘状态进行查看,可以添加新的招聘信息等。报修管理界面,管理员在报修管理界面中查看奖罚种类信息,奖罚描述信息,新增奖惩信息等。车位管理界面,管理员在车位管理界面中新增。公告管理界面,管理员在公告管理界面查看公告的工作状态,可以对公告的数据进行导出,可以添加新公告的信息,可以编辑公告信息,删除公告信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值