APUE第十章笔记

第十章

10.1 引言

  • 信号是软件中断

10.2 信号概念

  • SIGABRT是夭折信号,当进程调用abort函数时产生这种信号。
  • SIGALRM是闹钟信号,当由alarm函数设置的时间已经超过后产生此信号
  • 在头文件<signal.h>中,这些信号都被定义为正整数(信号编号)。没有一个信号其编号为0。
  • SIGKILL和SIGSTOP信号却决不能被忽略。
  • 信号表以及各个信号说明参见APUE第251-256页。

10.3 函数signal

#include <signal.h>
void (*signal(int signo, void (*func)(int)))(int);
//返回:成功则为以前的信号处理配置,若出错则为SIG_ERR
  • signo参数是表10-1中的信号名。func的值是:(a)常数SIG_IGN,或(b)常数SIG_DFL,或©当接到此信号后要调用的函数的地址。如果指定SIG_IGN,则向内核表示忽略此信号。(记住有两个信号SIGKILL和SIGSTOP不能忽略。)如果指定SIG_DFL,则表示接到此信号后的动作是系统默认动作(见表10-1中的最后1列)。当指定函数地址时,我们称此为捕捉此信号。我们称此函数为信号处理程序(signalhandler)或信号捕捉函数(signal-catchingfunction)。
  • kill命令和kill函数只是将一个信号送给一个进程或进程组。
  • exec函数将原先设置为要捕捉的信号都更改为默认动作
  • 当一个进程调用fork时,其子进程继承父进程的信号处理方式。
  • shell自动将后台进程中对中断和退出信号的处理方式设置为忽略。

10.5 中断的系统调用

  • 如果在进程执行一个低速系统调用而阻塞期间捕捉到一个信号,则该系统调用就被中断不再继续执行。该系统调用返回出错,其errno设置为EINTR。
  • 低速系统调用是可能会使进程永远阻塞的一类系统调用。
  • 被中断的系统调用的自动再起动。自动再起动的系统调用包括:ioctl、read、readv、write、writev、wait和waitpid。
  • 请注意,本地磁盘不是慢速设备;

10.6 可重入函数

  • 不可重入函数原因:它们使用静态数据结构,它们调用malloc或free,它们是标准I/O函数
  • 在信号处理程序中保证调用安全的函数。这些函数是可重入的并被称为是异步信号安全的,除了可重入以外,在信号处理操作期间,它会阻塞任何会引起不一致的信号发送。
  • 当在信号处理程序中调用可重入函数时,应当在其前保存,在其后恢复errno。

10.7 SIGCLD语意

  • 如果进程特地指定对该信号的配置为SIG_IGN,则调用进程的子进程将不产生僵死进程。
  • 如果将SIGCLD的配置设置为捕捉,则内核立即检查是否有子进程准备好被等待,如果是这样,则调用SIGCLD处理程序。
  • 在linux中,#define SIGCLD SIGCHLD

10.8 可靠信号术语和语义

  • 向一个进程递送了一个信号。在信号产生(generation)和递送(delivery)之间的时间间隔内,称信号未决(pending)。
  • 如果为进程产生了一个选择为阻塞的信号,而且对该信号的动作是系统默认动作或捕捉该信号,则为该进程将此信号保持为未决状态,直到该进程对此信号解除了阻塞,或者将对此信号的动作更改为忽略。
  • 每个进程都有一个信号屏蔽字,它规定了当前要阻塞递送到该进程的信号集。

10.9 函数kill和raise

  1. kill函数将信号发送给进程或进程组。raise函数则允许进程向自身发送信号。
#include <signal.h>
int kill(pid_t pid, int signo);
int raise(int signo);
//两个函数返回:若成功则为0,若出错则为-1
  1. pid大于零时,pid是信号欲送往的进程的标识。
  2. pid等于零时,信号将送往所有与调用kill()的那个进程属同一个使用组的进程。
  3. pid等于-1时,信号将送往所有调用进程有权给其发送信号的进程,除了进程1(init)。
  4. pid小于-1时,信号将送往以-pid为组标识的进程。
  • 进程将信号发送给其他进程需要许可权
  • 规则是发送者的实际或有效用户ID必须等于接收者的实际或有效用户ID。
  • 如果被发送的信号是SIGCONT,则进程可将它发送给属于同一对话期的任一其他进程。
  • 如果signo参数是0,则kill仍执行正常的错误检查,但不发送信号。

