Android Native Signal机制

来源:互联网 发布:淘宝飞猪客服电话 编辑:程序博客网 时间:2024/05/24 07:21

信号是Linux编程中非常重要的部分,同样也适用于android

信号机制是进程之间相互传递消息的一种方法,信号全称为软中断信号,也有人称作软中断。从它的命名可以看出,它的实质和使用很象中断。所以,信号可以说是进程控制的一部分。


软中断信号(signal,又简称为信号)用来通知进程发生了异步事件。进程之间可以互相通过系统调用kill和raise(java 应用中使用 Procees.sendSignal())发送软中断信号。内核也可以因为内部事件而给进程发送信号,通知进程发生了某个事件。注意,信号只是用来通知某进程发生了什么事件,并不给该进程传递任何数据。 

收 到信号的进程对各种信号有不同的处理方法。处理方法可以分为三类:第一种是类似中断的处理程序,对于需要处理的信号,进程可以指定处理函数,由该函数来处 理。第二种方法是,忽略某个信号,对该信号不做任何处理,就象未发生过一样。第三种方法是,对该信号的处理保留系统的默认值,这种缺省操作,对大部分的信 号的缺省操作是使得进程终止。进程通过系统调用signal来指定进程对某个信号的处理行为。 

信号处理的行为是以进程级的。就是说不同的进程可以分别设置不同的信号处理方式而互不干扰。同一进程中的不同线程虽然可以设置不同的信号屏蔽字,但是却共享相同的信号处理方式 (也就是说 在一个线程里改变信号处理方式,将作用于该进程中的所有线程)。

信号的系统调用signal 和 sigaction


signal:

系统调用signal用来设定某个信号的处理方法。该调用声明的格式如下: 
void (*signal(int signum, void (*handler)(int)))(int); 
在使用该调用的进程中加入以下头文件: 
#include <signal.h> 

上述声明格式比较复杂,如果不清楚如何使用,也可以通过下面这种类型定义的格式来使用(POSIX的定义): 
typedef void (*sighandler_t)(int); 
sighandler_t signal(int signum, sighandler_t handler); 


传递给信号处理例程的整数参数是信号值,这样可以使得一个信号处理例程处理多个信号。系统调用signal返回值是指定信号signum前一次的处理例程或者错误时返回错误代码SIG_ERR。下面来看一个简单的例子(Java_com_sailor_Signal_testSignal) 

JNIEXPORT void Java_com_sailor_Signal_testSignal( JNIEnv* env, jobject obj){     int i = 0;     signal(SIGALRM, sigroutine);     for(i = 0;i<10;i++)     {       alarm(1);     }}

void sigroutine(int dunno){LOGE("dunno:%d!", dunno);switch(dunno){case SIGALRM: LOGE("get SIGALRM!");break;case SIG_MY_MSG:LOGE("get SIG_MY_MSG!");break;default:break;}}

输出了

dunno:
<pre name="code" class="cpp" style="line-height: 18px;">get SIGALRM!

系统调用signal自定义信号(SIGUSR1被android使用)

#define SIG_MY_MSG SIGUSR2void sigroutine(int dunno){LOGE("dunno:%d!", dunno);switch(dunno){case SIGALRM: LOGE("get SIGALRM!");break;case SIG_MY_MSG:LOGE("get SIG_MY_MSG!");break;default:break;}}

JNIEXPORT void Java_com_sailor_Signal_testMySignal( JNIEnv* env, jobject obj){signal(SIG_MY_MSG, sigroutine);sleep(2);LOGE("send SIG_MY_MSG!");        raise(SIG_MY_MSG);}


sigaction:

替代signal 来设计的较稳定的信号处理

sigaction函数的功能是检查或修改与指定信号相关联的处理动作(可同时两种操作)。

int sigaction(int signo,const struct sigaction *restrict act,

              struct sigaction *restrict oact);


结构sigaction定义如下:

struct sigaction{
  void (*sa_handler)(int);
   sigset_t sa_mask;
  int sa_flag;
  void (*sa_sigaction)(int,siginfo_t *,void *);
};

sa_handler字段包含一个信号捕捉函数的地址

sa_mask字段说明了一个信号集,在调用该信号捕捉函数之前,这一信号集要加进进程的信号屏蔽字中。仅当从信号捕捉函数返回时再将进程的信号屏蔽字复位为原先值。

sa_flag是一个选项,主要理解两个

SA_INTERRUPT 由此信号中断的系统调用不会自动重启
SA_RESTART 由此信号中断的系统调用会自动重启

SA_SIGINFO 提供附加信息,一个指向siginfo结构的指针以及一个指向进程上下文标识符的指针

最后一个参数是一个替代的信号处理程序,当设置SA_SIGINFO时才会用他。


eg:

JNIEXPORT void Java_com_sailor_Signal_testSigaction( JNIEnv* env, jobject obj){int i = 0;struct sigaction timeoutsigact;    timeoutsigact.sa_handler = handler;    sigemptyset(&timeoutsigact.sa_mask);    sigaddset(&timeoutsigact.sa_mask, SIGALRM);    sigaction(SIGALRM, &timeoutsigact, 0);for(i = 0;i<10;i++)     {       alarm(1);     }}


void handler(int sig){    LOGE("Got SIGSEGV at address: %d\n",                sig);    LOGE("get SIGALRM!");    }

sigaction自定义信号:

// SIGUSR1 is used by android system#define SIG_MY_MSG SIGUSR2void sigroutine(int dunno){LOGE("dunno:%d!", dunno);switch(dunno){case SIGALRM: LOGE("get SIGALRM!");break;case SIG_MY_MSG:LOGE("get SIG_MY_MSG!");break;default:break;}}

JNIEXPORT void Java_com_sailor_Signal_testMySigaction( JNIEnv* env, jobject obj){struct sigaction act;        act.sa_handler = sigroutine;        sigemptyset(&act.sa_mask);        act.sa_flags = 0;        sigaction(SIG_MY_MSG, &act, NULL);sleep(2);LOGE("send SIG_MY_MSG!");raise(SIG_MY_MSG);}


下面为java层代码

package com.sailor;public class Signal {static {// 加载动态库System.loadLibrary("JNISignal");}public native void testSignal();public native void testMySignal();public native void testMySigaction();public native void testSigaction();}

public void startSignal(View view){Signal signal = new Signal();/*signal.testMySigaction();*/signal.testMySignal();/*signal.testSignal();*//*signal.testSigaction();*/}
代码在http://download.csdn.net/detail/kanwah200/7988789





0 0