2014-12-01 2 views
2

네트워크 커널 확장에서 커널 공간에서 응용 프로그램 종료 (예 : cmd-q)를 감지하는 방법을 찾고 있습니다.커널 확장에서 응용 프로그램 종료를 감지하는 방법 Mac OS X

더 정확하게 : 프로세스 (예 : 터미널 핑)가 IOLockSleep (... THREAD_ABORTSAFE)에있는 동안 Ctrl-c가 잠금을 해제 할 수 있습니다. proc_issignal()에 요청하면 sigmask (SIGINT)에 응답합니다.

이제 다른 프로세스를 감지하는 방법을 찾고 있습니다. firefox (메뉴 막대 : 응용 프로그램 종료 (cmd-q)). 여기

내가 뭘하려 : 위에서 설명한대로

#define FLAG(X) ((dispatch_source_get_data(src) & DISPATCH_PROC_##X) ? #X" " : "") 

struct ProcessInfo { 
    int pid; 
    dispatch_source_t source; 
}; 

// function called back on event 
void process_termination_event(struct ProcessInfo* procinfo) { 
    dispatch_source_t src = procinfo->source; 
    printf("process_termination_event: %d \n", procinfo->pid); 
    printf("flags: %s%s\n", FLAG(EXIT), FLAG(SIGNAL)); 
    dispatch_source_cancel(procinfo->source); 
} 

// function called back when the dispatch source is cancelled 
void process_termination_finalize(struct ProcessInfo* procinfo) { 
    printf("process_termination_finalize: %d \n", procinfo->pid); 
    dispatch_release(procinfo->source); 
} 

// Monitor a process by pid, for termination 
void MonitorTermination(int pid) { 
    struct ProcessInfo* procinfo = (struct ProcessInfo*)malloc(sizeof(struct ProcessInfo)); 

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
    dispatch_source_t dsp = dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC, pid, DISPATCH_PROC_EXIT|DISPATCH_PROC_SIGNAL, queue); 

    procinfo->pid = pid; 
    procinfo->source = dsp; 

    dispatch_source_set_event_handler_f(procinfo->source, (dispatch_function_t)process_termination_event); 
    dispatch_source_set_cancel_handler_f(procinfo->source, (dispatch_function_t)process_termination_finalize); 
    dispatch_set_context(procinfo->source, procinfo); 
    dispatch_resume(procinfo->source); 
} 

int main(int argc, const char * argv[]) 
{ 
    for (int i = 0; i < argc; ++i) { 
     pid_t pid = atoi(argv[i]); 
     printf("MonitorTermination: %d\n", pid); 
     fflush(stdout); 

     MonitorTermination(pid); 
    } 

    CFRunLoopRun(); 
    return 0; 
} 

process_termination_event는 cmd를-Q 후 호출되지 않습니다. 힘이 끊긴 후에도. 자체 네트워크 커널 확장 함수 내 루프에서 개최되는

과정 :

errno_t KEXT::data_out(void *cookie, socket_t so, const struct sockaddr *to, mbuf_t *data, mbuf_t *control, sflt_data_flag_t flags) 
{ 
    // at this point I would like to detect the app quit/termination signal. 
    while(PROCESS_IS_NOT_TEMINATING); // <-- pseudo code, actually held with IOLockSleep... 
    return 0; 
} 

은 정말 어떤 도움을 주셔서 감사합니다 것입니다! 미리 감사드립니다.

답변

1

생각 해보지 않았지만 커널 공간에 있다면 커널 확장 (kext)을 작성한다고 가정합니다. 커널 확장을 사용하면 응용 프로그램을 실행하기 위해 monitor Vnodes을 사용할 수 있습니다. 대신 파일 범위를 사용할 수 있습니다.

사용자 레벨 응용 프로그램 (데몬)과 함께 kext는 프로세스가 실행을 시작했음을 알리고 사용자 수준 데몬에서 시작된 응용 프로그램의 종료를 모니터하고 Grand Central Dispatch 기능을 사용합니다. 필요한 경우 사용자 응용 프로그램이 종료 된 응용 프로그램의 kext에 알릴 수 있습니다. 당신은 응용 프로그램이 실행되는 통보 할 때

은이 같은 작업을 수행 할 수 있습니다, 사용자 수준 응용 프로그램에서 종료를 모니터링하려면 : -

그래서 각각의 시작 응용 프로그램의 KEXT 통보
// pid and path provided from vNode scope kext... 
void UserLevelApp::MonitorProcessTermination(int pid, const QString &path) 
{  
    ProcessInfo* procinfo = new ProcessInfo; 

    procinfo->pid = pid; 
    procinfo->path = path; 
    procinfo->context = this; 

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
    dispatch_source_t dsp = dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC, pid, DISPATCH_PROC_EXIT, queue); 

    dispatch_source_set_event_handler_f(dsp, (dispatch_function_t)process_termination_event); 
    dispatch_source_set_cancel_handler_f(dsp, (dispatch_function_t)process_termination_finalize); 

    procinfo->source = dsp; 
    dispatch_set_context(dsp, procinfo); 

    dispatch_resume(dsp); 
} 

// app terminated call-back function 
void UserLevelApp::process_termination_event(struct ProcessInfo* procinfo) 
{ 
    dispatch_source_cancel(procinfo->source); 

    // example of how to use the context to call a class function 
    procinfo->context->SomeClassFunction(procinfo->pid, procinfo->path); 

    qDebug("App Terminated: %d, %s\n", procinfo->pid, procinfo->path.toUtf8().data()); 
} 

// finalize callback function 
void UserLevelApp::process_termination_finalize(struct ProcessInfo* procinfo) 
{ 
    dispatch_release(procinfo->source); 
    delete procinfo; 
} 

을, 그것으로 응용 프로그램이 종료 될 때, 당신은 다시 등록 기능에서 호출되는 관련 이벤트 핸들러가 process_termination_event이 방법 하다니 process_termination_finalize

는 아소가 필요합니다 kext로 사용자 수준의 데몬 응용 프로그램을 설치하면 보안 및 안정성 측면에서 그다지 좋지 않습니다.

+0

접근 방법이 좋습니다. 하지만 "응용 프로그램이 종료 될 것입니다"라는 문제에 봉착했습니다. kext 함수는 앱을 계속 유지하기 때문입니다. kext가 처리를 마칠 때까지 앱을 종료 할 수 없습니다. – Jan

+0

내가 설명한 것을 구현했다면 앱을 종료해도 아무런 문제가 없어야합니다. 항상이 방법을 사용합니다. 커널 확장은 데몬에게 프로세스 활동을 통지하는 것 이상을 수행하고 있으며 프로세스의 모든 리소스를 보유하지 않아야합니다. – TheDarkKnight

+0

설명대로 구현했다고 생각합니다. 이제 더 자세한 설명과 데몬 코드를 추가했습니다. 어쩌면 뭔가 잘못되었거나 kext 처리 (루프/잠금 중)가 의도에 전혀 맞지 않을 수 있습니까? – Jan

관련 문제