10.10 函数alarm和pause

  • 使用alarm函数可以设置一个时间值,在将来的某个时刻该时间值会被超过。当所设置的时间值被超过后,产生SIGALRM信号。如果不忽略或不捕捉此信号,则其默认动作是终止该进程。
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
//返回:0或以前设置的闹钟时间的余留秒数
  • 参数seconds的值是秒数。
  • 每个进程只能有一个闹钟时间。如果在调用alarm时,以前已为该进程设置过闹钟时间,而且它还没有超时,则该闹钟时间的余留值作为本次alarm函数调用的值返回。以前登记的闹钟时间则被新值代换。
  • 如果有以前登记的尚未超过的闹钟时间,而且seconds值是0,则取消以前的闹钟时间,其余留值仍作为函数的返回值。

  • pause函数使调用进程挂起直至捕捉到一个信号。
#include <unistd.h>
int pause(void);
//返回:-1,errno设置为EINTR

10.11 信号集

  • 定义数据类型sigset_t以包含一个信号集。
#include<signal.h>
int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signo);
int sigdelset(sigset_t *set, int signo);
//四个函数返回:若成功则为0,若出错则为-1
int sigismember(const sigset_t *set, int signo);
//返回:若真则为1,若假则为0
  • 函数sigemptyset初始化由set指向的信号集,使排除其中所有信号。函数sigfillset初始化由set指向的信号集,使其包括所有信号。
  • 函数sigaddset将一个信号添加到现存集中,sigdelset则从信号集中删除一个信号。

10.12 函数sigprocmask

  • 函数sigprocmask可以检测或更改(或两者)进程的信号屏蔽字。
#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oset);
//返回:若成功则为0,若出错则为-1
  • oset是非空指针,进程的当前信号屏蔽字通过oset返回。
  • 若set是一个非空指针,则参数how指示如何修改当前信号屏蔽字。
  • SIG_BLOCK:添加信号
    SIG_UNBLOCK:移除信号
    SIG_SETMASK:赋值。

10.13 函数sigpending

  • sigpending返回对于调用进程被阻塞不能递送和当前未决的信号集。该信号集通过set参数返回。
#include <signal.h>
int sigpending(sigset_t *set);
//返回:若成功则为0,若出错则为-1

10.14 函数sigaction

  • sigaction函数的功能是检查或修改(或两者)与指定信号相关联的处理动作。
#include <signal.h>
int sigaction(int signo, const struct sigaction *act, struct sigaction *oact);
//返回:若成功则为0,若出错则为-1
  • 参数signo是要检测或修改具体动作的信号的编号数。若act指针非空,则要修改其动作。如果oact指针非空,则系统返回该信号的原先动作。
struct sigaction {
    void (*sa_handler)(); /*addr of signal handler, orSIG_IGN, orSIG_DFL*/
    sigset_t sa_mask;     /*additional signals to block*/
    int s a_flags;        /*signaloptions*/
    /* alternate handler */
    void (*sa_sigaction)(int, siginfo_t *, void *);
};
  • 如果sa_handler指向一个信号捕捉函数,则sa_mask字段说明了一个信号集,在调用信号捕捉函数之前,该信号集要加到进程的信号屏蔽字中。仅当从信号捕捉函数返回时再将进程的信号屏蔽字恢复为原先值。
  • sa_flags:
    SA_INTERRUPT:由此信号中断的系统调用不自动重启动
    SA_NOCLDSTO:当一子进程停止时,不产生此信号。
    SA_NOCLDWAIT:若signo是SIGCHLD,则当调用进程的子进程终止时,不创建僵死进程。
    SA_NODEFER:当捕捉到此信号时,在执行其信号捕捉函数时,系统不自动阻塞此信号。
    SA_ONSTACK:如果利用sigaltstack()建立信号专用堆栈,则此标志会把所有信号送往该堆栈。
    SA_RESETHAN:在此信号捕捉函数的入口处,将此信号的处理方式重置为SIG_DFL,并清除SA_SIGINFO标志。不能自动重置SIGILL和SIGTRAP这两个信号的配置。设置此标志使sigaction的行为如同设置了SA_NODEFER标志
    SA_RESTAR:由此信号中断的系统调用自动再起动
    SA_SIGINF:此选项对信号处理程序提供了附加信息:一个指向siginfo结构的指针以及一个指向进程上下文标识符的指针。
  • 如果设置了SA_SIGINFO标志,那么按下列方式调用信号处理程序:
    void handler(int signo, siginfo_t *info, void *context);
    siginfo和context详见APUE第280页。

10.15 函数sigsetjmp和siglongjmp

  • 在信号处理程序中进行非局部转移时应当使用sigsetjmp和siglongjmp函数。
#include <setjmp.h>
int sigsetjmp(sigjmp_buf env, int savemask);
//返回:若直接调用则为0,若从siglongjmp调用返回则为非0
void siglongjmp(sigjmp_buf env, int val)
  • 如果savemask非0,则sigsetjmp在env中保存进程的当前信号屏蔽字。则siglongjmp从其中恢复保存的信号屏蔽字。

