栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

Linux信号学习笔记(4)

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Linux信号学习笔记(4)

Linux信号学习笔记(4) sigaction中使用sa_sigaction函数的说明 sigaction的介绍

  在第三篇笔记中提到sigaction的结构体如下:

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_sigaction是一个比较复杂的函数类型,可以在收信号的同时还能接收参数。
  在结构体中还有个sa_flags的变量,在这个标志位中有一个参数SA_SIGINFO的作用是使用扩展信号响应函数而不是标准响应函数,也就是说想使用sa_sigaction时需要将sa_flags置为SA_SIGINFO,否则默认还是使用sa_handler函数。

sigqueue函数

  使用man sigqueue查看sigqueue函数的原型如下:

int sigqueue(pid_t pid, int sig, const union sigval value)

  该函数需要三个参数,相比kill函数的pid和sig以外还多了一个sigval的联合体,该联合体用于保存所要传递信息。

union sigval {
	int sival_int;
	void *sival_ptr;
};

  所以第三个参数sigval在调用函数传参时不能直接将int类型的数字填入其中,而是需要定义一个sigval类型的变量,并赋值,然后再将该变量填入函数的参数中。

sa_sigaction

  那么sa_sigaction这个函数会将接收到的数据存入siginfo的结构体中。那么第三个参数在LINUX中给出的解释如下 (百度翻译可能不是很通顺)
  是指向ucontext_t结构的指针,强制转换为void* 。该字段指向的结构包含内核保存在用户空间堆栈上的信号上下文信息;有关详细信息,请参见SIGROUNT(2)。关于ucontext_t结构的更多信息可以在getcontext(3)中找到。通常, 处理函数不使用第三个参数 。

(*sa_sigaction)(int, siginfo_t *, void *);
siginfo_t结构体

  查看siginfo_t结构体中的内容如下:

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;     
	int      si_int;       
	void    *si_ptr;       
	int      si_overrun;   
	int      si_timerid;   
	void    *si_addr;      
	long     si_band;      
	int      si_fd;        
	short    si_addr_lsb;  
	void    *si_lower;     
	void    *si_upper;     
	int      si_pkey;      
	void    *si_call_addr; 
	int      si_syscall;   
	unsigned int si_arch;  
}

  sigval传来的参数存放在其中si_int和si_ptr中,如果我传了整型,那就使用si_int即可。

测试代码

  那么 (sigqueue()这个函数能不能在终端使用啊,有明白的教教我) 只能用接收程序先输出进程号,再将该进程号输入到发送程序中,发送程序向该进程号发送15信号,并附带一个12138的数据,接收程序的处理函数在接收到15信号时会输出信号值,以及info中的si_int值。
  接收程序:

#include
#include
#include
#include
#include
void handle(int sig,siginfo_t* info,void* arg)
{
    printf("receive signal %d. with information:%dn",sig,info->si_int);
}
int main()
{
    struct sigaction sigact;
    printf("%dn",getpid());
    memset(&sigact,0,sizeof(sigact));
    sigact.sa_sigaction=handle;
    sigact.sa_flags=SA_SIGINFO;
    sigaction(15,&sigact,NULL);
    pause();
}

  发送程序:

#include
#include
#include
#include
#include

int main()
{
    pid_t pid;
    scanf("%d",&pid);
    union sigval info;
    info.sival_int=12138;
    sigqueue(pid,15,info);
}

  输出结果如下:

~$ ./demo_11_recv
3626
receive signal 15. with information:12138
ps

  在sigval中还有个成员是sival_ptr,这是个指针,但是由于内存保护的原因,进程是没办法访问操作系统分配以外的空间,所以也就没办法访问发送方所发送的地址,不过这个问题可以进程之间只用共享内存来解决 (这个坑等我学明白了再填)

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/642323.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号