在内核空间中存储结构体数组,Linux
我相信我可能有点过度思考这个问题...我的文件系统上有一个文本文件,我在启动时解析该文件并将结果存储到结构数组中。我需要将此数组从用户空间复制到内核空间(copy_from_user),并且必须让内核随时可以访问此数据。内核空间中的数据需要通过 Sockets.c 文件来访问。内核空间中是否有一个特殊的位置来存储数组,或者我可以简单地在 Sockets.c 中添加对数组的引用吗?我的 C 有点生锈了...
谢谢你的建议。
I believe I may be over-thinking this problem a bit... I've got a text file located on my filesystem which I am parsing at boot and storing the results into an array of structs. I need to copy this array from user space into kernel space (copy_from_user), and must have this data accessible by the kernel at any time. The data in kernel space will need to be accessed by the Sockets.c file. Is there a special place to store an array within kernel space, or can I simply add a reference to the array in Sockets.c? My C is a bit rusty...
Thanks for any advice.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我相信您的问题有两个主要部分:
将数据从用户空间传递到内核空间
将数据存储在内核空间中
对于第一个问题,我建议使用 Netlink 套接字,而不是更传统的系统调用(读/写/ioctl)接口。 Netlink 套接字允许使用类似套接字的接口将配置数据传递到内核,这使用起来更加简单和安全。
您的程序应该执行所有输入解析和验证,然后将数据传递到内核,最好以比大量数据 blob 更结构化的形式(例如逐项)。
除非您对高吞吐量(每秒兆字节数据)感兴趣,否则 netlink 接口就很好。以下链接提供了说明以及示例:
http://en.wikipedia.org/wiki/ Netlink
http://www.linuxjournal.com/article/7356
http://linux-net.osdl.org/index.php/Generic_Netlink_HOWTO
http://www.kernel.org/doc/Documentation/connector/
就数组而言存储方面,如果您计划存储超过 128KB 的数据,则必须使用 vmalloc() 来分配空间,否则首选 kmalloc()。您应该阅读《Linux 设备驱动程序》一书的相关章节:
http://lwn.net/ images/pdf/LDD3/ch08.pdf
请注意,使用 vmalloc() 分配的缓冲区不适合与设备进行 DMA 传输,因为内存页面不连续。如果您事先不知道有多少条目,您可能还需要考虑更复杂的数据结构,例如列表。
至于全局访问存储,您可以像使用任何 C 程序一样进行操作:
在您需要访问数据的所有 .c 文件包含的头文件中,放置如下内容:
extern
关键字表明这声明了一个在另一个源文件中实现的变量。这将使包含该标头的所有 C 文件都可以访问该指针。然后在一个 C 文件中,最好是包含其余代码的文件 - 如果存在:
这是头文件中声明的变量的实际实现。
PS:如果你要使用 Linux 内核,你真的需要温习你的 C 语言。否则你将会经历一些非常令人沮丧的时刻,并且最终会感到抱歉和痛苦。
PS2:如果您至少浏览整本 Linux 设备驱动程序书籍,您还将节省大量时间。尽管它的名称和相对年龄,它包含许多在为 Linux 内核编写任何代码时既最新又重要的信息。
I believe there are two main parts in your problem:
Passing the data from userspace to kernelspace
Storing the data in the kernelspace
For the first issue, I would suggest using a Netlink socket, rather than the more traditional system call (read/write/ioctl) interface. Netlink sockets allow configuration data to be passed to the kernel using a socket-like interface, which is significantly simpler and safer to use.
Your program should perform all the input parsing and validation and then pass the data to the kernel, preferably in a more structured form (e.g. entry-by-entry) than a massive data blob.
Unless you are interested in high throughput (megabytes of data per second), the netlink interface is fine. The following links provide an explanation, as well as an example:
http://en.wikipedia.org/wiki/Netlink
http://www.linuxjournal.com/article/7356
http://linux-net.osdl.org/index.php/Generic_Netlink_HOWTO
http://www.kernel.org/doc/Documentation/connector/
As far as the array storage goes, if you plan on storing more than 128KB of data you will have to use vmalloc() to allocate the space, otherwise kmalloc() is preferred. You should read the related chapter of the Linux Device Drivers book:
http://lwn.net/images/pdf/LDD3/ch08.pdf
Please note that buffers allocated with vmalloc() are not suitable for DMA to/from devices, since the memory pages are not contiguous. You might also want to consider a more complex data structure like a list if you do not know how many entries you will have beforehand.
As for accessing the storage globally, you can do it as with any C program:
In a header file included by all .c files that you need to access the data put something like:
The
extern
keyword indicates that this declares a variable that is implemented at another source file. This will make this pointer accesible to all C files that include this header.Then in a C file, preferrably the one with the rest of your code - if one exists:
Which is the actual implementation of the variable declared in the header file.
PS: If you are going to work with the Linux kernel, you really need to brush up on your C. Otherwise you will be in for some very frustrating moments and you WILL end up sorry and sore.
PS2: You will also save a lot of time if you at least skim through the whole Linux Device Drivers book. Despite its name and its relative age, it has a lot of information that is both current and important when writing any code for the Linux Kernel.
您可以在内核中的某个位置定义一个
extern
指针(例如,在您要使用它的sockets.c
文件中)。将其初始化为 NULL,并在某个适当的头文件中包含它的声明。在执行
copy_from_user()
的代码部分中,使用kmalloc()
为数组分配空间,并将地址存储在指针中。将数据复制到其中。您还需要锁定一个互斥锁来访问数组。由
kmalloc()
分配的内存将持续存在,直到使用kfree()
释放为止。You can just define an
extern
pointer somewhere in the kernel (say, in thesockets.c
file where you're going to use it). Initialise it toNULL
, and include a declaration for it in some appropriate header file.In the part of the code that does the
copy_from_user()
, allocate space for the array usingkmalloc()
and store the address in the pointer. Copy the data into it. You'll also want a mutex to be locked around access to the array.The memory allocated by
kmalloc()
will persist until freed withkfree()
.您的问题非常基本且模糊,因此我建议您完成本书中的一些练习。第 8 章的全部内容都致力于分配内核内存。
Your question is basic and vague enough that I recommend you work through some of the exercises in this book. The whole of chapter 8 is dedicated to allocating kernel memory.
将数组初始化为内核模块中的全局变量将使其永远可以访问,直到内核正在运行,即直到您的系统正在运行。
Initializing the Array as a global variable in your Kernel Module will make it accessible forever until the kernel is running i.e. until your system is running.