10.16 函数sigsuspend

  • sigsuspend函数在一个原子操作中实现恢复信号屏蔽字,然后使进程睡眠。
#include <signal.h>
int sigsuspend(const sigset_t *sigmask);
//返回:-1,errno设置为EINT
  • 进程的信号屏蔽字设置为由sigmask指向的值。
  • 进程的信号屏蔽字设置为由sigmask指向的值。在捕捉到一个信号或发生了一个会终止该进程的信号之前,该进程也被挂起。如果捕捉到一个信号而且从该信号处理程序返回,则sigsuspend返回,并且该进程的信号屏蔽字设置为调用sigsuspend之前的值。

10.17 函数abort

  • abort函数的功能是使程序异常终止。
#include <stdlib.h>
void abort(void);
//此函数不返回
  • ANSIC要求若捕捉到此信号而且相应信号处理程序返回,abort仍不会返回到其调用者。

10.18 函数system

  • POSIX.2要求system忽略SIGINT和SIGQUIT,阻塞SIGCHLD。
  • system的返回值是shell的终止状态,其终止状态是128加上它所执行的命令由一个信号终止时的该信
    号编号数。仅当shell本身异常终止时,system的返回值才报告一个异常终止。

10.19 函数sleep、nanosleep和clock_nanosleep

#include <unistd.h>
unsigned int sleep(unsigned int seconds);
//返回:0或未睡的秒数

  • nanosleep函数与sleep函数癸似,但提供了纳杪级的精度。
#include <time.h>
int nanosleep(const struct timespec *reqp, struct timespec *remtp);
//返回值:若休眠到要求的时间,返回0;若出错,返回-1
  • reqgtp参数用秒和纳秒指定了需要休眠的时间长度。如果某个信号中断了休眠间隔,进程并没有终止,remtp参数指向的timespec结构就会被设置为未休眠完的时间长度。如果对未休眠完的时间并不感兴趣,可以把该参数置为NULL。
  • nanosleep函数并不涉及产生任何信号

  • 使用一个特殊时钟来实现一段延时。函数clock_nanosleep实现了这一功能。
#include <time.h>
int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *reqtp, struct timespec *remtp);
//返回值;若休眠要求的时间,返回0:若出错,返回错误码
  • 参数clock_id用于指定延时是相对于哪一种时钟时间进行的评估。当flags被设置为0的时候,睡眠时间是相对的(想要睡眠多久),当其数值被设置为TIMER_ABSTIME的时候,睡眠时间是绝对的。
    参数clock_id

10.20 函数sigqueue

  • 使用排队信号必须做以下几个操作。
  1. 使用sigaction函数安装信号处理程序时指定SA_STGINFO标志。
  2. 在sigaction结构的sa_sigaction成员中提供信号处理程序。
  3. 使用sigqueue函数发送信号。
#include <signal.h>
int sigqueue(pid_t pid, int signo, const union sigvalvalue);
//返回值:若成功,返回0;若出错,返回
  • 信号不能被无限排队。
  • 随着实时信号的增强,引入了用于应用程序的独立信号集。这些信号的编号在SIGRTMI~SIGRTMAX之间,包括这两个限制值。注意,这些信号的默认行为是终止进程。

10.21 作业控制信号

  • 当对一个进程产生SIGTSTP,SIGSTOP,SIGTTIN或SIGTTOU中的任意一种时,对该进程的任一未决的SIGCONT信号就被丢弃。当对一个进程产生SIGCONT信号时,对同一进程的任一未决的停止信号被丢弃。

10.22 信号名和编号

  • extern char *sys_siglist[];:下标是信号编号,数组中的元素是指向一个信号字符串名字的指针。

  • 可以使用psignal函数可移植地打印与信号编号对应的字符串。
#include <signal.h>
void psignal(int signo, const char *msg)
  • 字符串msg(通常是程序名)输出到标准出错,后面跟着一个冒号和一个空格,再跟着对该信号的说明,最后是一个新行符。

  • 如果在sigaction信号处理程序中有siginfo结构,可以使用psiginfo函数打印信号信息。
#include <signal.h>
void psiginfo(const siginfo_t *info, const char *msg) ;
  • 它的工作方式与psignal函数类似。

  • 给出一个信号编号,strsignal 将返回描述该信号的字符串。
#include <string.h>
char *strsignal(int signo);
//返回值:指向描述该信号的字符串的指针

  • 信号编号与信号名互转
#include <signal.h>
int sig2str(int signo, char *str);
int str2sig(const char *str, int *signop) ;
//两个函数的返回值:若成功,返回0:若出错,返回-1
  • 信号名是不带SIG前缀的信号名,str2sig函数可以使用标识十进制信号编号的字符串。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值