C / C ++中的信号 - 使个人shell发送/接收信号程序

时间:2014-09-28 03:36:25

标签: c++ c linux shell signals

我正在进行一项使用蒙特卡罗模拟的任务,以确定将产生多少随机地址访问。故障直到ULONG_MAX尝试次数。我们被指示创建信号处理程序来处理这些信号SIGSEGV,SIGIINT,SIGTSTP,SIGALRM,SIGUSR1和SIGUSR2。

我有几个关于SIGSEGV,SIGUSR1和SIGUSR2的问题。

  1. 对于SIGSEGV,我查看了sigsetjmp和siglongjmp的手册页,但我很困惑这些函数的参数应该做什么。

  2. 对于USR信号,方向是: SIGUSR1 / SIGUSR2 - 每当执行10次评估时, 然后,当前估计的准确度增加一位精度。例如, 在进行了100次评估之后,已知答案在1/100或两位数内 精度,并且当执行了1000时,那么答案就在内部已知 1/1000,或3位精度。这个进展将传达给父母(shell) 你写的)以下列方式:

    • 每次评估的次数超过10次,孩子都应该使用 kill()命令将SIGUSR1信号发送给父级。 (最简单的方法 这是设置一个“报告”变量,最初为10,每次都是数量 评估与报告变量匹配发送信号并将报告变量相乘 由10.)

    • 父级现在需要一个信号处理程序来捕获SIGUSR1,并增加一个计数器 每次它到来。如果计数器超过了命令行上设置的限制 shell已启动,然后父进程使用kill()系统调用发送SIGUSR2 向孩子发出信号。 (计数器需要在之前的某个时间重置为零 启动下一个孩子。 )

    • 孩子现在需要一个信号处理程序来捕获SIGUSR2。答案应该是 与control-C相同,实际上可能是同一个处理程序。

  3. 所以,话虽如此,我完全混淆了如何制作/放置这两个USR信号的位置。 有人可以帮我从这里出去吗。我非常感谢。这是我一直在研究的代码(减去shell,我确定它工作正常。已经过测试)。

    #include <iostream> 
    #include <cstdlib> /* srand, rand */ 
    #include <time.h>   /* time */
    #include <limits.h>
    #include <setjmp.h>
    #include <signal.h>
    using namespace std; 
    #define MAXARGS 512
    
    /* Monte Carlo Simulator */
    unsigned long int seg_fault = 0; // count for generated segfaults due to attempts 
    unsigned long int attempts = 0; // count for evaluations attempted 
    
    // functions
    void handler_seg (int sig); 
    void handler_int (int sig); 
    void handler_tstp (int sig);
    void handler_alrm (int arg);    
    void handler_usr1 (int sig); 
    void handler_usr2 (int sig); 
    
    /* Takes floating point command line argument as max seconds to run before stopping. 
    If +, call alarm before starting the for loop*/
    /*Generated by CTRL-C, signal handler simply reports the final results and exits */
    void handler_int (int sig)
    {
        cout << "SIG_INT called" << endl; 
        cout << "Total number of SEG_FAULTS: " << seg_fault << endl; 
        cout << "Total number of evaluations: " << attempts << endl;
        double percent = seg_fault/attempts; 
        cout << "The percentage of seg_fault attempts: " << percent << endl;  
        exit ((int)percent); 
    }
    
    /*Generated by CTRL-Z, reports the current results without stopping program, this 
    handler doesnt exit, and returns when complete */
    void handler_tstp (int sig)
    {
        cout << "SIG_TSTP called" << endl;
        cout << "Total number of SEG_FAULTS: " << seg_fault << endl;
        cout << "Total number of evaluations: " << attempts << endl;
        double percent = seg_fault/attempts;
        cout << "The percentage of seg_fault attempts: " << percent << endl;
        return; // can go right back to what you were doing because no errors to report 
    }
    
    void handler_seg (int sig)
    {
        seg_fault++; 
        attempts++;
        // return of the handler if eval counter hasnt reached the limit ulong_max
        if (attempts != ULONG_MAX)
            siglongjmp(); // fixes the error of seg_fault infinite loop 
        else 
        {
            cout << "SIG_INT called" << endl; 
            cout << "Total number of SEG_FAULTS: " << seg_fault << endl; 
            cout << "Total number of evaluations: " << attempts << endl;
            double percent = seg_fault/attempts; 
            cout << "The percentage of seg_fault attempts: " << percent << endl;  
            exit ((int)percent); 
        }
    }
    
    int main (int argc, char* argv[], char **envp)
    {
        srand (time(NULL)); 
        int count = 0;
        char *cargs[MAXARGS];
        int alrmReq = 0; 
    
    // need to parse any command line arguments that are present 
    for (int i=0 ; i<argc ; i++)
    {
        cout << argv[i] << endl; 
        cargs[i] = argv[i];
        if (i == argc-1)
            alrmReq = atoi(argv[i]); // set the alarm value 
    }
    
    // Set up signal handlers to catch and respond to certain signals 
    signal (SIGSEGV, handler_seg);
    
    // for loop to generate and test random addresses using global eval 
    // counter for the loop counter
     if (alrmReq > 0)
    {
        alarm (alrmReq); 
        signal (SIGALRM, handler_alrm); 
    }
    
     int* address_ptr = NULL; // initialization only occurs for the first run in a loop 
     int temp = 0; 
     int report = 10;
    for (attempts=0; attempts<100 ; attempts++) // ULONG_MAX
    {
        sigsetjmp(); // remembers the context at the beginnging of the loop
        attempts++; 
        address_ptr = (int*)rand(); // possibly not all the mem locations
        // attempt to read from possible seg_fault location 
        temp = *address_ptr; // for seg fault returns back to redo instruction that caused the fault
    
        // check if attempts is a power of 10
        if (attempts == report)
        {
            //child use the kill command to send SIGUSR1 signal to parent 
            signal (SIGUSR1, handler_usr1); 
            report = report*10; 
        }
    }   
    
    // successfully completed the for loop 
    cout << "Successfully completed the for loop" << endl; 
    cout << "Total number of SEG_FAULTS: " << seg_fault << endl; 
    cout << "Total number of evaluations: " << attempts << endl;
    double percent = seg_fault/attempts; 
    cout << "The percentage of seg_fault attempts: " << percent << endl;  
    exit ((int)percent); 
    }
    

0 个答案:

没有答案