Netlink 예제프로그램에서 전송 실패...
글쓴이: junee74 / 작성시간: 화, 2011/08/30 - 9:25오후
netlink를 이용하여 kernel<->user간 테스트 프로그램을 작성해 보고 있습니다.
주로 kernel에서 메시지를 뿌리고, user에서 받기만 할 예정입니다.
왜 kernel에서 계속해서 메시지 전송을 실패하는지 이유를 모르겠습니다.
제가 작성한 테스트 코드는 다음과 같습니다.
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/kthread.h>
#include <linux/skbuff.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/netlink.h>
#include <net/netlink.h>
#include "netlink.h"
#define NETLINK_PROTOCOL 31
#define NETLINK_TYPE SOCK_RAW
#define NETLINK_GROUP 4
#define MAX_PAYLOAD 1024
struct sock *nl_sock = 0;
int seq_id=0;
struct task_struct *my_task = NULL;
static int netlink_test(int index)
{
struct sk_buff *skb = NULL;
struct nlmsghdr *nlh;
unsigned char *data;
int ret;
printk("%4d allocation sk_buff\n", index);
skb = alloc_skb(NLMSG_SPACE(MAX_PAYLOAD), GFP_KERNEL);
if(skb == NULL)
{
printk("fail to alloc sk_buff\n");
return -1;
}
printk("NLMSG_SPACE(MAX_PAYLOAD)=%d\n", NLMSG_SPACE(MAX_PAYLOAD));
printk("skb->len=%d\n", skb->len);
#if 1
// nlh = (struct nlmsghdr *)skb->data;
nlh = (struct nlmsghdr *)skb_put(skb, NLMSG_SPACE(MAX_PAYLOAD));
data = NLMSG_DATA(nlh);
printk("skb->len=%d\n", skb->len);
nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
nlh->nlmsg_type = 0;
nlh->nlmsg_flags = 0;
nlh->nlmsg_seq = 0;
nlh->nlmsg_pid = 0; // from kerenel
printk("copy data\n");
strcpy(data, "Notify Message from kernel!!!!");
NETLINK_CB(skb).dst_group = 1;
/*
int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, u32 pid,
u32 group, gfp_t allocation)
*/
printk("broad casting\n");
ret = netlink_broadcast(nl_sock, skb, 0, 1, GFP_KERNEL);
if(ret)
{
printk("fail to send kernel->user\n=%d\n", ret);
}
#endif
// kfree_skb(skb);
return ret;
}
static void netlink_recv(struct sk_buff *skb)
{
}
static int netlink_init(void)
{
int i = NETLINK_KOBJECT_UEVENT;
printk("create netlink socket\n");
nl_sock = netlink_kernel_create(&init_net, 31, 1, netlink_recv, NULL, THIS_MODULE);
if(nl_sock == NULL)
{
printk("fail to create netlink socket\n");
return -1;
}
netlink_set_nonroot(31, NL_NONROOT_RECV);
return 0;
}
static int netlink_close(void)
{
printk("close netlink socket\n");
netlink_kernel_release(nl_sock);
return 0;
}
static int thread_proc(void *unused)
{
// DECLARE_WAITQUEUE(wait, current);
int thread_proc_count = 0;
// int i;
msleep(100);
printk("thread start\n");
while(!kthread_should_stop())
{
thread_proc_count++;
printk("thread processing %d\n", thread_proc_count);
netlink_test(thread_proc_count);
msleep(1000);
}
printk("set current state TASK_RUNNING\n");
// __set_current_state(TASK_RUNNING);
printk("remove wait queue\n");
// remove_wait_queue(&thread_proc_wait, &wait);
return 0;
}
static int thread_start(void)
{
my_task = kthread_create(thread_proc, NULL, "%s", "my_thread");
if(my_task)
{
printk("thread start complete\n");
wake_up_process(my_task);
// wake_up(my_task);
}
return 0;
}
static int thread_terminate(void)
{
if(my_task) kthread_stop(my_task);
return 0;
}
int test_init(void)
{
int ret = 0;
printk("\n\n\n");
printk("Module Init\n");
printk("netlink init\n");
netlink_init();
printk("thread init\n");
thread_start();
/*
{
int i;
for(i=0; i<100; i++)
{
netlink_test(i);
msleep(1000);
}
}
*/
return ret;
}
void test_exit(void)
{
printk("netlink close\n");
netlink_close();
printk("thread terminate\n");
thread_terminate();
printk("Module Exit\n");
}
module_init(test_init);
module_exit(test_exit);
//MODULE_LICENSE("Dual BSD/GPL");
MODULE_LICENSE("GPL");실행 결과는 다음과 같습니다.
Module Init netlink init create netlink socket thread init thread start complete thread start thread processing 1 [ 1] allocation sk_buff NLMSG_SPACE(MAX_PAYLOAD)=1040 skb->len=0 skb->len=1040 copy data broad casting fail to send kernel->user =-3 thread processing 2 [ 2] allocation sk_buff NLMSG_SPACE(MAX_PAYLOAD)=1040 skb->len=0 skb->len=1040 copy data broad casting fail to send kernel->user =-3 thread processing 3 [ 3] allocation sk_buff NLMSG_SPACE(MAX_PAYLOAD)=1040 skb->len=0 skb->len=1040 copy data broad casting fail to send kernel->user =-3 thread processing 4 [ 4] allocation sk_buff NLMSG_SPACE(MAX_PAYLOAD)=1040 skb->len=0 skb->len=1040 copy data broad casting fail to send kernel->user =-3 thread processing 5 [ 5] allocation sk_buff NLMSG_SPACE(MAX_PAYLOAD)=1040 skb->len=0 skb->len=1040 copy data broad casting fail to send kernel->user =-3 thread processing 6 [ 6] allocation sk_buff NLMSG_SPACE(MAX_PAYLOAD)=1040 skb->len=0 skb->len=1040 copy data broad casting fail to send kernel->user =-3 thread processing 7 [ 7] allocation sk_buff NLMSG_SPACE(MAX_PAYLOAD)=1040 skb->len=0 skb->len=1040 copy data broad casting fail to send kernel->user =-3 thread processing 8 [ 8] allocation sk_buff NLMSG_SPACE(MAX_PAYLOAD)=1040 skb->len=0 skb->len=1040 copy data broad casting fail to send kernel->user =-3 thread processing 9 [ 9] allocation sk_buff NLMSG_SPACE(MAX_PAYLOAD)=1040 skb->len=0 skb->len=1040 copy data broad casting fail to send kernel->user =-3 thread processing 10 [ 10] allocation sk_buff NLMSG_SPACE(MAX_PAYLOAD)=1040 skb->len=0 skb->len=1040 copy data broad casting fail to send kernel->user =-3 thread processing 11 [ 11] allocation sk_buff NLMSG_SPACE(MAX_PAYLOAD)=1040 skb->len=0 skb->len=1040 copy data broad casting fail to send kernel->user =-3 thread processing 12 [ 12] allocation sk_buff NLMSG_SPACE(MAX_PAYLOAD)=1040 skb->len=0 skb->len=1040 copy data broad casting fail to send kernel->user =-3 thread processing 13 [ 13] allocation sk_buff NLMSG_SPACE(MAX_PAYLOAD)=1040 skb->len=0 skb->len=1040 copy data broad casting fail to send kernel->user =-3 thread processing 14 [ 14] allocation sk_buff NLMSG_SPACE(MAX_PAYLOAD)=1040 skb->len=0 skb->len=1040 copy data broad casting fail to send kernel->user =-3 netlink close close netlink socket thread terminate set current state TASK_RUNNING remove wait queue Module Exit
Forums:


netlink_broadcast()에서 반환한 에러
netlink_broadcast()에서 반환한 에러 코드가 -3입니다. /usr/include/asm-generic/errno-base.h를 보면 3은 ESRCH입니다.
~linux/net/netlink에서 ESRCH로 grep 해보면 한 군데가 잡히는데, netlink_broadcast_filtered()의 마지막 부분입니다.
그런데 info.delivered가 참이면 -ESRCH가 아니라 0을 반환합니다. 즉, 잘 전달했으면 0을 반환하고, (다른 심각한 오류가 발생한 건 아니지만) 전달은 안 됐으면 -ESRCH를 반환하는 거라고 추측할 수 있습니다.
자, 그래서... 현재 메시지를 받으려고 귀를 쫑긋 기울이고 있는 사용자 프로세스가 있는 상태인가요?
한편 커널의 다른 부분에서 netlink_broadcast()를 사용할 때 반환값을 어떻게 다루는지도 참고하실 수 있겠습니다.
$PWD `date`
댓글 달기