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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM