LINUX.ORG.RU

Сообщения srman

 

Взаимодействие userspace и kernel-space через netliink сокеты

Здравствуйте, люди! Есть такое дело - организовать взаимодействие между модулем ядра и приложением, чтобы можно было в любой момент пересылать данные в обе стороны. Почитавши немного решил сделать через netlink, однако инфы маловато по этому поводу, так что есть проблемы. В общем, получился некий код, он даже частично работоспособен, однако частенько отправляет систему в корку.

Зависаем например после сообщения:knetlink_process: reply nlmsg len 1040 type 2 pid

dmesg:
knetlink_process: reply nlmsg len 1040 type 2 pid 5772                                         
Mar 24 19:41:47 jamal kernel: [43646.512847] *pde = 00000000                                                                                
Mar 24 19:41:47 jamal kernel: sys [last unloaded: scsi_wait_scan]                                                                           
Mar 24 19:41:47 jamal kernel: [43646.513081]                                                                                                
Mar 24 19:41:47 jamal kernel: [43646.513092] Pid: 2918, comm: yakuake Not tainted (2.6.32-3-686 #1) F3Ka                                    
Mar 24 19:41:47 jamal kernel: [43646.513103] EIP: 0060:[<c10ae892>] EFLAGS: 00010002 CPU: 0                                                 
....                          
Mar 24 19:41:47 jamal kernel: [43646.550269] *pde = 00000000
Либо после того, как пытаюсь выгрузить модуль. С таким же сообщением в dmesg.

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <net/sock.h>
#include <linux/socket.h>
#include <linux/net.h>
#include <asm/types.h>
#include <linux/netlink.h>
#include <linux/skbuff.h>

DEFINE_MUTEX(mut);

#define KNETLINK_UNIT 17

static struct sock * knetlink_sk = NULL;
char data_string[] = "Hello Userspace! This is msg from Kernel";

int knetlink_process( struct sk_buff * skb, struct nlmsghdr *nlh )
{
	u8 * payload = NULL;
	int   payload_size;
	int   length;
	int   seq;
	pid_t pid;

	pid = nlh->nlmsg_pid;
	length = nlh->nlmsg_len;
	seq = nlh->nlmsg_seq;
	printk("\nknetlink_process: nlmsg len %d type %d pid %d seq %d\n",
		   length, nlh->nlmsg_type, pid, seq );
	/* обработка полезной нагрузки */
	payload_size = nlh->nlmsg_len - NLMSG_LENGTH(0);
	if ( payload_size > 0 ) {
		payload = NLMSG_DATA(nlh);
		printk("\nknetlink_process: Payload is %s ", payload);
	}
        // ответ пользовательскому приложению
	struct sk_buff *rskb = alloc_skb( nlh->nlmsg_len, GFP_KERNEL );
  	if ( rskb ) {
		printk("\nknetlink_process: replies with the same socket_buffer\n");
		*rskb = *skb;
 	} else {
		printk("WTF????!!!!");
/*		skb_put( rskb, length );
		kfree_skb( skb ); 		*/
 	}
 	
	nlh = (struct nlmsghdr *)rskb->data;
 	nlh->nlmsg_len = length;
 	nlh->nlmsg_pid = pid;
 	nlh->nlmsg_flags = 0;
 	nlh->nlmsg_type = 2;
 	nlh->nlmsg_seq   = seq++;
 	payload = NLMSG_DATA( nlh );
 
//Частенько подвисаем после этого сообщения
 	printk("\nknetlink_process: reply nlmsg len %d type %d pid %d\n",
 		   nlh->nlmsg_len, nlh->nlmsg_type, nlh->nlmsg_pid );
  	NETLINK_CB(rskb).pid = 0; //from kernel
	netlink_unicast( knetlink_sk, rskb, pid, MSG_DONTWAIT );
	return 0;
}

void knetlink_input( struct sk_buff * skb)
{
	mutex_lock(&mut);
	printk("\nFunction %s() called", __FUNCTION__);

	netlink_rcv_skb(skb, &knetlink_process);

	mutex_unlock(&mut);
}

int knetlink_init( void ) //Управление передаётся при загрузке модуля
{
	if ( knetlink_sk != NULL ) {
		printk("knetlink_init: sock already present\n");
		return 1;
	}
	
	//struct sock *	netlink_kernel_create ---- это API для создания сокета из kernel_space
	knetlink_sk = netlink_kernel_create(&init_net, KNETLINK_UNIT, 0, knetlink_input, NULL, THIS_MODULE);
	
	if ( knetlink_sk == NULL ) {
		printk("knetlink_init: sock fail\n");
		return 1;
	}
// (void*)knetlink_sk
	printk("knetlink_init: sock %p\n", knetlink_sk->sk_socket);
	return 0;
}

void knetlink_exit( void )
{
	
	mutex_lock(&mut);
	if ( knetlink_sk != NULL ) {
		printk("\nknetlink_exit: release sock %p\n", knetlink_sk->sk_socket);
		kfree_skb( knetlink_sk);
	} else {
		printk("knetlink_exit: warning sock is NULL\n");
	}
	mutex_unlock(&mut);
}

module_init( knetlink_init );
module_exit( knetlink_exit );

MODULE_LICENSE("GPL");

srman
()

RSS подписка на новые темы