内核态程序
关键函数
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;
}