/***********************************************************************************************
相關函數:
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
int sigqueue(pid_t pid, int sig, const union sigval value);
***********************************************************************************************/
kill 與 sigqueue兩個函數功能都是向進程發送信號
不同的是sigqueue函數可以傳遞用戶參數到信號處理函數中
如果要使用sigqueue函數,則必須將sigaction結構體中的flags設置爲SA_SIGINFO
同時將信號處理函數的地址賦值給sa_sigaction。
參數解釋:
pid: 進程pid
sig: 要發送的信號編碼
sigval: 一個共用體, 可以傳遞一個整形參數,
如果要傳遞多個參數時,可以將其包裝在一個結構體中然後賦給sival_ptr
union sigval {
int sival_int;
void *sival_ptr;
};
實例1:
使用kill函數發送信號.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
void sig_quit(int signo)
{
if (SIGQUIT == signo) {
printf("receive SIGQUIT\n");
}
}
int main(void)
{
sigset_t zeromask;
sigemptyset(&zeromask);
/****使用自定義信號捕捉函數捕捉SIGQUIT信號*****/
if (mysignal(SIGQUIT, sig_quit) == SIG_ERR) {
perror("mysignal error");
return EXIT_FAILURE;
}
/**
* sigsuspend函數的工作原理是:
* 首先將之前設置爲阻塞的信號設置爲非阻塞,及捕捉那些信號
* 然後調用pause函數掛起,直到直到接收到任意信號,並從此信號捕捉函數返回後才返回。
**/
sigsuspend(&zeromask);
return EXIT_SUCCESS;
}
實例2:
調用sigqueue函數發送信號。
struct value{
pid_t pid;
union sigval si_val;
};
void *thread_func(void *arg)
{
sigqueue(((struct value*)arg)->pid, SIGUSR1, ((struct value*)arg)->si_val);
pthread_exit((void*)EXIT_SUCCESS);
}
void sig_usr(int signo, siginfo_t *info, void *context)
{
if (SIGUSR1 == signo) {
printf("receive SIGUSR1!\n");
printf("info.si_int = %s\n", (char*)info->si_ptr);
}
}
int main(void)
{
char arg[] = "hello world!";
struct value v;
v.pid = getpid(); //得到進程id
v.si_val.sival_ptr = (void*)arg; //需要傳遞的參數
sigset_t zeromask;
sigemptyset(&zeromask);
struct sigaction act;
act.sa_sigaction = sig_usr; //信號處理程序
sigemptyset(&act.sa_mask);
act.sa_flags = SA_SIGINFO; //設置sa_flags的標誌位SA_SIGINFO, 程序將自動調用sa_sigaction所指向的信號處理函數
if (sigaction(SIGUSR1, &act, NULL) < 0) {
perror("sigaction error");
return EXIT_FAILURE;
}
int err;
pthread_t tid;
/****創建線程,在線程中向進程發送信號****/
err = pthread_create(&tid, NULL, thread_func, (void*)&v);
if (err != 0) {
perror("pthread_create error");
return EXIT_FAILURE;
}
sigsuspend(&zeromask);
/****等待線程退出***/
pthread_join(tid);
return EXIT_SUCCESS;
}
實例1中使用到的mysignal函數源碼:
#include <stdlib.h>
#include <signal.h>
typedef void sigfunc(int);
sigfunc *mysignal(int signum, sigfunc *func)
{
struct sigaction act, oldact;
act.sa_handler = func;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if (SIGALRM == signum) {
#ifndef SA_INTERRUPT
act.sa_flags = SA_INTERRUPT;
#endif
} else {
/***處SIGALRM信號外,都嘗試重啓系統調用***/
act.sa_flags = SA_RESTART;
}
if (sigaction(signum, &act, &oldact) < 0) {
return (SIG_ERR);
}
return (oldact.sa_handler);
}