send_sig发送信号到用户态(通用ioctrl处理)

内核态:

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/spinlock.h>
#include <linux/blkdev.h>
#include <linux/module.h>  
#include <linux/fs.h>  
#include <linux/errno.h>  
#include <linux/mm.h>  
#include <linux/cdev.h>  
#include <linux/sched.h>

/*
'k'为幻数,要按照Linux内核的约定方法为驱动程序选择ioctl编号,
应该首先看看include/asm/ioctl.h和Documentation/ioctl-number.txt这两个文件.

对幻数的编号千万不能重复定义,如ioctl-number.txt已经说明‘k'的编号已经被占用的范围为:
'k'    00-0F    linux/spi/spidev.h    conflict!
'k'    00-05    video/kyro.h        conflict!
所以我们在这里分别编号为0x1a和0x1b
*/
#define CMD_MAGIC       'k'
#define KDEV_CMD1       _IO(CMD_MAGIC, 0x1a)
#define KDEV_CMD2       _IO(CMD_MAGIC, 0x1b)
#define IO_CMD_LEN      256  
#define CHAR_DEV_NAME   "kdev"

#if 1

static int user_cmd_proc(char *user_cmd, char *out_str)
{
    if(strncmp(user_cmd, "sendsig", 7) == 0) {
        send_sig(SIGUSR1, current, 0); //send SIGUSR 1
    }
    
    if(strncmp(user_cmd, "showpid", 7) == 0) {
        sprintf(out_str, "pid=%d tgid=%d\n", current->pid, current->tgid);
    }
    
    return 0;
}
#endif

#if 1
  
int mem_open(struct inode *inode, struct file *filp)  
{  
    return 0;   
}  
  
int mem_release(struct inode *inode, struct file *filp)  
{  
    return 0;  
}  

char user_cmd[IO_CMD_LEN] = {0};
char out_str[IO_CMD_LEN] = {0};

static int mem_ioctl( struct file *file, unsigned int cmd, unsigned long arg)
{    

    printk("mem_ioctl: %d \n", cmd);    
    switch(cmd)
    {
        case KDEV_CMD1:
            if(copy_from_user(user_cmd,  (int *)arg, IO_CMD_LEN)) 
                return -EFAULT;
            user_cmd_proc(user_cmd, out_str);
            if(copy_to_user( (int *)arg, out_str, IO_CMD_LEN)) 
                return -EFAULT;
            break;
        
        case KDEV_CMD2:
            break;
    }
    
    return 0;
}

static int mem_major = 0;
struct class *pclass = NULL;  
struct cdev my_dev;   

static const struct file_operations mem_fops =  
{  
    .owner = THIS_MODULE,  
    .unlocked_ioctl = mem_ioctl,
    .open = mem_open,  
    .release = mem_release,  
};  

static int memdev_init(void)  
{  
    int result;  

    dev_t devno = MKDEV(mem_major, 0);  

    if (mem_major) { /* 静态申请设备号*/  
        result = register_chrdev_region(devno, 2, CHAR_DEV_NAME);  
    } else { /* 动态分配设备号 */  
        result = alloc_chrdev_region(&devno, 0, 2, CHAR_DEV_NAME);  
        mem_major = MAJOR(devno);  
    }   

    if (result < 0)  {  
        printk("alloc_chrdev failed!\n");  
        return result;  
    }  

    cdev_init(&my_dev, &mem_fops);  
    my_dev.owner = THIS_MODULE;  
    my_dev.ops = &mem_fops;  
    cdev_add(&my_dev, MKDEV(mem_major, 0), 2);   /*设备数2*/  

    pclass = class_create(THIS_MODULE, CHAR_DEV_NAME);  
    if (IS_ERR(pclass))  {  
        printk("class_create failed!\n");  
        goto failed;  
    }  

    device_create(pclass, NULL, devno, NULL, CHAR_DEV_NAME);  
    return 0;  

failed:   
    cdev_del(&my_dev);
    unregister_chrdev_region(devno, 1);  
    return result;  
}  
  
static void memdev_exit(void)  
{  
    device_destroy(pclass, MKDEV(mem_major, 0));  
    class_destroy(pclass);
    
    cdev_del(&my_dev);
    unregister_chrdev_region(MKDEV(mem_major, 0), 2); 
}  
#endif
  
MODULE_AUTHOR("derek yi");  
MODULE_LICENSE("GPL");  
  
module_init(memdev_init);  
module_exit(memdev_exit);  

用户态:

#include <stdio.h>  
#include <fcntl.h>  
#include <stdlib.h>  
#include <string.h>  
#include <sys/types.h>  
#include <sys/stat.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <sys/syscall.h>

#define CMD_MAGIC       'k'
#define KDEV_CMD1       _IO(CMD_MAGIC, 0x1a)
#define KDEV_CMD2       _IO(CMD_MAGIC, 0x1b)
#define IO_CMD_LEN      256  

char kdev_io_buf[IO_CMD_LEN] = {0};

void signal_handler(int signo)
{
    printf("signal_handler: %d\n", signo);
}

pid_t gettid(void)
{  
    return syscall(SYS_gettid);  
} 

int main()
{
    int fd;
    int ret = 0;

    signal(SIGUSR1, (void *)signal_handler);
    printf("main: pid=%d tid=%d \n", getpid(), gettid());
    
    fd = open("/dev/kdev", O_RDWR);
    if( fd < 0 ) {
        printf("open memdev WRONG!\n");
        return 0;
    }

    sprintf(kdev_io_buf, "sendsig");
    ret = ioctl(fd, KDEV_CMD1, kdev_io_buf);
    printf("ioctl: ret=%d rdata:%s\n", ret, kdev_io_buf);

    sprintf(kdev_io_buf, "showpid");
    ret += ioctl(fd, KDEV_CMD1, kdev_io_buf);
    printf("ioctl: ret=%d rdata:%s\n", ret, kdev_io_buf);
    
    close(fd);
    return 0;
}

测试结果:

derek@ubox:~/share/ldd6$ sudo insmod kdev.ko 
derek@ubox:~/share/ldd6$ gcc app.c 
derek@ubox:~/share/ldd6$ sudo ./a.out 
main: pid=8584 tid=8584 
signal_handler: 10
ioctl: ret=0 rdata:
ioctl: ret=0 rdata:pid=8584 tgid=8584

 

posted @ 2017-04-15 22:30  soul.stone  阅读(2649)  评论(0编辑  收藏  举报