9--Linux学习----信号
来源:互联网 发布:stc12c5a32s2数据手册 编辑:程序博客网 时间:2024/05/21 18:43
---------------------------------信号------------------------------------------
1. 信号的作用
通知其他进程相应。进程之间一种通信机制
信号处理函数:
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
小小案例(引出什么是信号)
// signaldeal.c#include <unistd.h>#include <stdio.h>#include <signal.h>void deal(int s){printf("信号发生!\n");}main(){signal(SIGINT,deal);while(1){printf("进程执行!\n");sleep(1);}}
常见处理信号命令:
------------------------------------------------
$ kill -s 信号 进程ID ----信号: 数字1-31 34-64
$kill -l -- 查看所有信号
------------------------------------------------
案例: 使用程序发送信号
int kill(pid pid, int s)
进程ID:
>0 : 发送信号到指定的进程
=0 : 发送信号到该进程所在进程组的所有进程
=-1 : 发送给所有进程,除init外
<0 : 发送给指定的进程组。
2.信号的发送 与 安装
signal
kill
3.信号的应用
3.1 延时器 timeout
SIGALRM
信号发出函数: alarm
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
说明: alarm函数在sec秒之后发送一个SIGALRM信号。
3.2 定时器(有周期性,反复发送)
#include <sys/time.h>
int setitimer(int which, // 3种计时方式ITIMER_REAL(真实时间),ITIMER_VIRTUAL,ITIMER_PROF
const struct itimerval *new_value, // 定时器
struct itimerval *old_value); // 返回原来设置的定时器,如果为NULL,不返回
struct itimerval {
struct timeval it_interval; /* next value */ 间隔时间
struct timeval it_value; /* current value */ 延时时间
};
struct timeval {
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* microseconds */
};
案例1: 指定时间执行
#include <stdio.h>#include <signal.h>void deal(int s){printf("起床!\n");}main(){signal(SIGALRM,deal);alarm(5);while(1){ // ....}}
案例2: (5秒后,每隔1秒打印)
// alarm2.c#include <stdio.h>#include <signal.h>#include <sys/time.h>void deal(int s){ // printf("\7"); fprintf( stdout, "\7" );printf("起床\n");}main(){struct itimerval v = {0};signal(SIGALRM,deal);v.it_value.tv_sec = 5; // 延时时间v.it_interval.tv_sec = 1 ;///间隔时间setitimer(ITIMER_REAL,&v,0);while(1){//...}}
信号的应用:
系统与应用程序之间
应用与应用程序之间
父子进程之间
案例: 使用单进程 + 信号中断
使用定时器信号(不是进程),实现多任务。
/// demo1.c#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <fcntl.h>#include <signal.h>#include <curses.h>#include <math.h>#include <sys/time.h>#include <string.h>#include <time.h>WINDOW *wtime, *wnumb;int num,i;void showtime(int s){time_t tt;struct tm *t;if(s == SIGALRM){tt = time(0);//time(&tt);t = localtime(&tt);mvwprintw(wtime,1,1,"%02d:%02d:%02d",t->tm_hour,t->tm_min,t->tm_sec);refresh();//wrefresh(wtime);//wrefresh(wnumb); }}main(){ struct itimerval val;initscr();curs_set(0); /// 隐藏光标signal(SIGALRM,showtime);/// 绑定一个信号,让时间显示bzero(&val,sizeof(struct itimerval));val.it_value.tv_sec=0; ///设置为立即显示延时时间,可以试试,这句不能少,不然滞后显示val.it_value.tv_usec = 1;// 间隔时间val.it_interval.tv_sec = 1;wnumb = derwin(stdscr,3,11,(LINES-3)/2,(COLS-11)/2); //高度3,宽度11wtime = derwin(stdscr,3,10,0,(COLS-10)/2);box(wnumb,0,0); // 加上边框box(wtime,0,0);setitimer(ITIMER_REAL,&val,0); //不可少,启动定时器while(1){num = 0;for(i=0; i<7; ++i){num = num*10 +rand()%10;}mvwprintw(wnumb,1,2,"%07d",num);refresh();wrefresh(wnumb);sleep(1);wrefresh(wtime);usleep(10000);}endwin();}
案例2 : 多进程 + 信号 的应用
实现父子进程之间的通信
sleep 与 pause 函数被信号影响后,它们将不会继续执行。
随机显示7位随机属,当按下空格后,随机数停止显示。
// demo2.c #include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <signal.h>#include <curses.h>#include <math.h>#include <sys/time.h>#include <string.h>WINDOW *w;int num;int istop =0;void handle(int s){if(s == SIGUSR1){if(istop == 0) istop = 1;else istop = 0;}}main(){initscr();curs_set(0); // 隐藏光标noecho(); /// 禁止输入显示/// 创建子窗体w = derwin(stdscr,3,11,(LINES-3)/2,(COLS-11)/2);keypad(stdscr,TRUE); // z支持功能键keypad(w,TRUE);// 给窗体加边框box(w,0,0);refresh();wrefresh(w); if( fork() ) /// 父进程{ signal(SIGUSR1,handle); // handle函数绑定到信号上while(1){if(istop == 1){pause(); /// 进程挂起}num = 0;num = rand()%10000000;mvwprintw(w,1,2,"%07d",num);refresh();wrefresh(w);usleep(100000);}}else //子进程中处理按键 {while(1){ int ch;ch = getch();if(ch == 32) // 32指的是空格键{kill(getppid(),SIGUSR1);}}}endwin();}
4.信号的可靠与不可靠
信号有丢失现象。
分为:可靠信号 与 不可靠信号
早期: 信号1-31 31个信号,不可靠(与系统有关)
后期: 信号34-64 可靠信号(用户有关)
5.信号的操作
信号导致的问题:
1.信号的屏蔽
#include <signal.h>
int sigprocmask(int how, // 操作方式
SIG_BLOCK ----把参数set中的信号添加到信号屏蔽字中
SIG_SETMASK --- 把信号屏蔽字设置为参数set中的信号
SIG_UNBLOCK --- 从信号屏蔽字中删除参数set中的信号
const sigset_t *set, // 操作信号的集合
sigset_t *oldset); // 返回原来操作的信号集合
编程步骤:
1.声明信号集合
sigset_t sigs;
2.加入屏蔽信号
一组信号集合维护函数
2.1 清空集合 int sigemptyset(sigset_t *set);
2.2 添加信号到集合 int sigaddset(sigset_t *set, int signum);
2.3 从集合中删除信号 int sigdelset(sigset_t *set, int signum);
2.4 添加所有信号到集合 int sigfillset(sigset_t *set);
2.5 判定信号是否在集合 int sigismember(const sigset_t *set, int signum);
3.屏蔽信号
4.解除屏蔽
案例: (花费10秒钟计算1-10之间的和,外界中断信号不会影响程序的执行)
// mask.c#include <stdio.h>#include <signal.h>main(){int sum = 0;int i;// 1sigset_t sigs;//2sigemptyset(&sigs); // 清空信号集合sigaddset(&sigs,SIGINT); // 添加SIGINT 这个信号到信号集合//3 屏蔽SIGINT(Ctrl+c) 这个信号sigprocmask(SIG_BLOCK,&sigs,0); for(i=0; i<=10; ++i){sum += i;sleep(1);}printf("sum = %d\n",sum);//4.sigprocmask(SIG_UNBLOCK,&sigs,0);// 从信号屏蔽子中删除参数set中的信号printf("Over!\n"); // 这个有可能被外界信号干扰}
2.信号屏蔽的切换
int sigsuspend(const sigset_t *mask);-------------------目前还没有理解这个函数,
sigsuspend 是阻塞函数,对参数信号屏蔽。
3.查询被屏蔽的信号
int sigpending(sigset_t *set);
- LINUX学习笔记-信号SIGNAL
- 9--Linux学习----信号
- Linux进程-信号
- LINUX-信号SIGNAL
- LINUX-信号SIGNAL
- Linux进程-信号
- Linux进程-信号
- LINUX-信号SIGNAL
- 10 Linux 学习---信号(下)
- linux 进程通信-信号学习总结(1)
- Linux进程通信-信号
- 关于Linux的中断信号signal-信号是啥
- linux 内核-信号-队列
- linux 内核-信号-队列
- (转)LINUX-信号SIGNAL
- 信号及信号处理--信号处理--信号的屏蔽
- 信号---用于Linux 进程通信
- PySide学习笔记第八章-事件和信号
- 精彩BUG人生[4] -- bug free or not
- 网络监控工具弥补云监控短板
- Search in Rotated Sorted Array
- 【读书笔记】安卓异步任务
- 自定义的一些button样式
- 9--Linux学习----信号
- Remove Duplicates from Sorted Array
- 线索二叉树_legend
- lm8333添加键盘背光代码
- 如何在PC上查看一个web页面在移动端的展示效果
- C# 序列化和反序列化
- ListView/Adapter IllegalStateException
- 平面图形布局
- C++ map的基本操作和用法