简体   繁体   中英

Signal handling in kernel-space

I've written a program that uses SIGALRM and a signal handler.

I'm now trying to add this as a test module within the kernel.
I found that I had to replace a lot of the functions that libc provides with their underlying syscalls..examples being timer_create with sys_timer_create timer_settime with sys_timer_settime and so on.

However, I'm having issues with sigaction .
Compiling the kernel throws the following error
arch/arm/mach-vexpress/cpufreq_test.c:157:2: error: implicit declaration of function 'sys_sigaction' [-Werror=implicit-function-declaration]

I've attached the relevant code block below

int estimate_from_cycles() {
    timer_t timer;
    struct itimerspec old;

    struct sigaction sig_action;
    struct sigevent sig_event;
    sigset_t sig_mask;

    memset(&sig_action, 0, sizeof(struct sigaction));
    sig_action.sa_handler = alarm_handler;
    sigemptyset(&sig_action.sa_mask);

    VERBOSE("Blocking signal %d\n", SIGALRM);
    sigemptyset(&sig_mask);
    sigaddset(&sig_mask, SIGALRM);

    if(sys_sigaction(SIGALRM, &sig_action, NULL)) {
            ERROR("Could not assign sigaction\n");
            return -1;
    }

    if (sigprocmask(SIG_SETMASK, &sig_mask, NULL) == -1) {
            ERROR("sigprocmask failed\n");
            return -1;
    }

    memset (&sig_event, 0, sizeof (struct sigevent));
    sig_event.sigev_notify = SIGEV_SIGNAL;
    sig_event.sigev_signo = SIGALRM;
    sig_event.sigev_value.sival_ptr = &timer;


    if (sys_timer_create(CLOCK_PROCESS_CPUTIME_ID, &sig_event, &timer)) {
            ERROR("Could not create timer\n");
            return -1;
    }

    if (sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) == -1) {
            ERROR("sigprocmask unblock failed\n");
            return -1;
    }

    cycles = 0;
    VERBOSE("Entering main loop\n");

    if(sys_timer_settime(timer, 0, &time_period, &old)) {
            ERROR("Could not set timer\n");
            return -1;
    }

    while(1) {
            ADD(CYCLES_REGISTER, 1);
    }
    return 0;
}

Is such an approach of taking user-space code and changing the calls alone sufficient to run the code in kernel-space?

Is such an approach of taking user-space code and changing the calls alone sufficient to run the code in kernel-space?

Of course not! What are you doing is to call the implementation of a system call directly from kernel space, but there is not guarantee that they SYS_function has the same function definition as the system call. The correct approach is to search for the correct kernel routine that does what you need. Unless you are writing a driver or a kernel feature you don't nee to write kernel code. System calls must be only invoked from user space. Their main purpose is to offer a safe manner to access low level mechanisms offered by an operating system such as File System, Socket and so on.

Regarding signals. You had a TERRIBLE idea to try to use signal system calls from kernel space in order to receive a signal. A process sends a signal to another process and signal are meant to be used in user space, so between user space processes. Typically, what happens when you send a signal to another process is that, if the signal is not masked, the receiving process is stopped and the signal handler is executed. Note that in order to achieve this result two switches between user space and kernel space are required.

However, the kernel has its internal tasks which have exactly the same structure of a user space with some differences ( eg memory mapping, parent process, etc..). Of course you cannot send a signal from a user process to a kernel thread (imagine what happen if you send a SIGKILL to a crucial component). Since kernel threads have the same structure of user space thread, they can receive signal but its default behaviour is to drop them unless differently specified.

I'd recommend to change you code to try to send a signal from kernel space to user space rather than try to receive one. ( How would you send a signal to kernel space? which pid would you specify?). This may be a good starting point : http://people.ee.ethz.ch/~arkeller/linux/kernel_user_space_howto.html#toc6

You are having problem with sys_sigaction because this is the old definition of the system call. The correct definition should be sys_rt_sigaction . From the kernel source 3.12 :

 #ifdef CONFIG_OLD_SIGACTION
 asmlinkage long sys_sigaction(int, const struct old_sigaction __user *,
                                 struct old_sigaction __user *);
 #endif

 #ifndef CONFIG_ODD_RT_SIGACTION
 asmlinkage long sys_rt_sigaction(int,
                                  const struct sigaction __user *,
                                  struct sigaction __user *,
                                  size_t);
 #endif

BTW, you should not call any of them, they are meant to be called from user space.

You're working in kernel space so you should start thinking like you're working in kernel space instead of trying to port a userspace hack into the kernel. If you need to call the sys_* family of functions in kernel space, 99.95% of the time, you're already doing something very, very wrong.

Instead of while (1) , have it break the loop on a volatile variable and start a thread that simply sleeps and change the value of the variable when it finishes.

Ie

void some_function(volatile int *condition) {
    sleep(x);
    *condition = 0;
}

volatile int condition = 1;
start_thread(some_function, &condition);
while(condition) {
        ADD(CYCLES_REGISTER, 1);
}

However, what you're doing (I'm assuming you're trying to get the number of cycles the CPU is operating at) is inherently impossible on a preemptive kernel like Linux without a lot of hacking. If you keep interrupts on, your cycle count will be inaccurate since your kernel thread may be switched out at any time. If you turn interrupts off, other threads won't run and your code will just infinite loop and hang the kernel.

Are you sure you can't simply use the BogoMIPs value from the kernel? It is essentially what you're trying to measure but the kernel does it very early in the boot process and does it right.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM