从Linux内核模块向应用发信号
有一个客户有这样的需求,要从设备驱动/内核模块向应用程序发信号,我在网上找了资料,并做了一个测试用例,证明是可行的。 这里的关键是内核模块要找到相应的应用程序的进程号, 这可以通过 ioctl 函数把应用的进程号传给内核模块。 另外, 内核模块发送信号的API 是 send_sig_info。 应用程序要注册信号处理函数, 这跟常规的做法没有区别。
这是应用程序的源码:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <sys/ioctl.h>
static sem_t event_sem;
static volatile sig_atomic_t interested_event = 0;
void sig_handler_event1(int sig)
{
interested_event = 1;
sem_post(&event_sem);
}
static void * event_handler_thread_func()
{
printf("in %s line %d\n", __func__, __LINE__);
while(1){
sem_wait(&event_sem);
if (interested_event){
printf("%s,%d, received interested_event signal.\n",__func__, __LINE__);
interested_event = 0;
}
}
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
pthread_t event_thread;
if (pthread_create(&event_thread, NULL, event_handler_thread_func, NULL) != 0){
printf("Thread create failed%s.\n", strerror(errno));
exit(1);
}
sem_init(&event_sem, 0, 0);
struct sigaction usr_action;
sigset_t block_mask;
sigfillset (&block_mask);
usr_action.sa_handler = sig_handler_event1;
usr_action.sa_mask = block_mask;//block all signal inside signal handler.
usr_action.sa_flags = SA_NODEFER;//do not block SIGUSR1 within sig_handler_int.
printf ("handle signal %d\n", SIGRTMIN+1);
sigaction (SIGRTMIN+1, &usr_action, NULL);
int fd = open("/dev/lkm_example", O_RDWR);