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`
댓글 달기