triggering user space with kernel

前端 未结 3 704
感动是毒
感动是毒 2021-01-20 18:25

I need to send a string from kernel to a user space function without asking for it in particular from the user space, sort of triggering a function or application in the use

相关标签:
3条回答
  • 2021-01-20 18:35

    An example I used in the past was to send signal to user space from hardware interrupt in kernel space.

    KERNEL SPACE

    You have to prepare siginfo and task_struct before sending a signal:

    struct siginfo info;
    struct task_struct *t;
    
    info.si_signo = SIG_TEST;
    info.si_code = SI_QUEUE;
    info.si_int = 1234; // Any value you want to send
    rcu_read_lock();
    

    And also find the task with user space application PID. You have to send it from user-space to kernel-space through write or ioctl operations.

    t = pid_task(find_pid_ns(pid, &init_pid_ns), PIDTYPE_PID);
    

    Then you can send the signal.

    rcu_read_unlock();      
    send_sig_info(SIG_TEST, &info, t);
    

    I omitted here, but you must check the result of every operation.

    The previous code prepare the signal structure and send it. Bear in mind that you need the application's PID. In my case the application from user space send its PID through ioctl driver procedure.

    USER SPACE

    You have to define and implement the callback function:

    void signalFunction(int n, siginfo_t *info, void *unused) {
          .....
          .....  
    }
    

    In main procedure:

    struct sigaction sig;
    
    sig.sa_sigaction = signalFunction; // Callback function
    sig.sa_flags = SA_SIGINFO;
    sigaction(SIG_TEST, &sig, NULL);
    

    I hope it helps.

    0 讨论(0)
  • 2021-01-20 18:47

    Here's how my process works, I would be interested in any suggestions for improvements as well:

    1. Start the kernel module
    2. Start user space application, which sends a custom command to the kernel module to register the user space PID for kernel module signals. In my case this was via a write to /dev/mymodule. The kernel module registers the PID:

      ...
      printk("registering a new process id to receive signals: %d\n", current->pid);
      signal_pid = current->pid;
      ...
      

      The user space application also registers a handler with the kernel for certain types of signals.

      void local_sig_handler(int signum) {
              printf("received a signal from my module\n");
              fflush(stdout); }
      ...
      signal(SIGIO, local_sig_handler);
      
    3. Kernel module generates a signal

      ...
      struct siginfo info;
      struct task_struct *t;
      info.si_signo=SIGIO;
      info.si_int=1;
      info.si_code = SI_QUEUE;        
      
      printk("<1>IRQ received: %d\n", irq);
      printk("<1>searching for task id: %d\n", signal_pid);
      
      t= pid_task(find_vpid(signal_pid),PIDTYPE_PID);//user_pid has been fetched successfully
      
      if(t == NULL){
              printk("<1>no such pid, cannot send signal\n");
      } else {
              printk("<1>found the task, sending signal\n");
              send_sig_info(SIGIO, &info, t);
      }
      
    4. Kernel relays the signal to the application's handler

    0 讨论(0)
  • 2021-01-20 18:54

    You've got a few options:

    1. Signals. User process defines a signal handler, and kernel signals the user process upon receipt of an event. This works well, but requires that the handling code run in an async signal handler (which makes it trickier to write correct code). The downside is that the amount of data you can transmit using a signal handler is somewhat limited. Make sure to use a signal that can be queued (e.g. a realtime signal) so you don't lose messages when the process is in the middle of handling a signal.
    2. Blocking system call or file access. User process executes a system call (or reads/writes a file) which puts it to sleep. The kernel driver for the call maintains a queue of events, and dequeues events when they arrive and when a blocked waiter exists (this avoids losing events when the user process is unblocked).
    3. Create a system call which configures a sigevent. On the kernel side, create a sigqueue to fire the relevant events.
    0 讨论(0)
提交回复
热议问题