一信号的处理
1 发送信号的系统函数
1raise
sleepusleeppause 2alarm 2 信号集的基本概念和基本操作
1基本概念2基本操作
sigemptyset - 清空信号集sigfillset - 填满信号集sigaddset - 添加信号到信号集中sigdelset - 删除信号集中的信号sigismember - 判断信号是否存在 3 信号的屏蔽
1sigprocmask2sigpending 4 计时器5 扩展
1sigaction2sigqueue 二进程间的通信技术
1 基本概念2 通信方式
一、信号的处理
1.1 发送信号的系统函数
(1)raise()
#include <signal.h>
int raise(
int sig);
功能:
主要用于给当前正在调用的线程/线程发送参数指定的信号,对于单线程的程序来说,等价于
kill(getpid(), sig);
返回值:
success —- 0,error —- 非0;
sleep()
#include <unistd.h>
unsigned int sleep(
unsigned int seconds);
功能:
主要用于使得当前正在调用的线程进入睡眠状态,直到参数指定的秒数睡够了,或者一个不能被忽略的信号到达了;
返回值:
如果参数指定的秒数过去了,则返回0,否则返回还没有来得及睡的秒数,也就是剩余的秒数;
usleep()
#include <unistd.h>
int usleep(useconds_t usec);
功能:
主要用于使得当前正在调用的线程睡眠参数指定的微秒;
pause()
#include <unistd.h>
int pause(
void);
功能:
主要用于是的当前正在调用的进程或线程暂停程序的执行,等待信号的到来;
返回值:
只有当信号被捕获时返回-1,并设置errno为EINTR;
(2)alarm()
#include <unistd.h>
unsigned int alarm(
unsigned int seconds);
功能: 主要用于在进过参数指定的秒数之后,给当前正在调用的进程发送SIGALRM信号; 每次重新设置闹钟之后都会取消之前的闹钟,当参数为0时,专门用于取消闹钟;
返回值: 如果之前没有闹钟则返回0,否则返回之前闹钟剩余的秒数;
1.2 信号集的基本概念和基本操作
(1)基本概念
信号集本质上就是若干个信号组成的集合。
思考: 请问采用最节省内存空间的方式设计信号集的数据类型,如何设计?
分析: int arr[64]; => 4*64 = 256B short arr[64]; => 2*64 = 128B char arr[64]; => 1*64 = 64B 采用每一个二进制位来代表一个信号,使用1表示有该信号,使用0表示没有该信号;=> 8B … 0010 0011 => 存在信号1、信号2、信号6
结论: 操作系统内部使用数据类型:sigset_t表示信号集的数据类型,该数据类型的大小是:128B;
typedef struct
{
unsigned long int __val[(
1024 / (
8 *
sizeof (
unsigned long int)))];
} __sigset_t;
typedef __sigset_t sigset_t
(2)基本操作
sigemptyset() - 清空信号集
#include <signal.h>
int sigemptyset(sigset_t *
set);
sigfillset() - 填满信号集
#include <signal.h>
int sigfillset(sigset_t *
set);
sigaddset() - 添加信号到信号集中
#include <signal.h>
int sigaddset(sigset_t *
set,
int signum);
sigdelset() - 删除信号集中的信号
#include <signal.h>
int sigdelset(sigset_t *
set,
int signum);
sigismember() - 判断信号是否存在
#include <signal.h>
int sigismember(
const sigset_t *
set,
int signum);
返回值: 信号存在返回1,信号不存在返回0,出错返回-1;
1.3 信号的屏蔽
在某些特殊程序的执行过程中,可能不允许被信号打断,此时就需要使用信号的屏蔽技术来解决该问题;
(1)sigprocmask()
#include <signal.h>
int sigprocmask(
int how,
const sigset_t *
set, sigset_t *oldset);
功能:
主要用于检查 / 修改即将屏蔽的信号集;
参数:
第一个参数:具体的屏蔽方式;
SIG_BLOCK - 使用当前屏蔽集 + 参数set屏蔽集
- ABC + CDE(set) =>ABCDE
SIG_UNBLOCK - 使用当前屏蔽集 - 参数set屏蔽集
- ABC - CDE(set) => AB
SIG_SETMASK - 使用参数set屏蔽集替换当前屏蔽集
- ABC CDE(set) => CDE
第二个参数:信号集类型的指针,用于指定新的信号集;
第三个参数:信号集类型的指针,用于带出之前屏蔽的信号集;
如果不想带出之前的屏蔽集,该参数给NULL即可;
注意: 信号的屏蔽并不是删除信号,而是相当于用一个隔板把信号档起来,对于可靠信号来说,产生了多少次,则在隔板的另一侧会排队等待多少个,而对于不可靠信号来说,无论产生了多少次,在隔板的另一侧只有一个信号排队等待,当信号的屏蔽解除时,相当于将隔板移开,只要进程不结束,则全部依次处理;
(2)sigpending()
#include <signal.h>
int sigpending(sigset_t *
set);
功能:
主要用于获取信号屏蔽期间来过但没来得及处理的信号集,通过参数set返回;
1.4 计时器
在linux系统中,操作系统会为每一个进程管理3种计时器,分别为:真实计时器、虚拟计时器以及实用计时器,一般都使用真实计时器进行计时;
#include <sys/time.h>
int getitimer(
int which,
struct itimerval *curr_value);
int setitimer(
int which,
const struct itimerval *new_value,
struct itimerval *old_value);
功能:
主要用于获取 / 设置计时器的参数信息;
参数:
第一个参数:计时器的类型;
ITIMER_REAL - 真实计时器,产生SIGALRM信号
- 统计进程消耗的真实时间
ITIMER_VIRTUAL - 虚拟计时器,产生SIGVTALRM信号
- 统计进程在用户态下消耗的时间(了解)
ITIMER_PROF - 实用计时器,产生SIGPROF信号
- 统计进程在用户态和内核态消耗的总时间
第二个参数:结构体指针,用于指定计时器的新值;
struct itimerval
{
struct timeval it_interval;
struct timeval it_value;
};
struct timeval
{
time_t tv_sec;
suseconds_t tv_usec;
};
第三个参数:结构体指针,用于带出设置之前的旧值;
1.5 扩展
(1)sigaction()
#include <signal.h>
int sigaction(
int signum,
const struct sigaction *act,
struct sigaction *oldact);
功能:
主要用于设置信号的处理方式,signal()的增强版;
参数:
第一个参数:具体的信号值 / 信号名称;(SIGKILL和SIGSTOP除外)
第二个参数:结构体指针,设置指定信号新的处理方式;
struct sigaction
{
void (*sa_handler)(
int);
void (*sa_sigaction)(
int, siginfo_t *,
void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(
void);
};
struct siginfo_t
{
int si_signo;
...
}
第三个参数:结构体指针,获取指定信号原来的处理方式;
(2)sigqueue()
#include <signal.h>
int sigqueue(pid_t pid,
int sig,
const union sigval value);
功能:
主要用于向指定的进程发送指定的信号,还可以带一个附加数据;
参数:
第一个参数:指定进程的进程号;
第二个参数:具体的信号值 / 信号名称,类似kill();
0 - - - - - 测试指定的进程是否存在
第三个参数:联合类型,
union sigval
{
int sival_int;
void *sival_ptr;
};
… …
二、进程间的通信技术
2.1 基本概念
两个 / 多个进程之间的信息交互,就叫做进程间的通信;
2.2 通信方式
文件信号管道共享内存消息队列(重点)信号量集网络(重点) … …
其中4、5、6通信方式统称为XSI IPC通信方式(X/open System Interface Inter-Process Communication)
练习: 尝试查询sigaction()的用法;
明日预报:
(1)进程间的通信技术;