我發現,關於如何從一個內核模塊發送一個實時信號到用戶空間的示例代碼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
小修正:應該用'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
感謝您的更正。然而,這一變化對結果沒有影響。用戶空間任務仍然沒有收到來自模塊的信號。 –