信号处理(unix操作系统系)---5
来源:互联网 发布:js调用android摄像头 编辑:程序博客网 时间:2024/05/16 01:58
信号处理
一.实验目的
本实验要求利用可靠信号机制解决信号处理时可能出现的时间窗口,以及非局部转移等问题,将学习使用sigaction,alarm,sigpending,sigsetjmp和siglongjmp等函数解决在处理信号时遇到的问题。
二.实验设计
我们可以直接利用系统shell(在cs8是bash):execl(“/bin/sh”, “sh”, “-c”, buf, (char *) 0);
这样程序sigtest就具有系统shell的全部功能。
需要处理的信号:因为需要使用闹钟,所以实验需要处理两个信号:SIGALRM和
针对:SIGQUIT(要处理两种情况、用户输入、命令执行中)信号的可能情况。
第一种:如果当前程序正在执行用户命令,则信号处理函数必须“杀死”用户命令进程:kill(pid, SIGKILL); // pid为用户命令进程的ID。
第二种:对于信号SIGQUIT还有一种可能:正在接收用户输入的命令串。此时需要放弃当前输入,重新开始接收输入。解决方法可能需要使用非局部转移机制。
三.源代码
#include "apue.h"#include <sys/wait.h>#include <setjmp.h>#include <unistd.h>#include <signal.h>static void sig_int(int); /* our signal-catching function */static void sig_alrm(int);/* 闹钟 */static volatile pid_t pid;/* 进程id */static sigjmp_buf jmpbuf;/* 非局部转移 */Sigfunc *signal(int signo , Sigfunc *func){ struct sigaction act, oact;/* act:原来的动作 新的动作:oact */ act.sa_handler = func;/* 处理函数设置为传进来的出来函数 */ sigemptyset (& act.sa_mask);/* 信号就要考虑屏蔽字 这是清空屏屏蔽字 */ act.sa_flags = 0; if (signo == SIGALRM) sigaddset (& act.sa_mask, SIGQUIT);/* 如果是因为alarm信号引去的系统调用中断,会重启该系统调用。 act.sa_flags |= SA_RESTART; //在输入期间,发生中断,原来的系统调用将重启。 /* 设置信号值signo对应的处理函数为act.sahandle 旧的信号将保存在oact中。 */ if (sigaction(signo , &act,&oact)<0)return (SIG_ERR); /* 调用传进来的函数 ,将执行结果返回给调用方 */ return (oact.sa_handler);}
int main(int argc,char *argv[]){ char buf[MAXLINE]; /* from apue.h */ int status, time, flag = 0; if (argc >= 3) { flag=1; time=atoi(argv[2]); } if (signal(SIGQUIT, sig_int) == SIG_ERR) err_sys("signal error"); if (signal(SIGALRM, sig_alrm) == SIG_ERR) err_sys("signal error"); /* 设置转移终点 */ sigsetjmp(jmpbuf,1); /* 跳转打印标志 */ printf("%% "); /* print prompt (printf requires %% to print %) */ /* alarm 标志 time为睡眠某个时间后的唤醒 */ alarm(time); if (flag) /* 死循环 */ while (fgets(buf, MAXLINE, stdin) != NULL) { if (buf[strlen(buf) - 1] == '\n')/* replace newline with null 也就是'\0' */ buf[strlen(buf) - 1] = 0;/* 创建线程出错 */ /* 创建子进程 */if ((pid = fork()) < 0){ err_sys("fork error");} else if (pid == 0) { /* child 子进程执行代码段 */ execl("/bin/sh","sh","-c",buf,(char *)0); err_ret("couldn't execute: %s", buf); exit(127);}/* parent 进程运行的代码段 *//* 等待子进程退出,并看子进程退出状态 */waitpid(pid, &status, 0);pid =0;alarm(0);printf("%% "); } exit(0);}/* SIGQUIT 信号处理函数 ctrl+\ 不是ctrl+c ctrl+z */voidsig_int(int signo){ sigset_t pendmask; /* 子进程还没执行完, 杀死子进程 */ if (pid > 0) { /* waitpid (pid,NULL,0); */ kill(pid,SIGKILL); } /* 子进程执行完,正在执行父进程 跳到转移终点所在的位置。可以传参数代表哪个终点 */ else { printf ("\n"); printf ("interrupt\n"); siglongjmp (jmpbuf,1); } /* 函数返回在送往进程的时候被阻塞挂起的信号集合,如果返回出错则提示错误 */ if (sigpending(&pendmask) < 0) { err_sys("sigpending error"); } /* sigismember()用来测试参数signum 代表的信号是否已加入至参数set信号集里。 * 如果信号集里已有该信号则返回1,否则返回0。如果有错误则返回-1。 */ if (sigismember(&pendmask,SIGALRM)) {signal(SIGALRM,SIG_IGN);signal(SIGALRM,sig_alrm); }} /* 闹钟信号处理函数 */voidsig_alrm(int signo){ printf("TIME OUT!\n"); sigset_t pendmask; if (pid >0) { kill(pid,SIGKILL); } if (sigpending(&pendmask)<0) err_sys("sigpending error"); if (sigismember(&pendmask,SIGQUIT)) { signal(SIGQUIT,SIG_IGN); signal(SIGQUIT,sig_int); } siglongjmp (jmpbuf,1); }
四.运行结果
- 信号处理(unix操作系统系)---5
- 信号处理(unix操作系统系)
- UNIX平台信号(SIGNAL)处理
- unix信号处理函数 signal (1)
- unix信号处理函数 signal (1)
- Unix信号处理
- unix信号处理机制
- unix-关于信号、信号处理函数
- unix中的信号处理机制
- Unix信号处理学习笔记
- Unix信号处理学习笔记
- unix中的信号处理机制
- unix网络编程 信号处理
- UNIX再学习 -- 信号处理
- UNIX网络编程笔记(5):处理SIGCHLD信号
- linux操作系统下c语言编程入门 -- (5)信号处理
- UNIX信号(下)
- 《Unix环境高级编程》:信号处理
- javascript的全局函数
- 动态库的调用方式
- 编制模拟“五个哲学家”问题的程序(unix操作系统系)---4
- 那么ESP和EBP指的分别是什么呢?
- 职业经理人周刊 第52期 读书笔记
- 信号处理(unix操作系统系)---5
- fgets 函数 注意点
- 编制模拟“五个哲学家”问题的线程实现(unix操作系统系)---6
- UDP通信之网络打洞【转】
- unix命令行的个人心得
- asterisk chan_sip.c代码分析(转…
- 向前走
- nachos下双向量表的设计(含并发错误)1
- nachos下双向量表的设计(通过锁机制排除1的错误)2