netlink机制-实现系统调用

简介:
上篇文章《linux的配置接口-netlink原理和设计》展示了netlink如何完成kill系统调用,然而这个例子不足以说明netlink的强大,如果我不实现一个netlink式的系统调用,很多人是不会信服的,本文就展示一个netlink实现的read调用。
     在展示代码之前,我还是要不厌其烦的说一下netlink的优点,总的来说,netlink有以下三个优点:
1.netlink便于提供统一的入口,它的作用类似于socketcall。
2.netlink仅提供链路,和具体的控制逻辑无关,控制逻辑由消息格式决定
 
3.netlink天生就是基于消息的,而基于消息的最善于做“异步”这件事。netlink的处理可以由单独的内核线程来完成。  
     下面的例子展示如何使用netlink做异步IO操作:
   
用户态进程部分代码:
 
经过测试,完全可以使用netlink来读取文件。在以上的例子中,编写过程中遇到了一个困难,那就是use_mm和unuse_mm并不是内核的导出函数,如果想使用那就得重新编译内核,可是我不想那么做,于是只有使用一种不规范的方式,那就是想办法取到use_mm和unuse_mm函数的地址,这个恰好可以从procfs得到(要是windows,恐怕又可以在看雪论坛上长篇大论了),这个问题很简单的解决了。我的意思是说,有的时候, 80/20原则和墨菲法则  处处起作用,我们应该发挥主观能动性解决主要问题而不是被旁的问题引入歧途!比如,我们不应该想办法使内核导出use_mm函数,而是想办法使用它即可!
     另外要说的是,本例子中仅仅实现了read系统调用,诸如getpid以及open调用仍然使用标准系统调用,然而这并不是说这些一定要使用标准系统调用,鉴于本文篇幅有限,我只能列举出一个典型的系统调用-read的netlink实现,其它的系统调用用类似的方式也能实现!值得注意的是,用netlink实现read的方式中,重要的不是netlink本身,而是use_mm的调用将地址空间切换到调用进程,以便使用ptr指针,还有files的切换,以便使用fd文件描述符...
     这个例子仅仅是预研性质的,证明了可行性,还有很多地方有待改进。大致上有以下几类问题:
1.read_syscall_thread这个内核线程仅仅处理了read这个系统调用,实际上应该使它成为一个总体的分发者,分发所有的系统调用,然后将具体的工作交给工作队列  -workqueue。该内核线程中可以配置一个链表,保存所有的接收到的系统调用请求,可以来自于不同进程,然后将这些请求分发到工作队列,这样单独的请求不会阻塞整个处理流程。
2.数据结构readi应该设计成syscall_info:  
struct syscall_info {
    int syscall_num;
    char *parameter;
    ...
}
这样所有的syscall就都可以用netlink机制了。
3.同步请求和异步请求如何区分也是一个问题  ,如果是同步请求,netlink将请求分发到具体模块之后,具体处理模块的工作队列要等待其完成,如果是异步请求,netlink只需要将请求分发到具体模块,不需要等待完成,而是通过sleep/wakeup的方式进行通知,然后netlink通过一个netlink_unicast来发送完成消息,此时,用户态进程可能正在poll这个netlink。
3.用户态进程如何配合。用户态调用实际上都是异步的,所谓的同步方式此时退化成了一层封装,比如同步调用等价于以下的逻辑:
sync-call() {
    sendmsg
    recvmsg
}
而异步调用则是:
async-call() {
    sendmsg
}
这一点和PCIe总线很类似的,而且和windows的机制也是很类似,Windows本身就是异步的,它就是这样实现的,Windows是基于消息传递的。
4.基于netlink的IPC。进程1封装一个syscall_info结构体  :
struct IPC_info {
    int target_pid;
    char msg[MAX];
}
struct syscall_info {
    int syscall_num;
    char *parameter;
    struct IPC_info iinfo;
}
然后通过netlink发往内核,内核收到并解析之后,用target_pid作为netlink_unicast的参数将msg发送出去
5.由4可知,netlink虽然很和谐,然后如果要想全面使用之的话,不得不对整个系统进行全面改造,每一个用户态进程几乎都要侦听netlink,为了IPC。  
     由此可见,netlink能完成的任务很全面,包括:
1.从内核往用户态进程发送信息,比如udevd使用的sysfs的uevent 
2.从用户态往内核态具体模块发信息,比如iproute2
3.用户态执行系统调用,比如上一篇的kill系统调用的netlink实现
4.用户态执行的异步系统调用,比如上述的aio-read的netlink实现
5.用户态进程间通信,比如...这个太简单了,没有实现
 

netlink就是操作系统中所有消息的中转和分发站,可以将netlink比作系统软件中的PCIe,那么用户态进程和内核态具体处理模块就是PCIe端点,而类似上述的read_syscall_thread内核线程就是PCIe桥或者控制器,系统中总的netlink消息分发线程就类似于PCIe中的Root complex



 本文转自 dog250 51CTO博客,原文链接:http://blog.51cto.com/dog250/1271024

相关文章
|
3天前
|
网络协议 Linux C语言
用户态协议栈设计netmap实现
用户态协议栈设计netmap实现
43 0
|
3天前
|
算法 Unix Linux
进程原理及系统调用
进程原理及系统调用
|
3天前
|
存储 Linux
Linux进程间通信(mmap)
Linux进程间通信(mmap)
32 0
|
10月前
|
Unix Linux C语言
软中断通信及signal()解读
软中断通信及signal()解读
|
10月前
|
Unix Linux
进程原理及其系统调用(下)
进程原理及其系统调用
57 0
|
10月前
|
算法 Linux 调度
进程原理及其系统调用(上)
进程原理及其系统调用
93 0
|
Linux 芯片
Linux中断处理机制
中断是指在CPU正常运行期间,由于内外部事件或由程序预先安排的事件引起的CPU暂时停止正在运行的程序,转而为该内部或外部事件或预先安排的事件服务的程序中去,服务完毕后再返回去继续运行被暂时中断的程序。
Linux中断处理机制
|
Linux
Linux进程间软中断通信
Linux进程间软中断通信
167 0
Linux进程间软中断通信
|
Android开发
【Binder 机制】进程通信-正常情况 | 进程通信- mmap 内存映射 | Binder 机制重要组件
【Binder 机制】进程通信-正常情况 | 进程通信- mmap 内存映射 | Binder 机制重要组件
162 0
【Binder 机制】进程通信-正常情况 | 进程通信- mmap 内存映射 | Binder 机制重要组件
|
Linux
基于NETLINK的内核与用户空间共享内存的实现
一、前言 前些日子,开发中用到了netlink来实现内核与用户空间共享内存,写点笔记与大家分享。因为我对这块也不了解,写出来的东西一定存在很多错误,请大家批评指正~ 内核与用户空间共享内存的关键是,用户空间必须得知共享内存的起始地址,这就要求内核空间应该有一种通信机制来通知用户空间。已经有Godbach版主等人用proc文件系统实现了(可以google '共享内存 内核 用户空间'),很显然任何内核空间与用户空间的通信方法都可资利用。本文主要讲基于NETLINK机制的实现。 二、NETLINK简介 netlink在linux的内核与用户空间通信中用得很多(但具体例子我举不出,因为我不清楚~~
278 0