相关API接口
发送信号给指定进程
#include <sys/types.h>
#include <signal.h>
/**
* [kill 发送信号给指定的进程]
* @param pid [
* pid有多种情况:
1) pid > 0 表示给进程号为pid的进程发送信号;
2) pid = 0 表示给调用进程的进程组中的每一个进程发送信号;
3) pid = -1 表示给调用进程有权限发送信号的每一个进程发送信号;
4) pid < -1 表示给进程组号为-pid的每一个进程发送信号;
* ]
* @param sig [需要发送信号的编号,可以使用数字或者宏定义实现]
* @return [成功返回0,失败返回-1且修改errno的值]
*/
int kill(pid_t pid, int sig);
//等价于shell命令中 kill sig_num pid
实例
#include <sys/types.h>
#include <signal.h>
int main()
{
int ret;
ret = kill(16720, SIGSTOP); /* 给16720进程发送SIGSTOP信号 */
if (ret == -1)
{
perror("kill");
return -1;
}
return 0;
}
#include <sys/types.h>
#include <signal.h>
/* 给具有亲缘关系的进程发送 */
int main()
{
int ret;
pid_t pid;
pid = fork();
if (pid == -1)
{
perror("fork");
return -1;
}
else if (pid == 0)
{
while(1)
{
printf("child\n");
sleep(1);
}
//kill(getppid(), SIGSTOP); /* 子进程给父进程发送SIGSTOP信号 */
exit(EXIT_SUCCESS);
}
sleep(5);
ret = kill(pid, SIGINT); /* 父进程给子进程发送信号SIGINT */
if (ret == -1)
{
perror("kill");
return -1;
}
}
给调用进程发送信号
#include <signal.h>
/**
* [raise 是给调用进程发送信号,等价于:kill(getpid(), sig)]
* @param sig [需要发送信号的编号,可以使用数字或者宏定义实现]
* @return [成功返回0,失败返回非0]
*/
int raise(int sig);
实例
#include <stdio.h>
#include <signal.h>
int main()
{
int ret;
printf("嗨起来\n");
sleep(2);
printf("我嗨死了\n");
#if 0
ret = kill(getpid(), SIGSTOP);
if (ret == -1)
{
perror("kill");
return -1;
}
#else
ret = raise(SIGSTOP); /* 等价于ret = kill(getpid(), SIGSTOP); */
if (ret != 0)
{
return -1;
}
#endif
while(1)
{
printf("***哈哈哈*** 又起来嗨了\n");
sleep(1);
}
return 0;
}
给调用进程发送SIGABRT信号
#include <stdlib.h>
/*给调用进程发送SIGABRT信号,进程异常终止;功能等价于:ret = kill(getpid(), SIGABRT)*/
void abort(void);
实例
#include <stdio.h>
#include <signal.h>
int main()
{
int ret;
printf("嗨嗨嗨嗨\n");
sleep(2);
printf("嗨死了\n");
#if 1
ret = kill(getpid(), SIGABRT);
if (ret == -1)
{
perror("kill");
return -1;
}
#else
abort();/* 等价于:ret = kill(getpid(), SIGABRT); */
#endif
while(1)
{
printf("***哈哈哈*** 起来继续嗨;\n");
sleep(1);
}
return 0;
}
设定闹钟和定时器
#include <unistd.h>
/**
* [alarm
* 1) 设置定时器(闹钟),当设置时间计数为零的时候,发送闹钟信号SIGALRM;
2)在设置定时器(闹钟),如果已存在则取消原来的定时器,并设置新的定时器;
]
* @param seconds [秒数]
* @return [
* 1) 如果有设置定时器,则返回剩余秒数;
2) 如果之前没有设置定时器,则成功返回0;
]
*/
unsigned int alarm(unsigned int seconds);
实例
#include <unistd.h>
#include <stdio.h>
int main()
{
/* 设置定时器 */
printf("%d\n", alarm(5));/* 第一次设置定时器,返回值为0 */
sleep(3);
printf("%d\n", alarm(5));/* 第二次设置定时器,返回上一次设置定时器的剩余时间2 */
while(1)
{
printf("哇哇哇哇\n");
sleep(1);
}
return 0;
}
设置定时器二
#include <sys/time.h>
/**
* [getitimer description]
* @param which [description]
* @param curr_value [description]
* @return [description]
*/
int getitimer(int which, struct itimerval *curr_value);
/**
* [setitimer 设置定时器(闹钟)。 可代替alarm函数。精度微秒us,可以实现周期定时]
* @param which [
* which:指定定时方式
1) 自然定时:ITIMER_REAL → 14)SIGALRM计算自然时间
2) 虚拟空间计时(用户空间):ITIMER_VIRTUAL → 26)SIGVTALRM 只计算进程占用cpu的时间
3) 运行时计时(用户 + 内核):ITIMER_PROF → 27)SIGPROF计算占用cpu及执行系统调用的时间
* ]
* @param new_value [
* struct itimerval, 负责设定timeout时间
struct itimerval {
struct timerval it_interval; // 闹钟触发周期
struct timerval it_value; // 闹钟触发时间, 在设定之后的第一次触发需要的时间
};
struct timeval {
long tv_sec; // 秒
long tv_usec; // 微秒
}
itimerval.it_value: 设定第一次执行function所延迟的秒数
itimerval.it_interval: 设定以后每几秒执行function
* ]
* @param old_value [存放旧的timeout值,一般指定为NULL]
* @return [成功返回0,失败返回-1,且修改errno的值]
*/
int setitimer(int which, const struct itimerval *new_value, struct itimerval *old_value);
实例
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/time.h>
void myfunc(int sig)
{
if (sig == SIGALRM)
printf("timer out...\n");
}
int main()
{
struct timeval it_value = {5, 0};
struct timeval it_interval = {2, 0};
struct itimerval newvalue = {it_interval, it_value};
/* 注册信号处理函数 */
signal(SIGALRM, myfunc);
/* 设置定时器 */
setitimer(ITIMER_REAL, &newvalue, NULL);
while(1)
{
printf("test\n");
sleep(1);
}
return 0;
}
注册信号
#include <signal.h>
typedef void (*sighandler_t)(int);
/**
* [signal 注册信号]
* @param signum [需要注册信号的编号]
* @param handler [
* 处理方式:
1) SIG_IGN :忽略信号
2) SIG_DFL :系统默认信号处理方式
3) 自定义信号处理函数,函数类型:参数是int返回值是void。
]
* @return [
* 成功:第一次返回 NULL,下一次返回此信号上一次注册的信号处理函数的地址。如果需要使用此返回值,必须在前面先声明此函数指针的类型。
失败:返回 SIG_ERR ]
*/
sighandler_t signal(int signum, sighandler_t handler)
实例
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void handler(int sig)
{
printf("sig: %d\n", sig);
}
int main()
{
/* 注册SIGINT信号的处理方式是忽略 */
signal(SIGINT, SIG_IGN);
signal(SIGSTOP, SIG_IGN);/* 无效的,因为SIGSTOP不能被忽略 */
/* 注册SIGQUIT信号的处理方式是自定义信号处理函数 */
signal(SIGQUIT, handler);
while(1)
{
printf("哇哇哇哇\n");
sleep(1);
}
}
注册信号处理方式
#include <signal.h>
/**
* [sigaction 注册信号处理方式,指定信号signum的处理方式]
* @param signum [signum信号的编号,除了SIGKILL和SIGSTOP信号]
* @param act [传递信号的新的处理方式,注册信号的处理方式]
* @param oldact [返回信号之前的处理方式,一般使用NULL。]
* @return [成功0 失败-1 修改errno值]
*/
int sigaction(int signum, const struct sigaction *act, struct sigaction*oldact);
struct sigaction {
void (*sa_handler)(int); //旧版本的信号处理函数指针
void (*sa_sigaction)(int, siginfo_t *, void *); //新版本的信号处理函数指针
sigset_t sa_mask; //信号阻塞集
int sa_flags; //信号处理的方式
void (*sa_restorer)(void); //已弃用
};
/*
在有些系统中 sa_handler 和 sa_sigaction 使用联合体实现
void (*sa_handler)(int);
如果使用该版本的信号处理函数,则只能在信号处理函数中去实现信号处理的功能,所以不能做延时处理操作。
void (*sa_sigaction)(int signum, siginfo_t *info, void *context);
signum:信号的编号。
info:记录信号发送进程信息的结构体。
context:可以赋给指向 ucontext_t 类型的一个对象的指针,以引用在传递信号时被中断的接收进程或线程的上下文。
功能:在信号处理函数中来响应信号,并将信息添加到进程或者线程的上下文中,然后由上下文去处理信号。此时对于由耗时的信号处理也能够正常响应并处理 。
*/
实例
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void my_sa_sigaction(int signum, siginfo_t *info, void *context)
{
printf("signum = %d\n", signum);
}
int main()
{
struct sigaction act;
act.sa_sigaction = my_sa_sigaction;
//act.sa_handler = SIG_IGN;
sigaction(SIGQUIT, &act, NULL);
while(1) {
sleep(1);
printf("sigaction\n");
}
}
#include <signal.h>
int sigemptyset(sigset_t *set); //将set集合置空
int sigfillset(sigset_t *set); //将所有信号加入set集合
int sigaddset(sigset_t *set, int signum); //将指定的signum信号加入到set集合
int sigdelset(sigset_t *set, int signum); //将指定signum信号从set集合删除
int sigismember(const sigset_t *set, int signum); //判断指定signum信号是否存在set集合中
实例
#include <stdio.h>
#include <signal.h>
int main()
{
int i;
int ret;
/* 定义信号集合 */
sigset_t set;
printf("%d\n", sizeof(sigset_t));
/* 清空信号set集合 */
ret = sigemptyset(&set);
if (ret == -1)
{
perror("sigemptyset");
return -1;
}
/* 将所有信号添加到集合中 */
ret = sigfillset(&set);
if (ret == -1)
{
perror("sigfillset");
return -1;
}
/* 从信号集合set中删除信号 */
ret = sigdelset(&set, 5);
if (ret == -1)
{
perror("sigdelset");
return -1;
}
ret = sigdelset(&set, 15);
if (ret == -1)
{
perror("sigdelset");
return -1;
}
/* 向信号集合set中添加信号15 */
ret = sigaddset(&set, 15);
if (ret == -1)
{
perror("sigaddset");
return -1;
}
/* 判断信号signum是否存在于集合set中 */
for (i = 1; i <= 64; i++)
{
ret = sigismember(&set, i);
if (ret == -1)
{
perror("sigismember");
return -1;
}
else if (ret == 0)
{
printf("%d not is member\n", i);
}
else
{
printf("%d is member\n", i);
}
}
}
设置阻塞集
#include <signal.h>
/**
* [sigprocmask 设置阻塞集]
* @param how [
* SIG_BLOCK:向信号阻塞集合中添加 set 信号集,新的信号掩码是set和旧信号掩码的并集。
相当于 mask = mask|set。
SIG_UNBLOCK:从信号阻塞集合中删除 set 信号集,从当前信号掩码中去除 set 中的信号。
相当于 mask = mask & ~ set。
SIG_SETMASK:将信号阻塞集合设为 set 信号集,
相当于原来信号阻塞集的内容清空,然后按照 set 中的信号重新设置信号阻塞集。
相当于mask = set。
* ]
* @param set [set要操作的信号集地址。
若 set 为 NULL,则不改变信号阻塞集合,函数只把当前信号阻塞集合保存到 oldset 中。]
* @param oldset [oldset保存原先信号阻塞集地址]
* @return [成功:0,失败:-1,失败时错误代码只可能是 EINVAL,表示参数 how 不合法]
*/
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
实例
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
int main()
{
int i;
int ret;
/* 定义信号集合 */
sigset_t set;
/* 清空信号set集合 */
ret = sigemptyset(&set);
if (ret == -1)
{
perror("sigemptyset");
return -1;
}
/* 向信号集合set中添加信号SIGINT */
ret = sigaddset(&set, SIGINT);
if (ret == -1)
{
perror("sigdelset");
return -1;
}
/* 设置阻塞集 */
ret = sigprocmask(SIG_BLOCK, &set, NULL);
if (ret == -1)
{
perror("sigprocmask");
return -1;
}
while(1)
{
printf("sigprocmask\n");
sleep(1);
}
}
获取未决信号集合
#include <signal.h>
/**
* [sigpending 获取未决信号集合]
* @param set [存储集合数据的地址]
* @return [成功返回0,失败返回-1修改errno的值]
*/
int sigpending(sigset_t *set);
网友评论