信号处理(unix操作系统系)

 

信号处理

一.实验目的

本实验要求利用可靠信号机制解决信号处理时可能出现的时间窗口,以及非局部转移等问题,将学习使用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;
static sigjmp_buf jmpbuf;

Sigfunc *
signal(int signo , Sigfunc *func)
{
    struct sigaction act,oact;

    act.sa_handler = func;
    sigemptyset (& act.sa_mask);
    act.sa_flags = 0;
    if (signo == SIGALRM)
        sigaddset (& act.sa_mask,SIGQUIT);
    act.sa_flags |=SA_RESTART;
    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 %) */
        if (flag)
            alarm(time);
    while (fgets(buf, MAXLINE, stdin) != NULL) {
    
        if (buf[strlen(buf) - 1] == '\n')
            buf[strlen(buf) - 1] = 0; /* replace newline with null */

        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);
}


void
sig_int(int signo)
{
    sigset_t pendmask;
    if (pid >0){
        kill(pid,SIGKILL);
    //    waitpid (pid,NULL,0);    
    }
    else{
        printf ("\n");
        printf ("interrupt\n");
         siglongjmp (jmpbuf,1);    
    }
    if (sigpending(&pendmask)<0)
        err_sys("sigpending error");
    if (sigismember(&pendmask,SIGALRM)){
        signal(SIGALRM,SIG_IGN);
        signal(SIGALRM,sig_alrm);
    }
}

void
sig_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操作系统系)_第1张图片


你可能感兴趣的:(信号处理(unix操作系统系))