shihyu 发表于 2016-03-16 21:30

用户空间跟内核空间沟通问题

本帖最后由 shihyu 于 2016-03-16 21:50 编辑

我代码作用是想从 用户空间 applnprocess 透过 ioctl传 用户空间 process 的 pid 到 内核 , 内核再透过 send_sig 函数不断发 SIGUSR2 给用户空间的appln prcoess , 当我不想kernel 再发SIGUSR2 signal 我再透过 ioctl 让 kernel 停止发 SIGUSR2#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/oom.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/kthread.h>
#include "header.h"

MODULE_LICENSE("Dual BSD/GPL");

static int major_no;
static int vrmonitor_pid;
static int cccc = 100;
static int send_sig_flag = 1;

static struct task_struct* brook_tsk;
static int vrmonitor_sig_handler(void* arg);

static int vrmonitor_sig_handler(void* arg)
{
    struct task_struct* p;
    struct pid* pp;

    printk(KERN_EMERG "cccc addr=%p ,cccc=%d\n", &cccc, cccc++);

    pp = find_vpid(vrmonitor_pid);
    p = pid_task(pp, PIDTYPE_PID);

    while (send_sig_flag) {
      msleep(1000);
      send_sig(SIGUSR2, p, 0);
      printk(KERN_EMERG "vrmonitor_sig_handler current pid=%d send to PID=%d \n", current->pid, vrmonitor_pid);
    }

    send_sig_flag = 1;

    return 0;
}

static int device_open(struct inode* inode, struct file* file)
{
    printk(KERN_EMERG "pid=%d, Node Opened\n", current->pid);
    return 0;
}

int device_ioctl(struct file* filp,
               unsigned int cmd,
               unsigned long args)
{
    int ret;

    switch (cmd) {
    case IOCTL_CMD:
      printk(KERN_EMERG "IOCTL_CMD");
      break;

    case IOCTL_SEND_PID:
      printk(KERN_EMERG "appln PID=%u , current kernel pid=%d\n", (unsigned int)args, current->pid);
      vrmonitor_pid = (unsigned int)args;
      brook_tsk = kthread_create(vrmonitor_sig_handler, NULL, "brook");

      if (IS_ERR(brook_tsk)) {
            ret = PTR_ERR(brook_tsk);
            brook_tsk = NULL;
            goto out;
      }

      wake_up_process(brook_tsk);
      break;

    case IOCTL_STOP_SIG:
      send_sig_flag = 0;
      printk(KERN_EMERG "IOCTL_STOP_SIG send_sig_flag=%d\n", send_sig_flag);
      break;

    default:
      printk(KERN_EMERG "Illegal ioctl command word\n");
      break;
    }

    return 0;

out:
    return ret;
}

static int device_release(struct inode* inode, struct file* file)
{
    printk(KERN_EMERG "Module Released \n");
    return 0;
}

static struct class* my_class;

static struct file_operations fops = {
    .open = device_open,
    .release = device_release,
    .unlocked_ioctl = device_ioctl
};

static int hello_init(void)
{
    major_no = register_chrdev(0, DEVICE_NAME, &fops);
    printk(KERN_EMERG "Module Major No : %d\n", major_no);

    my_class = class_create(THIS_MODULE, DEVICE_NAME);
    device_create(my_class, NULL, MKDEV(major_no, 0), NULL, DEVICE_NAME);
    printk(KERN_EMERG "Module loaded in kernel\n");
    return 0;
}

static void hello_exit(void)
{
    printk(KERN_EMERG "Device is Released or closed \n");
    device_destroy(my_class, MKDEV(major_no, 0));
    class_unregister(my_class);
    class_destroy(my_class);
    unregister_chrdev(major_no, DEVICE_NAME);
}

module_init(hello_init);
module_exit(hello_exit);
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <signal.h>
#include "header.h"

static int fd;

void stop_sig(int sig)
{
    unsigned int sig_flag = 0;

    ioctl(fd, IOCTL_STOP_SIG, sig_flag);
    printf("stop_sig=%d, pid=%d\n", sig, getpid());
    (void) signal(SIGINT, SIG_DFL);

#if 0
    kill(getpid(), SIGINT);
#endif
}


void signal_handler(int signum)
{
    printf("signal_handler %d, pid=%d\n", signum, getpid());

    if (signum == SIGUSR2) {
      printf("SIGUSR2\n");
    } else if (signum == SIGUSR1) {
      printf("SIGUSR1\n");
    }
}

int main()
{
    pid_t pid = getpid();

    printf("PID=%u\n", pid);

    signal(SIGUSR2, signal_handler);
    signal(SIGINT, stop_sig);

    fd = open(DEVICE_PATH, O_RDWR);
    if (fd == -1) {
      printf("open fail\n");
      exit(-1);
    }

    ioctl(fd, IOCTL_SEND_PID, pid);
    printf("Ioctl executed\n");

    while(1) {}

    close(fd);
    return 0;
}
运行步骤
sudo insmod sample.ko
sudo ./appln


下面是打印出来的log


// user space log
PID=6897
Ioctl executed
signal_handler 12, pid=6897
SIGUSR2
signal_handler 12, pid=6897
SIGUSR2
^Cstop_sig=2, pid=6897// ctrl + c 发往 kernel 让kernel停止发送 SIGUSR2


// kernel log
vrmonitor_sig_handler current pid=6898 send to PID=6897
vrmonitor_sig_handler current pid=6898 send to PID=6897
IOCTL_STOP_SIG send_sig_flag=0// kernel 收到准备停止
Module Released
vrmonitor_sig_handler current pid=6898 send to PID=6897



我再一般pc上运行正常 ,


可是再 vmwareubuntu kernel 只发两次 SIGUSR2 , 就打印出 Module Released
下面 log ,user space 的 applnprcoess 就莫名其妙结束 , 我还没按 ctrl+c
只是启动 sudo ./appln 这样




vrmonitor_sig_handler current pid=6898 send to PID=6897
vrmonitor_sig_handler current pid=6898 send to PID=6897
Module Released

Tinnal 发表于 2016-03-17 00:52

收到另的信号退出了呀。GDB一个就知道了呀。或者unlimit -c unlimited,产生个core文件看看

shihyu 发表于 2016-03-17 01:29

本帖最后由 shihyu 于 2016-03-17 01:29 编辑

ok... 我明天试试看 gdb
thanks
页: [1]
查看完整版本: 用户空间跟内核空间沟通问题