⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 netlink-exam-kern.c

📁 通过这些实例
💻 C
字号:
//kernel module: netlink-exam-kern.c
#include <linux/config.h>
#include <linux/module.h>
#include <linux/netlink.h>
#include <linux/sched.h>
#include <net/sock.h>
#include <linux/proc_fs.h>

#define BUF_SIZE 16384
static struct sock *netlink_exam_sock;
static unsigned char buffer[BUF_SIZE];
static unsigned int buffer_tail = 0;
static int exit_flag = 0;
static DECLARE_COMPLETION(exit_completion);

static void recv_handler(struct sock * sk, int length)	//消息处理函数
{
        wake_up(sk->sk_sleep);
}

static int process_message_thread(void * data)
{
        struct sk_buff * skb = NULL;
        struct nlmsghdr * nlhdr = NULL;
        int len;
        DEFINE_WAIT(wait);

        daemonize("mynetlink");

        while (exit_flag == 0) {
                prepare_to_wait(netlink_exam_sock->sk_sleep, &wait, TASK_INTERRUPTIBLE);
                schedule();
                finish_wait(netlink_exam_sock->sk_sleep, &wait); 

                while ((skb = skb_dequeue(&netlink_exam_sock->sk_receive_queue))
                         != NULL) {
                        nlhdr = (struct nlmsghdr *)skb->data;
                        if (nlhdr->nlmsg_len < sizeof(struct nlmsghdr)) {
                                printk("Corrupt netlink message.\n");
                                continue;
                        }
                        len = nlhdr->nlmsg_len - NLMSG_LENGTH(0);
                        if (len + buffer_tail > BUF_SIZE) {
                                printk("netlink buffer is full.\n");
                        }
                        else {
                                memcpy(buffer + buffer_tail, NLMSG_DATA(nlhdr), len);
                                buffer_tail += len;
                        }
                        nlhdr->nlmsg_pid = 0;
                        nlhdr->nlmsg_flags = 0;
                        NETLINK_CB(skb).pid = 0;
                        NETLINK_CB(skb).dst_pid = 0;
                        NETLINK_CB(skb).dst_group = 1;
                        netlink_broadcast(netlink_exam_sock, skb, 0, 1, GFP_KERNEL);
                }
        }
        complete(&exit_completion);
        return 0;
}

static int netlink_exam_readproc(char *page, char **start, off_t off,
                          int count, int *eof, void *data)
{
        int len;

        if (off >= buffer_tail) {
                * eof = 1;
                return 0;
        }
        else {
                len = count;
                if (count > PAGE_SIZE) {
                        len = PAGE_SIZE;
                }
                if (len > buffer_tail - off) {
                        len = buffer_tail - off;
                }
                memcpy(page, buffer + off, len);
                *start = page;
                return len;
        }

}

static int __init netlink_exam_init(void)
{
        netlink_exam_sock = netlink_kernel_create(NETLINK_GENERIC, 0, recv_handler, THIS_MODULE);//创建一个netlink的sock
        if (!netlink_exam_sock) {
                printk("Fail to create netlink socket.\n");
                return 1;
        }
        kernel_thread(process_message_thread, NULL, CLONE_KERNEL);	//创建一个内核线程来处理process_message_thread
        create_proc_read_entry("netlink_exam_buffer", 0444, NULL, netlink_exam_readproc, 0);
        return 0;
}

static void __exit netlink_exam_exit(void)
{
        exit_flag = 1;
        wake_up(netlink_exam_sock->sk_sleep);
        wait_for_completion(&exit_completion);
        sock_release(netlink_exam_sock->sk_socket);
}

module_init(netlink_exam_init);
module_exit(netlink_exam_exit);
MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -