linux实时信号与sigqueue函数编程实例
一、sigqueue函數
功能:新的發送信號系統調用,主要是針對實時信號提出的支持信號帶有參數,與函數sigaction()配合使用。
原型:int sigqueue(pid_t pid, int sig, const union sigval value);
第一個參數是指定接收信號的進程id;
第二個參數確定即將發送的信號;
第三個參數是一個聯合數據結構union sigval,指定了信號傳遞的參數,即通常所說的4字節值。 ?
typedef union sigval ?{? int sival_int;? void *sival_ptr;? }sigval_t;?
返回值:成功返回0,失敗返回-1
sigqueue()比kill()傳遞了更多的附加信息,但sigqueue()只能向一個進程發送信號,而不能發送信號給一個進程組。
接收程序:
#include<sys/types.h> #include<sys/stat.h> #include<unistd.h> #include<fcntl.h> #include<stdio.h> #include<stdlib.h> #include<errno.h> #include<string.h> #include<signal.h>#define ERR_EXIT(m) \do { \perror(m); \exit(EXIT_FAILURE); \} while(0)void handler(int, siginfo_t *, void *); int main(int argc, char *argv[]) {struct sigaction act;act.sa_sigaction = handler; //sa_sigaction和sa_handler都是結構體sigaction的成員,只能取其一,當設置了sa_sigaction就 //不用設置sa_handler了,sa_sigaction多用于實時信號,可以保存信息sigemptyset(&act.sa_mask);act.sa_flags = SA_SIGINFO; // 設置標志位后可以接收其他進程// 發送的數據,保存在siginfo_t結構體中if (sigaction(SIGINT, &act, NULL) < 0)ERR_EXIT("sigaction error");for (; ;)pause();return 0;}void handler(int sig, siginfo_t *info, void *ctx) {printf("recv a sig=%d data=%d data=%d\n",sig, info->si_value.sival_int, info->si_int);}----------------------------------------------------- struct sigaction {void (*sa_handler)(int);sigset_t sa_mask; int sa_flags; void (*sa_sigaction)(int, siginfo_t *, void *); }; 如果不設置sa_flags的話,初始化為void (*sa_handler)(int);這個就和signal差不多了哦,void handler(int signo);如果設置了sa_flags=SA_SIGINFO則,初始化為void (*sa_sigaction)(int, siginfo_t *, void *); 其中siginfo、context這個結構體的定義參見APUE(Advanced Programming in the UNIX Environment),即《UNIX環境高級編程》,上述例子中用 void handler(int signo, siginfo_t* info, void* context);作為信號處理函數注意兩者不可以同時使用...?
發送程序:
#include<sys/types.h> #include<sys/stat.h> #include<unistd.h> #include<fcntl.h> #include<stdio.h> #include<stdlib.h> #include<errno.h> #include<string.h> #include<signal.h>#define ERR_EXIT(m) \do { \perror(m); \exit(EXIT_FAILURE); \} while(0)int main(int argc, char *argv[]) {if (argc != 2){fprintf(stderr, "Usage %s pid\n", argv[0]);exit(EXIT_FAILURE);}pid_t pid = atoi(argv[1]); //字符串轉換為整數union sigval val;val.sival_int = 100;sigqueue(pid, SIGINT, val); //只可以發信號給某個進程,而不能是進程組return 0; }終端打印結果:
recv a sig=2 data=100 data=100
實時信號收發編程
接受程序:
#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)void handler(int);int main(int argc, char *argv[]) {struct sigaction act;act.sa_handler = handler;sigemptyset(&act.sa_mask);act.sa_flags = 0;sigset_t s;sigemptyset(&s);sigaddset(&s, SIGINT);sigaddset(&s, SIGRTMIN);sigprocmask(SIG_BLOCK, &s, NULL);if (sigaction(SIGINT, &act, NULL) < 0)ERR_EXIT("sigaction error");if (sigaction(SIGRTMIN, &act, NULL) < 0)ERR_EXIT("sigaction error");if (sigaction(SIGUSR1, &act, NULL) < 0)ERR_EXIT("sigaction error");for (;;)pause();return 0; }void handler(int sig) {if (sig == SIGINT || sig == SIGRTMIN)printf("recv a sig=%d\n", sig);else if (sig == SIGUSR1){sigset_t s;sigemptyset(&s);sigaddset(&s, SIGINT);sigaddset(&s, SIGRTMIN);sigprocmask(SIG_UNBLOCK, &s, NULL);} }在主函數中將SIGINT和SIGRTMIN信號加入信號屏蔽字,只有當接收到SIGUSR1信號時才對前面兩個信號unblock。需要注意的是如《信號的未決與阻塞》中說的一樣:如果在信號處理函數中對某個信號進行解除阻塞時,則只是將pending位清0,讓此信號遞達一次(同個實時信號產生多次進行排隊都會抵達),但不會將block位清0,即再次產生此信號時還是會被阻塞,處于未決狀態。
發送程序:
#include<sys/types.h> #include<sys/stat.h> #include<unistd.h> #include<fcntl.h> #include<stdio.h> #include<stdlib.h> #include<errno.h> #include<string.h> #include<signal.h>#define ERR_EXIT(m) \do { \perror(m); \exit(EXIT_FAILURE); \} while(0)int main(int argc, char *argv[]) {if (argc != 2){fprintf(stderr, "Usage %s pid\n", argv[0]);exit(EXIT_FAILURE);}pid_t pid = atoi(argv[1]); //字符串轉換為整數union sigval val;val.sival_int = 100;sigqueue(pid, SIGINT, val); // 不可靠信號不會排隊,即會丟失sigqueue(pid, SIGINT, val);sigqueue(pid, SIGINT, val);sigqueue(pid, SIGRTMIN, val); //實時信號會排隊,即不會丟失sigqueue(pid, SIGRTMIN, val);sigqueue(pid, SIGRTMIN, val);sleep(3);kill(pid, SIGUSR1);return 0; }先是運行recv程序:
simba@ubuntu:~/Documents/code/linux_programming/APUE/signal$ ./sigrtime_recv2
接著ps出recv進程的pid,運行send程序:
simba@ubuntu:~/Documents/code/linux_programming/APUE/signal$ ./sigrtime_send 4076
在send程序中連續各發送了SIGINT和SIGRTMIN信號3次,接著睡眠3s后使用kill函數發送SIGUSR1信號給recv進程,此時recv進程會輸出如下:
recv a sig=34
recv a sig=34
recv a sig=34
recv a sig=2
即實時信號支持排隊,3個信號都接收到了,而不可靠信號不支持排隊,只保留一個信號。
?
參考:《APUE》
總結
以上是生活随笔為你收集整理的linux实时信号与sigqueue函数编程实例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 非常好的一篇对linux信号(signa
- 下一篇: arm Linux 中断管理机制