How to access a file in FreeBSD kernel space.

Hi all,

I want to access a binary file inside a FreeBSD kernel module. What are those API's to open, read, write and close a binary file in FreeBSD kernel space?

Thanks and regards,
 
As far as I know there are no funtions in the kernel to do this. Opening and reading files is normally done by functions in libc.
 
Couldn't you use the kernel's own file management calls to do this? After all, even libc makes system calls to the kernel. Digging through the source, I found that all the open file calls converge on the function kern_openat in the file /usr/src/sys/kern/vfs_syscalls.c. Make sure you close the file as part of your module's exit routine.
 
Maelstorm said:
Couldn't you use the kernel's own file management calls to do this? After all, even libc makes system calls to the kernel. Digging through the source, I found that all the open file calls converge on function kern_openat in the file /usr/src/sys/kern/vfs_syscalls.c. Make sure you close the file as part of your module's exit routine.

Libc is part of the user space so to speak so that's fine as far as dependencies go. The kernel on the other hand shouldn't know about the user space objects, file names in particular, it should only provide means for the user space code to handle files with the standard open(2) etc. system calls. By making the kernel aware of the user space objects and all of their intricacies you would create a circular dependency in the kernel and that's something to be avoided at all cost. "Pass the puck, never see it again" is the way it should be done.

If you want to see how dealing with files in drivers is done properly, take a look at how pf(4) uses a user space helper program pfctl(8) to read the configuration file(s) and translate them into binary data structures that are then fed to the kernel driver trough the /dev/pf device.
 
I think you have misunderstood what I was getting at. I didn't mention using libc inside the kernel, which you cannot do. Besides, at some point, libc must make the system call to the kernel to actually perform what is requested.

What I was suggesting was doing the same thing that libc does, but bypassing the wrapper functions that include the kernel space to user space string/data copying code so the call and data says within kernel space. Since the execution path is already in kernel space, you can call the implementation function directly. You will need to trace through the source and find the kernel entry-point for functions that perform open, close, read, and write though. There are two or three layers of wrapper functions involved before you get to the actual implementation of the function. If the wrapper functions are bypassed, and all the parameters are correct, the kernel does not make the distinction as to where the call came from. All it knows is that someone requested it to perform some action. To my knowledge, there is nothing that says that this cannot be done. However, in doing things this way, a programmer must perform all manipulation of data manually as the "nice" libc functions are not available. If you are reading in a text file, then the programmer must break the data up into individual lines and such as the incoming data is considered to be raw binary.

I disagree with your assessment that the kernel does not know about user space objects, files in particular. By definition, the kernel must know about files because it is the kernel that must manipulate the file to perform the requested functions such as open, close, read, write, stat, etc. Additionally, you don't even need to use functions likeopen(2). By using syscall(2), you can more or less bypass all the "nice" functions in libc and talk to the kernel directly from your application.
 
However, it is problematic for the kernel to try to access namespaces (i.e. opening a file by name). If you have a reference to a vnode, you can use vn_rdwr() to do I/O to a kernel buffer (just be sure to use UIO_SYSSPACE as the UIO segment). The trickier part is how you get access to the vnode in the first place. Ideally you have a userland program that opens a file and then invokes some sort of ioctl that passes in the FD of the file it opened. You can then use fget() to get a reference on the file from which you can gain a reference to the vnode.

If you are writing a driver that needs to load support data such as firmware, you should use be using the firmware_get() function instead of trying to open the file directly yourself.
 
Back
Top