2014-01-28 4 views
0

데몬이 파일에 대한 액세스를 제어하기 위해 fanotify API를 사용하게했습니다. 다음은 작업 스레드입니다.fanotify를 사용하여 파일에 대한 액세스를 제어하는 ​​실행중인 데몬으로 시스템을 재부팅하거나 종료하면 시스템이 멈 춥니 다

void * threadProc(void * data) 
{ 
    if(data == NULL) return 0; 

    RealTimeDrvrImp & _this = *((RealTimeDrvrImp *)data); 

    const unsigned int fi_flags = FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK; 
    const unsigned int fi_event_f_flags = O_RDONLY | O_LARGEFILE; 

    _this.m_fa_fd = fanotify_init(fi_flags, fi_event_f_flags); 
    if (-1 == _this.m_fa_fd) 
     return NULL; 

    const unsigned int fm_flags = FAN_MARK_ADD | FAN_MARK_MOUNT; 
    const uint64_t fm_event_f_flags = FAN_OPEN_PERM /*| FAN_ACCESS_PERM*/ /*| FAN_CLOSE_WRITE*/; 

    if (-1 == fanotify_mark(_this.m_fa_fd, fm_flags, fm_event_f_flags, 0, "/")) 
    { 
     close(_this.m_fa_fd); 
     return NULL; 
    } 

    char buf[4096]; 
    int len = 0; 
    struct timespec tmsp = { 0, 1000000 };//500 miliseconds 
    pid_t self_pid = getpid(); 

    while(_this.m_DoAvRealtimeScanThread) 
    { 
     if(-1 == (len = read(_this.m_fa_fd, (void *) &buf, sizeof (buf)))) 
     { 
      if(EAGAIN == errno) 
      { 
       nanosleep(& tmsp, NULL); 
       continue; 
      } 
      else 
       break; 
     } 
     const struct fanotify_event_metadata *metadata 
       = (struct fanotify_event_metadata *) buf;  

     while (FAN_EVENT_OK(metadata, len)) { 
      if (metadata->fd != FAN_NOFD) { 
       if (metadata->fd >= 0) 
       { 
        bool bCloseFdNow = true; 

        if( metadata->mask & FAN_OPEN_PERM || 
         metadata->mask & FAN_ACCESS_PERM) 
        { 
         bool bWriteNow = true; 
         struct fanotify_response response = {0,0}; 
         response.fd = metadata->fd; 
         response.response = FAN_ALLOW; 

         if(metadata->pid == self_pid) 
         {//this process event, always allow 
         } 
         else if(_this.IsReplyReadyNow(response)) 
         {//response.response is set in IsReplyReadyNow(); 
         } 
         else //else event is added to a queue, 
          //will be handled and closed later in another thread 
         { 
          bCloseFdNow = false; 
          bWriteNow = false; 
         } 

         if(bWriteNow) 
         { 
          pthread_mutex_lock(& _this.m_faWriteMtx); 
          write(_this.m_fa_fd, &response, sizeof (struct fanotify_response)); 
          pthread_mutex_unlock(& _this.m_faWriteMtx); 
         } 

        } 
        if(bCloseFdNow) 
         close(metadata->fd); 
       } 
      } 
      metadata = FAN_EVENT_NEXT(metadata, len); 
     } 
    } 

    close(_this.m_fa_fd); 
    _this.m_fa_fd = -1;  
    return NULL; 
} 

올바르게 작동합니다. 재부팅하기 전에 데몬을 중지 시키거나 모든 것을 종료해도 괜찮습니다. 하지만 시스템을 재부팅하거나 데몬이 실행중인 경우 시스템이 정지합니다.

아마도 시스템이 SIGSTOP을 재부팅/시스템 종료시 데몬으로 보내는 것일까 요? 맞습니까? 그렇다면 데몬은 모든 파일에 대한 액세스를 허용 할 수 없으며 시스템을 잠급니다.

도와주세요.

저는 커널 3.11.0에서 64 비트 우분투 12.04를 사용하고 있습니다.

+0

나는 SIGKILL이 데몬으로 보내지는 것을 본다. 나도 틀렸어. – DumbCoder

+0

그래, 나도 그렇게 생각한다. 그러나 그 사이에 데몬이 어떻게 든 잠겨 있니? – kopalvich

+0

재부팅 중에 다른 사용자 프로세스가 어떻게 중지됩니까? 어쩌면 당신은 그것을 따를 수 있습니다. Probabaly 브라우저를 열고 재부팅을 시작하십시오. – DumbCoder

답변

0

차단 된 이유를 알았습니다.

분명히 재부팅하면 리눅스는 내 데몬이 제어하는 ​​파일에 집중적으로 액세스합니다. 각각의 액세스는 _this.IsReplyReadyNow() 호출에서 허용되어야합니다.이 호출은 여러 syslog() 호출을 사용하여 파일 시스템 이벤트를 기록합니다. 내 항목의 일부 후 시스템 로그에서 다시 부팅이 메시지 온 :

내 데몬이 차단 그 후

과 'imuxsock 인해 속도 제한가 메시지를 삭제하기 시작'을 허용하는 정지 또는 파일 액세스 권한을 거부하고 시스템을 차단합니다.

syslog() 호출을 주석 처리했을 때 시스템이 마침내 재부팅되었습니다.