linux内核态 send_sig_info/kill_fasync 向用户态发送数据

内核态程序

关键函数

send_sig_info 发送带kernel_signalinfo 

kill_fasync 仅发送sigurse1 信号不能发送参数(需要用户端使用 read 来读取);

#include <linux/types.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/ioctl.h>
#include <linux/signal.h>
#include <linux/interrupt.h>

//#include <linux/netdevice.h>
//#include <net/sock.h>
#include <linux/sched/signal.h>


#define SIGETX 44

#define MEM_SIZE 256
#define MEM_NAME "mem"

typedef struct fasync_str
{
	/* data */
	int pid;
	int uid;
	int data;	
}fasync_str;

__user fasync_str  fs;



struct mem_dev
{
	struct cdev dev;
	char mem[MEM_SIZE];
	int length;
	struct fasync_str fstruct;
	struct fasync_struct *async_queue;
};
static struct mem_dev *mem_dev_p;
static dev_t mem_devno;
static struct class *mem_class;


static ssize_t mem_read(struct file *filp, char __user *buf, size_t count, loff_t *pos)
{
	struct mem_dev *dev_p = filp->private_data;

	if (copy_to_user(buf, &dev_p->fstruct, count))
	{
		return -EFAULT;
	}
	return count;
}


static ssize_t mem_write(struct file *filp, const char __user *buf, size_t count, loff_t *pos)
{
	struct mem_dev *dev_p = filp->private_data;
	

	if (copy_from_user(&dev_p->fstruct, buf, count))
	{
		return -EFAULT;
	}
	
	printk("write %d %d %d SIGUSR1 %d \n", ((fasync_str*)buf)->pid, ((fasync_str*)buf)->uid, ((fasync_str*)buf)->data, SIGUSR1);
	if (dev_p->async_queue)
	{
		//kill_fasync(&dev_p->async_queue, SIGUSR1, POLL_IN);
		printk("kill_fasync \n");
		
		//struct siginfo info;

		((fasync_str*)buf)->data = 900;

		fs.data = 9001;
		fs.pid = 189;
		fs.uid = 90;

		struct kernel_siginfo info;
		memset(&info, 0, sizeof(struct kernel_siginfo));
		info.si_signo = SIGETX;
		info.si_code = SI_QUEUE;
		info.si_ptr = buf;
		
		printk("size kernel_siginfo %d\n", sizeof(struct kernel_siginfo));
		//info.si_ptr = &fs;


		static struct task_struct *task = NULL;
		struct pid *user_pid = dev_p->async_queue->fa_file->f_owner.pid;
		rcu_read_lock();
		//task = pid_task(find_vpid(((fasync_str*)buf)->pid), PIDTYPE_PID);
		task = pid_task(user_pid, PIDTYPE_PID);
		rcu_read_unlock();
		//printk("pid = %d \n", ((fasync_str*)buf)->pid);
		
		send_sig_info(SIGETX, &info, task);
		//struct task_struct *p;
		//send_sig(SIGUSR1, task, 0);

		//send_signal();

	}

	return count;
}



static int mem_fasync(int fd, struct file *filp, int mode)
{
	struct mem_dev *dev_p = filp->private_data;
	printk("mem_fasync \n");
	return fasync_helper(fd, filp, mode, &dev_p->async_queue);
}


static int mem_open(struct inode * inode , struct file * filp)
{
	filp->private_data = mem_dev_p;
	return 0;
}


static int mem_release(struct inode * inode, struct file *filp)
{
	printk("mem_release \n");
	mem_fasync(-1, filp, 0);
	return 0;
}


static const struct file_operations mem_fops = 
{
	.owner = THIS_MODULE,
	.open = mem_open,
	.release = mem_release,
	.read = mem_read,
	.write = mem_write,
	.fasync = mem_fasync,
};


