2

私の目的は、カーネルからユーザー空間で実行されている Android サービスにシグナルを送信することです。このシグナルを受信すると、サービスはカーネルに IOCTL コールバックを行う必要があります。この ioctl 呼び出しによってカーネルからデータを取得した後、ユーザーに表示する必要があります。このために、Java サービスからネイティブ メソッドを呼び出します。このメソッドは、このシグナルのハンドラー関数を含む sigaction 構造を登録します。このハンドラー関数は、IOCTL 呼び出しを行い、Java 関数を呼び出して文字列を Java サービスに渡します。

これがsignal.javaクラスです

public class signal {
static{
    System.loadLibrary("signal");
}
public native String hello();

public String messageMe(String s)
{
    if(null != MainActivity.mUiHandler)
    {
        Message msgToActivity = new Message();
        msgToActivity.what = 0;

            msgToActivity.obj  = s; // you can put extra message here

        MainActivity.mUiHandler.sendMessage(msgToActivity);
    }

    System.out.println(s);
        return s;
}

}

この「messageMe」関数をシグナル ハンドラから呼び出す必要があります。これは、sigaction 構造を登録するネイティブの hello() 関数です。

JNIEXPORT jstring JNICALL Java_com_example_service_signal_hello
(JNIEnv * env, jobject obj) {

 int configfd;
char buf[10];
/* setup the signal handler for SIG_TEST
 * SA_SIGINFO -> we want the signal handler function with 3 arguments
 */
struct sigaction sig;
sig.sa_sigaction = receiveData;
sig.sa_flags = SA_SIGINFO;
sigaction(SIG_TEST, &sig,NULL);
}

receiveData はハンドラ関数です。ここに行きます。

void receiveData(int n, siginfo_t *info,void* unused) {
    char buf[200];
    char *msg = "hello world";
    int fd = -1;
    if ((fd = open("/dev/my_device", O_RDWR)) < 0) {
            perror("on");
            return;
    }
    if(ioctl(fd, READ_IOCTL, buf) < 0)
            perror("second ioctl");

     jstring jstr = (*env)->NewStringUTF(env, buf);
     jclass *clazz = (*env)->GetObjectClass(env, obj);
     jmethodID messageMe = (*env)->GetMethodID(env,clazz, "messageMe", "(Ljava/lang/String;)Ljava/lang/String;");
     jobject result = (*env)->CallObjectMethod(env,obj, messageMe, jstr);

    printf("message: %s\n", buf);

このハンドラ関数は、Java 関数「messageMe」を呼び出し、カーネルから読み取った文字列を引数として渡す必要があります。ただし、環境変数 JNIEnv * と jobject obj はありません。これらの変数へのグローバル ポインターを hello() 関数で維持し、ここで使用すると、NoClassDefFoundError が返されました。このシグナル ハンドラから Java 関数に文字列を送信するにはどうすればよいですか?

4

2 に答える 2

1

次のグローバル変数があります。将来の使用のためにこれらのオブジェクトをキャッシュしました。

JavaVM* vm;
static jclass cl;
static jobject ob;

hello 関数では、上記の変数のグローバル参照を作成しました。

JNIEXPORT jstring JNICALL Java_com_example_service_signal_hello
(JNIEnv * env, jobject obj) {
(*env)->GetJavaVM(env,&vm);
ob = (*env)->NewGlobalRef(env,obj);
jclass clazz = (*env)->FindClass(env,"com/example/service/signal");
cl = (*env)->NewGlobalRef(env,clazz);
}

今、これらをハンドラー関数で使用しました

void receiveData(int n, siginfo_t *info,void* unused) {
//other code
JNIEnv* env = NULL;
    if(vm==NULL)
        return;
    (*vm)->AttachCurrentThread(vm,&env,0);
 jmethodID messageMe = (*env)->GetStaticMethodID(env,cl, "messageMe", "(Ljava/lang/String;)Ljava/lang/String;");
jobject result = (*env)->CallStaticObjectMethod(env,cl, messageMe, jstr);
}

私が行った変更の 1 つは、通常のメソッドの代わりに静的メソッドを使用することでした。そのため、クラスの特定のインスタンスを使用する必要はありませんでした。メソッドが静的でない場合、グローバル変数「ob」を CallObjectMethod で使用できます。

于 2013-05-20T10:25:20.653 に答える