2016-04-09 28 views
0

Yüklenebilir bir çekirdek modülünden bir kullanıcı uygulamasına bir sinyal çağrısı yapmayı denerim. Uygulama, sinyal çağrısını işlemek için sigaction kullanır ve daha sonra switch ve case tarafından farklı eylemleri işlemek için sival_int kullanır. Çekirdek tarafındaÇekirdek: sigqueue işlevlerini kullanma

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); 
    ... 
} 

I (birlikte sigqueue_alloc() ve sigqueue_free() ile) send_sigqueue() kullanmayı deneyin. Bu, include/linux/sched.h, line 2320'da extern olarak bildirilmiş ve kernel/signal.c, line 1560'da tanımlanmıştır. Ama bağlayıcı bu fonksiyonlar tanımsız diyor: o bağlanabilir değildir Neden

#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); 
    ... 
} 

:

İşte
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 kısaltılmış kaynağını geliyor? Benim yaklaşımım yanlış mı?

+0

Çekirdek modülünde kullanılabilir olmak için, sembol ** dışa aktarılmalıdır ** (EXPORT_SYMBOL). Başlık dosyasında * extern * olarak basit tanım yeterli değildir. – Tsyvarev

+0

@Tsyvarev Evet, biliyorum. Ama işlev de tanımlanıyor. Ama neden bağlantı kurmuyor? – Alex44

+0

Modül, * verilen işlevi tanımlayan kernel/signal.c' ile derlenmiyor. Modül, yalnızca bunu bildiren başlık dosyalarını görür. Modülde *, modülün * bağlanmasıyla * benzer bir şekilde, sadece * dışa aktarılan * semboller çözülür. Bu nedenle * tanımlanmamış sembol * hatası (uyarı) - verilen fonksiyon modülünüz tarafından tanımlanmadığı gibi modpost aşamasında da çözülmez. – Tsyvarev

cevap

0

Çekirdek modülleri için dışa aktarılan yararlı bir liste_başlığı veya işlevi System.map dosyasında adres olarak bulunur.

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

Bu fonksiyon-işaretçisi-adresler yerel fonksiyonlar için kullanılabilir: Bu, bu özel Çekirdek sürümü için sadece çalışmak ve çok taşınabilir değil edecek

#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); 
    ... 
} 

. Makro veya başka bir geçici çözüm varsa bu adresleri veya işlevleri aldınız mı? kernel/signal.c'u derlemek için iyi bir yol mu? Bunu geliştirmek için herhangi bir yol bilen varsa,

Yorum yapmak ve düzenlemek için çekinmeyin.

İlgili konular