• 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
    ", 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 
    ", 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!
    ");  
            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!
    ");  
            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
    ", 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 
    ", getpid(), gettid());
        
        fd = open("/dev/kdev", O_RDWR);
        if( fd < 0 ) {
            printf("open memdev WRONG!
    ");
            return 0;
        }
    
        sprintf(kdev_io_buf, "sendsig");
        ret = ioctl(fd, KDEV_CMD1, kdev_io_buf);
        printf("ioctl: ret=%d rdata:%s
    ", ret, kdev_io_buf);
    
        sprintf(kdev_io_buf, "showpid");
        ret += ioctl(fd, KDEV_CMD1, kdev_io_buf);
        printf("ioctl: ret=%d rdata:%s
    ", 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
  • 相关阅读:
    Oracle手工增加排序区避免SQL使用临时表空间排序产生物理IO
    Oracle中"TABLE ACCESS FULL"的”欺骗时刻“
    Oracle关于12C新特性InMemory踩坑历程
    Oracle19C关于参数sec_case_sensitive_logon控制密码大小写敏感问题
    友链
    RESTful API
    不自由的自由职业
    惊了!修仙=编程??
    [Git专题] 环境搭建
    Linux系统僵尸进程详解
  • 原文地址:https://www.cnblogs.com/soul-stone/p/6716073.html
Copyright © 2020-2023  润新知