Ice信号处理机制
概述
信号(signal)是一种进程间通信机制,它给应用程序提供了一种异步的软件中断,使应用程序有机会接受其他程序或者终端发出的命令(信号)。应用程序接收到信号后,一般有三种处理方式:忽略,默认,或者捕捉。如果我们自定义了信号处理函数,那么程序将会执行该信号的处理函数。
Ice::Application类提供了ice runtime的通信器初始化与信号捕获处理功能,适合在用户进程中使用。同时Ice也提供了Ice::Service类,相对于Ice::Application它更适用的情况是:应用程序需要作为Unix守护进程(daemon)运行在系统中。
下面将简单介绍这方面的内容。
Ice所能捕获的信号
在Ice run time中,支持三种linux信号的捕获:SIGINT,SIGHUP,SIGTERM。
1)SIGHUP:当终端发现断线情况时发送给与控制终端相连的控制进程的信号,或控制进程运行结束时发出的信号。它通常用来通知守护进程重新读取系统配置文件。
2)SIGINT:进程中断信号,可以用来中断一个正在运行的进程。通常是从终端输入的中断指令,如Ctrl+C键或Delete键。
3) SIGTERM:调用kill(1)命令时缺省产生的信号。
Application类中的信号处理
1.信号处理方法在Application类中的声明
Application.h中关于信号处理的函数定义如下:
// Application的入口函数,提供了丰富的初始化方式,一般使用第一个
// 将应用主函数参数直接传入即可
int main(int, char*[]);
int main(int, char*[], const char*);
int main(int, char*[], const Ice::InitializationData&);
int main(int, char*[], const char*, const Ice::LoggerPtr&);
int main(const StringSeq&);
int main(const StringSeq&, constchar*);
int main(const StringSeq&, constIce::InitializationData&);
// 应用的执行循环,应用需要继承这个函数并用自己的逻辑重写
virtual int run(int, char*[]) = 0;
// 信号回调函数
// 如果需要自己对信号进行处理,则需要继承和改写这个函数
// 注意,需在run()函数中调用callbackOnInterrupt()来向Ice表示使用用户回调
// 该函数的默认实现是空函数
virtual void interruptCallback(int);
// 返回应用名,即argv[0]
static const char* appName();
// 返回当前使用的Ice通信器实例指针
static CommunicatorPtr communicator();
// 设置信号处理模式
//
// 销毁模式:信号到来时将通信器实例销毁,也是Application的默认模式
static void destroyOnInterrupt();
// 关闭模式:信号到来时将通信器实例关闭,但不销毁
static void shutdownOnInterrupt();
// 忽略模式:信号到来时将通信器不做任何处理
static void ignoreInterrupt();
// 用户模式:信号到来时将调用interruptCallback()函数
static void callbackOnInterrupt();
// 信号的阻止和放开,不常用
// 阻塞信号的到来
static void holdInterrupt();
// 放开被阻塞的信号
static void releaseInterrupt();
// Application当前是否被信号中断
// 可用于判断Application的结束是否由于信号造成
static bool interrupted();
2.使用用户模式信号处理方法的示例:
#include <Ice/Application.h>
#include <iostream>
using namespace std;
class MyApplication : virtualpublic Ice::Application
{
public:
virtual int run(int argc , char* argv[])
{
//ignoreInterrupt(); //1.该方法设置信号处理模式为:忽略模式
//2.callbackOnInterrupt:用户模式,信号到来时调用interruptCallback方法
//如果不使用此方法,程序将会进行默认的信号处理。
callbackOnInterrupt();
interruptCallback(argc);
//More Server code here...
}
virtual void interruptCallback(int signo)
{
cout<<"Enter the interruptCallback()"<<endl;
if(signo== SIGINT)
{
cout<<"receive the signal SIGINT"<<endl;
//TODO:
}
else if(signo== SIGHUP)
{
cout<<"receive the signal SIGHUP"<<endl;
//TODO:
}
else if(signo== SIGTERM)
{
cout<<"receive the signal SIGTERM"<<endl;
//TODO:
}
else{cout<<"receivea signal:"<<signo<<endl;}
}
//More code here...
};
Service类的信号处理
1.Service类与Application类的异同
1)Ice::Application与Ice::Service功能相似,但Ice::Service类还封装了比较低级的,针对特定平台的初始化与关闭的步骤---系统服务常常需要这样的步骤。
2)Ice::Service需要用户继承的核心函数为start(),而Ice::Application需要用户继承的核心函数是run().虽然Ice::Service也有一个run()函数,但在Ice::Service中服务必须在start()函数中启动,比如处理命令行参数,创建对象适配器,注册servants等。
3)Ice::Service隐含了对Service的结束(通过run()方法调用WaitForShutdown()),而Ice::Application需要显式的定义类似ic->waitForShutdown()的操作。
2.信号处理方法在Ice::Service类中的声明
class ICE_API Service
{
public:
Service();
virtual ~Service();
// 关闭服务,默认操作是关闭服务所使用的Ice通信器
// 如果你需要其它的附加操作,继承并改写此函数
virtual bool shutdown();
// 信号回调函数,表示Service被信号所中断,默认操作是调用shutdown()函数
virtual void interrupt();
// 供给IceUtil::CtrlHandler注册的原始信号处理函数
// 它处理完SIGHUP后调用interrupt。一般无需继承和改写,除非你想自己处理SIGHUP
virtual void handleInterrupt(int);
protected:
// 允许子类执行它的启动活动,比如扫描所提供的参数向量、识别命令行选项,创建对象// 适配器,以及注册servants。
// 如果启动成功,子类必须返回true,否则返回false。
// 一般必须继承,并在其中实现应用自己的应用逻辑。
virtual bool start(int, char*[]) = 0;
// 阻塞等待Service的关闭。缺省操作是调用Ice通信器的waitForShutdown()。
virtual void waitForShutdown();
// 服务停止清理函数。决定了main()的返回值,缺省操作返回true。
// 如果你有其它资源需要清理,需要继承并改写该函数。
virtual bool stop();
// 初始化Service所用的Ice通信器
// Service类提供了一个方法让用户决定Ice通信器的构造方式
virtual Ice::CommunicatorPtr initializeCommunicator(int&, char*[], const InitializationData&);
// 日志相关函数
virtual void syserror(const std::string&);
virtual void error(const std::string&);
virtual void warning(const std::string&);
virtual void trace(const std::string&);
virtual void print(const std::string&);
public:
// 服务入口函数,处理服务安装、卸载和run()的调用
int main(int&, char*[], const InitializationData&= InitializationData());
int main(StringSeq&, constInitializationData& = InitializationData());
//
// 返回服务使用的Ice通信器
Ice::CommunicatorPtrcommunicator() const;
//
// 返回服务的惟一实例,注意实例是静态提供的。
static Service* instance();
//
// 判断当前运行模式。如果是以Win32服务或linux daemon方式运行,返回true.
// 否则返回false
bool service() const;
// 返回当前Service名字,等同于Ice::Application::appName()
std::string name() const;
// 检查当前平台是否支持后台运行(win32服务/linux daemon)
bool checkSystem()const;
// Service的真正执行函数
int run(int&, char*[], const InitializationData&= InitializationData());
protected:
// 允许信号中断
void enableInterrupt();
// 禁止信号中断
void disableInterrupt();
private:
Ice::LoggerPtr _logger; // Service使用的Log对象
Ice::CommunicatorPtr_communicator; //Services使用的通信器
bool _nohup; // 是否忽略SIGHUP函数
bool _service; // Service运行模式是否为服务/daemon
std::string _name; // Service应用名
static Service* _instance; // Service的惟一静态实例
};
3.用法举例
class MyService : publicIce::Service
{
protected:
virtual bool start(int, char *[],int&); //一般要覆盖基类的start,stop,interrupt这三种方法
virtual bool stop();
virtual void interrupt();
virtual void handleInterrupt(int);//在需要自定义处理信号情况下才需要覆盖这个方法
private:
Ice::ObjectAdapterPtrm_adapter;
};
void MyService::interrupt()
{
std::cout<< "Receive signal ..."<< std::endl;
//TODO:
}
bool MyService::stop()
{
std::cout<< "Stop running ..."<< std::endl;
//TODO:
return true;
}
void MyService::handleInterrupt(int signo)
{
interrupt();
if(signo==SIGHUP){
cout<<"signal:SIGHUP"<<endl;
//TODO:
}
else if(signo==SIGINT){
cout<<"signal:SIGINT"<<endl;
//TODO:
}
else if(signo==SIGTERM){
cout<<"signal:SIGTERM"<<endl;
//TODO:
}
else {
cout<<"Unknown signal."<<endl;
//TODO:
}
//TODO:
}
bool MyService::start(int argc, char * argv[],int& status)
{
enableInterrupt();//设置信号中断模式
//TODO:
//communicator()->waitForShutdown(); //不需要显示进行这个操作
return true;
}
参考自:http://blog.youkuaiyun.com/ydogg/article/details/1873854