gpt4 book ai didi

c - 内核 : using sigqueue-functions

转载 作者:行者123 更新时间:2023-11-30 17:02:36 25 4
gpt4 key购买 nike

我尝试实现从可加载内核模块到用户应用程序的信号调用。该应用程序使用 sigaction处理信号调用,稍后它将使用 sival_int通过 switch 处理不同的操作和case .

void signalHandler_function (int signum,
siginfo_t *siginfo,
void *ucontext)
{
printf("signum: %i\n", signum);
printf("sigval: %d\n", siginfo->si_value.sival_int);
}

int main(){
int ret;
int pid = getpid();
char pidc[4];
struct sigaction sig;

memcpy(pidc,&pid,4);

// configure signal handler
sig.sa_flags = SA_SIGINFO;
sig.sa_sigaction = signalHandler_function;
sigaction(SIGIO, &sig, NULL);

g_fdCharDev = open(EXPDEV_DEVPATHNAME, O_RDWR);

printf("My process ID : %d\n", pid);
ret = write(g_fdCharDev, &pid, 1);
...
}

在内核方面,我尝试使用 send_sigqueue() (与 sigqueue_alloc()sigqueue_free() 一起)。这是在 include/linux/sched.h, line 2320 中声明的如extern并在 kernel/signal.c, line 1560 中定义。但链接器说这个函数未定义:

make -C /lib/modules/3.19.0-58-generic/build/ M=/home/alex/git/Kernel3/SignalHandling modules
make[1]: Verzeichnis »/usr/src/linux-headers-3.19.0-58-generic« wird betreten
CC [M] /home/alex/git/Kernel3/SignalHandling/ExpDev.o
Building modules, stage 2.
MODPOST 1 modules
WARNING: "sigqueue_free" [/home/alex/git/Kernel3/SignalHandling/ExpDev.ko] undefined!
WARNING: "sigqueue_alloc" [/home/alex/git/Kernel3/SignalHandling/ExpDev.ko] undefined!
WARNING: "send_sigqueue" [/home/alex/git/Kernel3/SignalHandling/ExpDev.ko] undefined!
CC /home/alex/git/Kernel3/SignalHandling/ExpDev.mod.o
LD [M] /home/alex/git/Kernel3/SignalHandling/ExpDev.ko
make[1]: Verzeichnis »/usr/src/linux-headers-3.19.0-58-generic« wird verlassen
Process terminated with status 0 (0 minute(s), 0 second(s))
0 error(s), 0 warning(s) (0 minute(s), 0 second(s))

这是 LKM 的简短源代码:

#include <linux/init.h>   /// Macros used to mark up functions e.g. __init __exit
#include <linux/module.h> /// Core header for loading LKMs into the kernel
#include <linux/device.h> /// Header to support the kernel Driver Model
#include <linux/kernel.h> /// Contains types, macros, functions for the kernel
#include <linux/fs.h> /// Header for the Linux file system support
#include <asm/uaccess.h> /// Required for the copy to user function
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/rcupdate.h>
#include <linux/slab.h>

struct siginfo *g_sig_info;
static struct sigqueue *g_sigqueue;
int g_usp_pid;
struct task_struct *g_sig_task;

static int __init expdev_init(void)
{
...
// setup signal
g_sigqueue = sigqueue_alloc();
g_sigqueue->info.si_signo = SIGIO;
g_sigqueue->info.si_signo = SI_QUEUE;
g_sigqueue->info.si_errno = 0;
...
}

static void __exit expdev_exit(void)
{
sigqueue_free(g_sigqueue);
...
}

static ssize_t dev_write(struct file *filep,
const char *buffer,
size_t len,
loff_t *offset)
{
...
memcpy(&g_usp_pid,buffer,4); // we know the PID comes with the buffer

// find task to the given PID
rcu_read_lock();
g_sig_task = pid_task(find_pid_ns(g_usp_pid, &init_pid_ns),
PIDTYPE_PID);

//send signal to user land
g_sigqueue->info.si_value.sival_int = 33;
ret = send_sigqueue(g_sigqueue, g_sig_task, 0);
...
}

为什么无法链接?难道是我的方法不对?

最佳答案

为内核模块导出的任何有用的 list_head 或函数都可以作为 System.map 文件中的地址找到。

$ sudo grep sigqueue /boot/System.map-3.19.0-58-generic
ffffffff81084880 T sigqueue_alloc
ffffffff810848b0 T sigqueue_free
ffffffff81084920 T send_sigqueue

此函数指针地址可用于本地函数:

#include <linux/init.h>   /// Macros used to mark up functions e.g. __init __exit
#include <linux/module.h> /// Core header for loading LKMs into the kernel
#include <linux/device.h> /// Header to support the kernel Driver Model
#include <linux/kernel.h> /// Contains types, macros, functions for the kernel
#include <linux/fs.h> /// Header for the Linux file system support
#include <asm/uaccess.h> /// Required for the copy to user function
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/rcupdate.h>
#include <linux/slab.h>

struct siginfo *g_sig_info;
static struct sigqueue *g_sigqueue;
int g_usp_pid;
struct task_struct *g_sig_task;

// ffffffff81084920 T send_sigqueue
int (*send_sigqueue_ptr)( struct sigqueue *,
struct task_struct *,
int group) = (void*)0xffffffff81084920;
// ffffffff81084880 T sigqueue_alloc
struct sigqueue *(*sigqueue_alloc_ptr)(void) = (void*)0xffffffff81084880;
// ffffffff810848b0 T sigqueue_free
void (*sigqueue_free_ptr)(struct sigqueue *) = (void*)0xffffffff810848b0;

static int __init expdev_init(void)
{
...
// setup signal
g_sigqueue = sigqueue_alloc_ptr();
g_sigqueue->info.si_signo = SIGIO;
g_sigqueue->info.si_code = SI_QUEUE;
g_sigqueue->info.si_errno = 0;
...
}

static void __exit expdev_exit(void)
{
sigqueue_free_ptr(g_sigqueue);
...
}

static ssize_t dev_write(struct file *filep,
const char *buffer,
size_t len,
loff_t *offset)
{
...
memcpy(&g_usp_pid,buffer,4); // we know the PID comes with the buffer

// find task to the given PID
rcu_read_lock();
g_sig_task = pid_task(find_pid_ns(g_usp_pid, &init_pid_ns),
PIDTYPE_PID);

//send signal to user land
g_sigqueue->info.si_value.sival_int = 33;
ret = send_sigqueue_ptr(g_sigqueue, g_sig_task, 0);
...
}

这仅适用于这个特殊的内核版本,并且不太可移植。是否有任何宏或其他解决方法可以获取此地址或函数?这也是编译 kernel/signal.c 的好方法吗?

如果有人知道改善这一点的方法。请随意评论和编辑。

关于c - 内核 : using sigqueue-functions,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36520957/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com