static int __init my_mem_init(void)
{
	int ret;
	ret = alloc_chrdev_region(&mem_devno, 0, 1, MEM_NAME);
	if (ret)
	{
		goto out_1;
	}

	mem_dev_p = kmalloc(sizeof(struct mem_dev), GFP_KERNEL);
	if (NULL == mem_dev_p)
	{
		ret = -ENOMEM;
		goto out_2;
	}
	
	memset(mem_dev_p, 0, sizeof(struct mem_dev));

	cdev_init(&mem_dev_p->dev, &mem_fops);
	mem_dev_p->dev.owner = THIS_MODULE;
	mem_dev_p->dev.ops = &mem_fops;
	ret = cdev_add(&mem_dev_p->dev, mem_devno, 1);
	if (ret)
	{
		goto out_3;
	}

	mem_class = class_create(THIS_MODULE, "mem_fasync");
	device_create(mem_class, NULL, mem_devno, NULL, "mem_fasync");

	printk("mem_init\n");
	return 0;

out_3: kfree(mem_dev_p);
out_2: unregister_chrdev_region(mem_devno, 1);
out_1: return ret;
}


static void __exit my_mem_exit(void)
{
	device_destroy(mem_class, mem_devno);
	class_destroy(mem_class);

	cdev_del(&mem_dev_p->dev);
	kfree(mem_dev_p);
	unregister_chrdev_region(mem_devno, 1);

	printk("mem_exit\n");
}

MODULE_LICENSE("Dual BSD/GPL");
module_init(my_mem_init);
module_exit(my_mem_exit);

用户态程序

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




#define DATA_WIDTH               10
#define DATA_HEIGHT              5
#define DATA_SIZE                (DATA_WIDTH *   DATA_HEIGHT)


#define SIGETX 44

int fd = -1;

typedef struct fasync_str
{
	/* data */
	int pid;
	int uid;
	int data;	
}fasync_str;

struct fasync_str fstruct;


void sig_event_handler(int n, siginfo_t *info, void *unused)
{
    if (n == SIGETX) {
        //int check = info->si_int;
		struct fasync_str *fs;
		fs = info->si_ptr;
		printf("sizeof(siginfo_t) %lu \n", sizeof(siginfo_t));
        //printf ("Received signal from kernel : Value =  %d\n", check);
		printf ("Received signal from kernel :pid %d uid %d data %d\n",fs->pid, fs->uid, fs->data);
    }
}

#if 0

void catch_sigio(int signu)
{
	printf("catch signo\n");
	struct fasync_str fs;
	memset(&fs, 0, sizeof(fs));
	printf("org pid %d uid %d data %d\n", fs.pid, fs.uid, fs.data);
	#if 1
	int res = read(fd, &fs, sizeof(fs));
	if(res != sizeof(struct fasync_str))
	{
		printf("read error \n");
		return;
	}
	printf("read pid %d uid %d data %d\n", fs.pid, fs.uid, fs.data);
	#endif 
}
#endif

int main(void)
{

	struct sigaction act;
	sigemptyset(&act.sa_mask);
    act.sa_flags = (SA_SIGINFO | SA_RESTART);
    act.sa_sigaction = sig_event_handler;
    sigaction(SIGETX, &act, NULL);

#if 0
	if (SIG_ERR == signal(SIGUSR1, catch_sigio))
	{
		printf("signal failed\n");
		return -1;
	}
#endif 
	fd = open("/dev/mem_fasync", O_RDWR|O_NONBLOCK);
	if (-1 == fd)
	{
		perror("open");
		return -2;
	}
	printf("open success\n");

	fcntl(fd, F_SETOWN, getpid());
	// *******--------------特别关键-----------------------*************
	// 1. 应用空间在使用除 SIGIO 信号后,需调用函数 fcntl(fd, F_SETSIG, SIGUSR1),部分头文件没有包含 F_SETSIG 宏定义,其值为10。
	fcntl(fd, 10, SIGUSR1); 
	int flags = fcntl(fd, F_GETFL);
	fcntl(fd, F_SETFL, flags | O_ASYNC);


	while (1)
	{
		printf("while \n");
		static int num = 0;
		num++;
		sleep(1);
		printf("wait...%d ", num);
        //continue;
		if(num %10 == 0)
		{
			fstruct.pid = getpid();
			fstruct.uid = 99;
			fstruct.data = 101;
			
            int size = write(fd, &fstruct, sizeof(fstruct));


			printf("===11== size=%d\n", size);
		}	
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值