2015-10-09 29 views
1

我發現,關於如何從一個內核模塊發送一個實時信號到用戶空間的示例代碼here從一個內核模塊到用戶空間發送實時信號失敗

我實現它的內核模塊中,如下所示:

static int dmtimer_sendSignal(int val, int id, int sig) 
{ 
    struct siginfo info; 
    struct task_struct *t; 
    int ret; 

    ret = 0; 

    if ((id > 0) && (sig > 0)) 
    { 
     /* send the signal */ 
     memset(&info, 0, sizeof(struct siginfo)); 
     info.si_signo = sig; 
     info.si_code = SI_QUEUE; // this is bit of a trickery: SI_QUEUE is normally used by sigqueue from user space, 
            // and kernel space should use SI_KERNEL. But if SI_KERNEL is used the real_time data 
            // is not delivered to the user space signal handler function. 
     info.si_int = val;   //real time signals may have 32 bits of data. 
     info._sifields._rt._sigval.sival_int = val; 
     info.si_errno = 0; 


     rcu_read_lock(); 
    // t = find_task_by_pid_type(PIDTYPE_PID, pid); //find the task_struct associated with this pid 
     t = pid_task(find_pid_ns(id, &init_pid_ns), PIDTYPE_PID); 
     if(t == NULL) 
     { 
      printk("no such pid\n"); 
      rcu_read_unlock(); 
      return -ENODEV; 
     } 
     ret = send_sig_info(sig, &info, t); //send the signal 
     rcu_read_unlock(); 
     if (ret < 0) 
     { 
      printk("error sending signal\n"); 
      return ret; 
     } 
     else 
      printk("Send sig %d val %d pid %d\n", sig, val, id); 

    } 
    return ret; 
} 

函數dmtimer_sendSignal()從模塊中的中斷服務例程中調用。

在用戶空間:

main() 
{ 
    sigemptyset (&alarm_sig); 
    for (i = SIGRTMIN; i <= SIGRTMAX; i++) 
     sigaddset (&alarm_sig, i); 
    sigprocmask (SIG_BLOCK, &alarm_sig, NULL); 

} 

void * DATA_taskInput(void *pArg) 
{ 
    siginfo_t info; 
    int32_t input; 
    sigset_t input_sig; 
    int fd; 

    // Create digital input event 
    sig = SIGRTMIN+1; 
    sigemptyset(&gSig_input); 
    sigaddset(&gSig_input, sig); 


    // Set real time signal number for module to use 
    if (TIMER_setParm(PARM_SIGRT, SIGRTMIN + 1) < 0) 
     error(0, errno, "THREADS_events() called TIMER_setParm():"); 

    // Set PID in module 
    TIMER_setParm(PARM_PID, getpid()); 

    fd = signalfd(-1, &gSig_input, 0); 

    while(!gQuitInput) 
    { 
     sigwaitinfo(&gSig_input, &info);   // digital input event 
//  read(fd, &info, sizeof(info)); 

     printf("val = 0x%x\n", info.si_int); 
    } 

    close(fd); 

    printf("DATA_taskInput() end.\n"); 

    return NULL; 

} // end: DATA_taskInput 

用戶空間應用的PID,和實時信號數目被實現爲模塊參數和由用戶空間應用程序設置,與TIMER_setParm()。

問題是用戶空間應用程序保持阻塞等待信號(sigwaitinfo()永不返回)。我從控制檯看到的printk()調用的輸出:

「發送SIG 35 VAL XXXX PID NNNN」

與用於信號(35)和PID正確的價值觀。

如果我從用戶空間應用程序調用sigqueue()或者如果從控制檯輸入「kill -35 nnnn」,sigwaitinfo()將成功返回。

我在做什麼錯?

是否需要從工作隊列中調用dmtimer_sendSignal()?

我已經嘗試將代碼設置爲SI_KERNEL(沒有區別),解除信號(應用程序關閉)和kill_proc_info()(未找到)。

我正在使用來自Critical Link的AM335x SOM上運行的Angstrom發行版。 Angstrom版本v2012.05 - 內核3.2.0-00351-gb80917e

+0

小修正:應該用'rcu_read'節調用'send_sig_info()',它保證它的't'參數保持有效。順便說一句,在'__send_signal'實現中,[註釋](http://lxr.free-electrons.com/source/kernel/signal.c?v=3.9#L1077)表示:「實時信號必須排隊sigqueue或其他一些實時機制。它是執行定義是否kill()這樣做。「可能這是問題的根源:雖然看起來相似,但'kill'系統​​調用與'send_sig_info'內核函數不同。 – Tsyvarev

+0

感謝您的更正。然而,這一變化對結果沒有影響。用戶空間任務仍然沒有收到來自模塊的信號。 –

回答

0

我有一個類似的問題,你已經解決了。

在我的例子,

  • KernelModule:send_sig_info(SIGRTMIN)

  • UserProcess:sigaction(SIGRTMIN)(等待由sa_sigaction處理信號)

,我的真正的問題是,「UserProcess的SIGRTMIN 「與Kernel不同。

  • UserProcess的SIGRTMIN = 34內核= 32

  • SIGRTMIN所以,我改變信號編號從SIGRTMIN〜36,我成功地將其固定。

    你在內核模塊中使用了哪個信號號? SIGRTMIN? 如果您使用SIGRTMIN,我建議您更改信號編號。

    謝謝。

    Jinbum Park。

  • +0

    我使用的是35號信號。我最終使用了netlink,它允許我將數據發送到用戶空間。 –

    相關問題