【网络编程】信号

文章目录

  • 一、Linux信号概述
    • 1.1 发送信号
    • 1.2、信号处理方式
  • 二、信号函数
    • 2.1、signal系统调用
    • 2.2、sigaction系统调用
  • 三、信号集
    • 3.1、信号集函数
    • 3.2、进行信号掩码
    • 3.3、被挂起的信号
  • 四、网路编程相关信号


一、Linux信号概述

1.1 发送信号

  Linux下,一个进程给其他进程发送信号的API是kill函数

#include 
#include 
int kill(pid_t pid, int sig);
//该函数把信号sig发送给目标进程

  pid参数的含义如下:

pid参数 含义
pid > 0 信号发送给PID为pid的进程
pid = 0 信号发送给本进程组内的其他进程
pid = -1 信号发送给除init进程外的所有进程,但发送者需要拥有对目标进程发送信号的权限
pid < -1 信号发送给组ID为-pid的进程组中的所有成员

  该函数成功时返回0,失败返回-1并设置error。

1.2、信号处理方式

  在目标进程收到信号时,需要调用一个接收函数来处理,这个接收函数的原型如下:

#include 
typedef void (*__sighandler_t) (int);

  用户除了能用以上自定义函数以外,还能使用系统自带的函数进行处理

#include 
#define SIG_IGN ((__sighandler_t) 1)
#define SIG_DFL ((__sighandler_t) 0)

  SIG_IGN表示忽略目标信号,SIG_DFL表示使用信号的默认处理方式

二、信号函数

2.1、signal系统调用

  下面函数可以为一个信号设置处理函数:

#include 
_sighandler_t signal(int sig, _sighandler_t _handler)

  其参数含义如下:

参数 含义
sig 表示要捕获的信号类型
_headler 用于指定信号sig的处理函数,是_sighandler_t类型的函数指针

  成功的话返回一个_sighandler_t类型的函数指针,它是前一次调用signal函数时传入的函数指针。如果是第一次调用signal的话,则返回的是sig对应的默认处理函数指针SIG_DEF。
  出错的话返回SIG_ERR并设置error。

2.2、sigaction系统调用

  设置更健壮的信号处理函数则如下:

#include 
int sigaction(int sig, const struct sigaction* act, struct sigaction* oact);

struct sigaction{
#define  __USE_POSIX199309
	union{
		_sighadler_t sa_handler;
		void (*sa_sigaction) (int , siginfo_t*, void*);
	}
	_sigaction_handler;
#define sa_handler    __sigaction_handler.sa_headler
#define sa_sigaction  __sigaction_handler.sa_sigaction
#else
	_sighandler_t sa_handler;
#endif
	_sigset_t sa_mask;
	int sa_flags;
	void (*sa_restorer) (void);
};
函数中的参数 含义
sig 表示要捕获的数据类型
act 指定新的信号处理方式
oact 输出信号先前的处理方式
结构体中的参数 含义
sa_hander 指定信号处理函数
sa_mask 在进程原有信号掩码的基础上增加信号掩码
sa_flags 设置程序收到信号时的行为

  sigaction成功时返回0,失败时返回-1并设置error。

三、信号集

3.1、信号集函数

  Linux使用数据结构sigset_t来表示一组信号,其定义如下:

#include 
#define _SIGSET_NWORDS (1024 / (8 * sizeof(unisigned long int )))
typedef struct{
	unisigned long int __val[_SIGSET_NWORDS];
}__sigset_t;

  由此可见,sigset_t是一个长整型的数组,其中每个元素的每个位表示一个信号,这种定义方式与fd_set类似。
  并且,Linux提供了以下函数来对其进行操作。

#include 
int sigemptyset(sigset_t* _set);  //清空信号集
int sigfillset(sigset_t* _set);  //在信号集中设置所有信号
int sigaddset(sigset_t* _set, int _signo);//将信号_signo添加到信号集中
int sigdelset(sigset_t* _set, int _signo);//将信号_signo从信号集中删除
int sigismember(_const sigset_t* _set, int _signo);//测试_signo是否在信号集中

3.2、进行信号掩码

  这里可以使用sigprocmask来设置或查看进程掩码:

#include 
int sigprocmask(int _how, _const sigset_t* _set, sigset_t* _oset);
参数 含义
_set 新的信号掩码
_oset 原来的信号掩码(如果不为NULL的话)
_how 设置进程信号掩码的方式

  如果_set为NULL的话,则信号掩码不变,此时仍然可以用_oset来获得进程当前的信号掩码。
  sigprocmask成功时返回0,失败返回-1并设置error。

3.3、被挂起的信号

  在设置信号掩码后,被屏蔽的信号将无法被进程接收,该信号会被设置为一个挂起的信号,如果我们使用以下函数对其取消挂起,则它能立即被该进程接收到:

#include 
int sigpending(sigset_t* set);

  set参数用于保存被挂起的信号集。
  该函数成功时返回0,失败时返回-1并设置error。

四、网路编程相关信号

  • SIGHUP
      当挂起进程的控制终端时,将触发SIGHUP信号。对于没有控制终端的网络后台程序,它们通常利用SIGHUP信号来强制服务器重读配置文件
  • SIGPIPE
      往一个读端关闭的管道或者socket连接中写数据将会引发SIGPIPE信号,我们在代码中需要捕获或者忽略该信号,因为该信号的默认行为是结束进程。
  • SIGURG
      SIGURG信号是内核通知应用程序带外数据到达的方式。

《Linux高性能服务器编程》学习笔记

你可能感兴趣的:(网络编程,网络,linux)