发送信号传参
igqueue函数对应kill函数,但可在向指定进程发送信号的同时携带参数
int sigqueue(pid_t pid, int sig, const union sigval value);成功:0 ;失败:-1 ,设置errno
union sigval {
int sival_int;
void *sival_ptr;
};
向指定进程发送指定信号的同时,携带数据。但,如传地址,需注意,不同进程之间虚拟地址空间各自独立,将当前进程地址传递给另一进程没有实际意义。
捕捉函数传参
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。但此时的sa_flags必须指定为SA_SIGINFO。siginfo_t是一个成员十分丰富的结构体类型,可以携带各种与信号相关的数据。
#if 0
siginfo_t {
int si_signo;
int si_errno;
int si_code;
int si_trapno;
pid_t si_pid;
uid_t si_uid;
int si_status;
clock_t si_utime;
clock_t si_stime;
sigval_t si_value; 其他Unix版本
int si_int; posix
void *si_ptr; posix
int si_overrun;
int si_timerid;
void *si_addr;
long si_band;
int si_fd;
short si_addr_lsb;
void *si_call_addr;
int si_syscall;
unsigned int si_arch;
}
#endif
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit (EXIT_FAILURE); \
} while (0 )
#if 1
void myHandle_forsigaction(int signum, siginfo_t *s_t, void *p)
{
int myint = 0 ;
printf ("recv signum : %d \n" , signum);
myint = s_t->si_value.sival_int;
printf ("%d, %d \n" , myint, s_t->si_int );
}
int test()
{
pid_t pid;
int ret = 0 ;
struct sigaction act;
act.sa_sigaction = myHandle_forsigaction;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_SIGINFO;
if (sigaction(SIGINT, &act, NULL) < 0 )
ERR_EXIT("sigaction error" );
pid = fork();
if (pid == -1 ){
printf ("fork err...\n" );
return 0 ;
}
if (pid == 0 ){
int i = 0 ;
union sigval mysigval;
mysigval.sival_int = 222 ;
for (i=0 ; i<10 ; i++)
{
ret = sigqueue(getppid(), SIGINT, mysigval);
if (ret != 0 )
{
printf ("sigqueue .....\n" );
exit (0 );
}
else
{
printf ("sigqueue...successs\n" );
sleep(2 );
}
}
}
else if (pid > 0 )
{
for (;;)
pause();
}
return 0 ;
}
#endif
#if 1
void myhandle(int signo)
{
if (signo == SIGUSR1){
sigset_t bset;
sigemptyset(&bset);
sigaddset(&bset, SIGINT);
sigdelset(&bset, SIGRTMIN);
sigprocmask(SIG_UNBLOCK, &bset, NULL);
printf ("解除阻塞 recv sig SIGUSR1:%d \n" , signo);
}else if (signo == SIGINT || signo == SIGRTMIN){
printf ("recv sig num:%d \n" , signo);
}else {
printf ("其他信号recv sig num:%d \n" , signo);
}
}
void mysa_sigaction(int signo, siginfo_t * s_t, void *p)
{
if (signo == SIGUSR1){
sigset_t bset;
sigemptyset(&bset);
sigaddset(&bset, SIGINT);
sigdelset(&bset, SIGRTMIN);
sigprocmask(SIG_UNBLOCK, &bset, NULL);
printf ("解除阻塞 recv sig SIGUSR1:%d \n" , signo);
}else if (signo == SIGINT || signo == SIGRTMIN){
int myint = 0 ;
myint = s_t->si_value.sival_int;
printf ("recv sig num:%d,信号携带的数据:%d, %d \n" , signo, myint, s_t->si_int);
}else {
printf ("其他信号recv sig num:%d \n" , signo);
}
}
void test()
{
pid_t pid;
struct sigaction act;
#if 1
act.sa_handler = myhandle;
act.sa_flags = 0 ;
#else
act.sa_sigaction = mysa_sigaction;
act.sa_flags = SA_SIGINFO;
#endif
if (sigaction(SIGINT, &act, NULL) < 0 ){
ERR_EXIT("sigaction SIGINT" );
}
if (sigaction(SIGRTMIN, &act, NULL) < 0 ){
ERR_EXIT("sigaction SIGRTMIN" );
}
if (sigaction(SIGUSR1, &act, NULL) < 0 ){
ERR_EXIT("sigaction SIGUSR1" );
}
sigset_t bset;
sigemptyset(&bset);
sigaddset(&bset, SIGINT);
sigdelset(&bset, SIGRTMIN);
sigprocmask(SIG_BLOCK, &bset, NULL);
pid = fork();
if (pid == -1 ){
ERR_EXIT("fork err" );
}
if (pid == 0 ){
int i = 0 ;
int ret = 0 ;
union sigval v;
v.sival_int = 201 ;
for ( i = 0 ; i < 3 ; i++)
{
ret = sigqueue(getppid(), SIGINT, v);
if (ret != 0 ){
printf ("发送不可靠信号 SIGINT 2 失败 ret: %d\n" , ret);
exit (0 );
}else {
printf ("发送不可靠信号 SIGINT 2 ok\n" );
}
}
v.sival_int = 301 ;
for ( i=0 ; i<3 ; i++)
{
ret = sigqueue(getppid(), SIGRTMIN, v);
if (ret != 0 ){
printf ("发送可靠信号 SIGRTMIN 34 失败 ret: %d\n" , ret);
exit (0 );
}else {
printf ("发送可靠信号 SIGRTMIN 34 ok\n" );
}
}
kill(getppid(), SIGUSR1);
}
while (1 ) {
sleep(1 );
}
printf ("main.....\n" );
}
#endif
/*
性能测试
可靠信号linux内核是要缓存的,缓存的大小需要通过ulimit -a 查看
不可靠信号只缓存1 条
*/
void myhandle(int num, siginfo_t *info , void * p)
{
if (num == SIGUSR1)
{
// 把SIGINT和SIGRTMIN均添加到本进程的阻塞状态字中
sigset_t bset;
sigemptyset(&bset);
sigaddset(&bset, SIGINT);
sigaddset(&bset, SIGRTMIN);
sigprocmask(SIG_UNBLOCK, &bset, NULL);
printf ("解除阻塞 recv sig num:%d \n" , num);
}
else if (num == SIGINT || num== SIGRTMIN)
{
printf ("recv sig num:%d , 收到的数据是,%d \n" ,num, info->si_value.sival_int);
}
else
{
printf ("其他recv sig num:%d \n" , num);
printf ("收到的数据是,%d \n" ,info->si_value.sival_int);
}
}
void test()
{
pid_t pid;
struct sigaction act;
act.sa_sigaction = myhandle;
act.sa_flags = SA_SIGINFO;
// 注册非实时信号 处理函数
if ( sigaction(SIGINT, &act, NULL) <0 )
{
ERR_EXIT("sigaction SIGINT" );
}
//注册实时信号的处理函数
if ( sigaction(SIGRTMIN, &act, NULL) <0 )
{
ERR_EXIT("sigaction SIGINT" );
}
//注册了一个用户自定义信号SIGUSR1 处理函数
if ( sigaction(SIGUSR1, &act, NULL) <0 )
{
ERR_EXIT("sigaction SIGINT" );
}
//把SIGINT和SIGRTMIN均添加到本进程的阻塞状态字中
sigset_t bset;
sigemptyset(&bset);
sigaddset(&bset, SIGINT);
sigaddset(&bset, SIGRTMIN);
sigprocmask(SIG_BLOCK, &bset, NULL);
pid = fork ();
if (pid == -1 )
{
ERR_EXIT("fork err" );
}
if (pid == 0 )
{
int i = 0 ;
int ret = 0 ;
union sigval v;
v.sival_int = 0 ;
//可靠信号 性能测试
for (i=0 ; i<900 *1024 ; i++) //8 K
{
v.sival_int ++;
ret = sigqueue(getppid(), SIGRTMIN, v);
if (ret != 0 ){
printf ("发送可靠信号 SIGRTMIN 34 失败 ret: %d \n" , ret);
//exit (0 );
}else {
printf ("发送可靠信号 SIGRTMIN 34 ok, %d \n" , i);
}
}
//不可靠信号性能测试
for (i=0 ; i<900 *1024 ; i++) //8 K
{
v.sival_int ++;
//ret = sigqueue(getppid(), SIGRTMIN, v);
ret = sigqueue(getppid(), SIGINT, v);
if (ret != 0 ){
printf ("发送不可靠信号 SIGINT 2 失败 ret: %d \n" , ret);
//exit (0 );
}else {
printf ("发送不可靠信号 SIGINT 2 ok, %d \n" , i);
}
}
sleep (1 );
kill (getppid(), SIGUSR1);
}
while (1 )
{
sleep (1 );
}
printf ("main....\n" );
}
/*
linux内核调优,需要看这个
hzmct@U -64 :/study/linuxtest /day02/ 02 signal$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 3773
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m ) unlimited
open files (-n) 65536
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q ) 819200
real-time priority (-r) 0
stack size (kbytes, -s ) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 3773 //未决信号集的最大数
virtual memory (kbytes, -v) unlimited
file locks (-x ) unlimited
子进程休眠1 s 的结果
hzmct@U -64 :/study/linuxtest /day02/ 02 signal$ ./dm03_sigqueuc
recv sig num:34 , 收到的数据是,1
recv sig num:34 , 收到的数据是,2
recv sig num:34 , 收到的数据是,3
recv sig num:34 , 收到的数据是,4
recv sig num:34 , 收到的数据是,5
recv sig num:34 , 收到的数据是,6
recv sig num:34 , 收到的数据是,7
recv sig num:34 , 收到的数据是,8
recv sig num:34 , 收到的数据是,9
recv sig num:34 , 收到的数据是,10
解除阻塞 recv sig num:10
数字的大小取决于你的系统设置
ulimit -i
hzmct@U -64 :~$ ulimit -i
3773
recv sig num:34 , 收到的数据是,3771
recv sig num:34 , 收到的数据是,3772
recv sig num:34 , 收到的数据是,3773
解除阻塞 recv sig num:10
*/
int main()
{
test();
return 0 ;
}