我正在尝试使用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函数。
我现在很困惑,需要你的帮助!