Linux信号:siginfo_t有错误的信息

时间:2013-11-28 13:53:29

标签: c++ linux signals

我正在尝试使用c ++ - static函数来捕获多个串行端口上的I / O,如Alternativ for Sigaction所示。但我在siginfo_t时遇到了一些问题。 SerialHandlerManager::register_handler始终使用SIGIO初始化signum

更新:这是一个可编辑的缩短代码

serialTest.cpp:

#include "serialTest.h"
#include "stdio.h"
/*----------------------SERIAL HANDLER MANAGER -----------------------------*/
SerialHandlerManager::SerialHandlerManager(){};

SerialHandlerManager* SerialHandlerManager::the_manager;

SerialHandlerManager* SerialHandlerManager::get_instance(){
    if(!the_manager)
        the_manager = new SerialHandlerManager;
    return the_manager;
}

void SerialHandlerManager::register_handler( int signum, int fd, SerialHandler* handler){
    /* ------------handling sigaction------------ */
   struct sigaction act;
    memset( &act, 0, sizeof(struct sigaction));

    act.sa_flags = SA_SIGINFO;
    act.sa_sigaction = SerialHandlerManager::dispatch_signal;
    if(fd >= handler_objects.size()) handler_objects.resize(fd + 1);
    handler_objects[fd] = handler;
    sigaction( signum, &act, NULL );

}

void SerialHandlerManager::dispatch_signal( int signum, siginfo_t * info, void * context )
{
     printf("%p %p %p\n", (void*)signum, info, context);
     printf("%d %d \n", info->si_fd, info->si_code);
//    (get_instance()->handler_objects[info->si_fd])->receive_function( signum );
}

/*------------------------- SERIAL HANDLER----------------------------------*/

/*------ CONST/DESTRUCT----- */
SerialHandler::SerialHandler( char* dev){
    //Setting Baudrate

    int baudrate = B38400;

    if ((this->config.fd = open(dev, O_RDWR | O_NOCTTY | O_NDELAY)) == -1)/* | O_NDELAY*/
    {
        perror("SerialHandler():Can't open device ");
    }

    config.term_attr.c_cflag    = 0;

    config.term_attr.c_cflag    = (baudrate | CS8 | CLOCAL | CREAD) & (~CSTOPB);
    config.term_attr.c_iflag    = 0;
    config.term_attr.c_oflag    = 0;
    config.term_attr.c_lflag    = 0;


    if (tcsetattr(config.fd, TCSAFLUSH, &config.term_attr) != 0)
    {perror("serial_init():tcsetattr() failed");}

    fcntl(config.fd, F_SETFL,FASYNC);
    /* installing Signal handler for Input interrupt */
    printf("fd: %d\n",config.fd);
    //Notify SerialHandlerManager that we are sensitive for SIGIO
    install_singal_handler( SIGIO );

}
SerialHandler::~SerialHandler(){
    close(this->config.fd);
}
/*------------------------------- receiving -------------------------------*/
void SerialHandler::receive_function(int status){
    printf("RECEIVE FUNCTION");
}

void SerialHandler::install_singal_handler( int signum){
    (SerialHandlerManager::get_instance())->register_handler( signum, config.fd, this);
}

int main(int argc,char* argv[]){
    //Install Serial Handler
    SerialHandler testhandler(argv[1]);
    sleep(100);
}

serialTest.h:

#ifndef  serialTest_INC
#define  serialTest_INC

#include <linux/ioctl.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/signal.h>
#include <stdlib.h>
#include <termios.h>
#include <fcntl.h>
#include <unistd.h> /* close /dev**/
#include <vector>
struct serial_cfg
{
    int fd;
    fd_set input_fdset;
    struct termios term_attr;
};


class SerialHandler{
    friend class SerialHandlerManager;
    private:

    //config of serial port
    struct serial_cfg config;

    /* installs new signal handler in SerialHandlerManager */
    void install_singal_handler( int signum );

/* Called using the SerialHandlerManager*/
    void receive_function(int status);
    public:
    SerialHandler(char* dev);
    /* also closes the device and releases it */
    ~SerialHandler();
};

/* For Handling multiple sigactions 
 * Singleton class*/
class SerialHandlerManager{
    private:
        SerialHandlerManager();
        static SerialHandlerManager* the_manager;
        std::vector<SerialHandler *> handler_objects;
        static void dispatch_signal( int signum, siginfo_t* info, void* context);
    public:
        static SerialHandlerManager* get_instance();
        /* Register new Serial Handler */
        void register_handler(int signum, int fd, SerialHandler* handler);
};

#endif   /* ----- #ifndef serialTest_INC  ----- */

因此,如果串行端口上有数据传入。实际上调用了dispatch_signal函数,但似乎siginfo_t没有正确的信息。这是输出:

  

singal在fd:0上获得,si_code:128

这似乎完全错误,因为128是SI_KERNEL代码。但是看一下sigaction man-page说当有SIGIO时,只有POLL_IN,POLL_OUT,......可以放在si_code中。 fd也不应该是0,因为我需要正确的fd来调用正确的Object函数。

我现在很困惑,需要你的帮助!

0 个答案:

没有答案