struct file in linux driver - c

I am currently learning how to write Linux device drivers and I have trouble understanding "struct file". I am using the book Linux Device Drivers 3rd edition to help me out.
This is what I understood.
a. struct file represents an open file thus, when open is called in the device driver module, the kernel will create a struct file that includes everything related to the device driver.
b. If you want to pass around this instance of the device driver then one has to pass a pointer to the particular struct file that was created by the kernel after open()
c. file->private_data will always return a pointer to the device.
Another question related to this is the field "f_pos". The book says that the driver can read this value if it wants to know the current position in the file. This is what I understand from it.
d. If struct foo_dev and if the total amount of memory used by this driver to store data is X then f_pos points to the current position in that block of memory reserved by the driver.
How much of what I understood is right and please correct me where I am wrong.
Thanks,
Mir

The struct file is created by the kernel and represents the kernels view of your device it allows the kernel to map from a file handle to the device.
The struct file only contains the data the kernels upper layers needs, this is unlikely to be everything you need for your driver, if you need extra storage to track your devices status (and generally you will) you need to allocate the memory for your structure yourself either in the open function or more normally when you detect your hardware.
If you do allocate storage then you can use the file->private_data to allow you to get from the struct file thats passed to your driver by read / write / etc to your structure.
How the file->private_data is used is up to the driver, the kernel doesn't touch it. Its just there for the drivers use.
The f_pos field is a legacy from the kernel using the same struct file for devices and files. It is an index into a file were the next operation will happen, it depends on your device if this makes sense, if your device supports some form of random access (say a ram device) then using f_pos and implementing lseek might make sense, if you hardware is sequential then f_pos is normally irrelevant.

This is in addition to what andrew has said ...
a) struct FILE is provided by kernel, but it is meant as an interface between kernel and one application.
b) In other words, you cannot pass around FILE structure between multiple applications for sharing a device. The only exception where it is possible to share is between parent & child processes.
To access a device or device drivers simultaneously from multiple applications, each app. shall have to call open on the device & create a FILE struct of its own. It is up to the driver whether to allow simultaneous accesses or not. Kernel has no say here.
c) private_data is exactly what it says. Data that's private to device driver. Application or library can use this field to communicate data that is very specific for the device driver.

Related

Mac OS X: How is the tcpcb struct of a TCP connection obtained by a kernel extension?

I want to provide a user space function that obtains TCP connection stats by implementing a kernel extension. From examining the TCP source, I see the tcpcp struct holds such stats. How can I, given a socket handle from user space, obtain the associated tcpcb struct via a kernel extension and return the stats to user space?
Direct answer to the question: I believe you can't get at this information from a kext without using some private headers to get the memory layout of the structs involved. This will break if/when Apple changes the layout of those structs.
However, it looks like you don't really care about the kext aspect and are happy to get the information from userspace, so have you investigated the TCPCTL_PCBLIST sysctl? This gives you the CBs for the TCP connections in the system, and the xtcpcb64 struct does contain the fields you're after. This mechanism might not be granular enough for your purposes though.

How can i call a function that written in kernel module, from the user program?

sample driver created and loaded successfully, in that a user defined function is written, it does some actions. i need to write a user program that calls the user defined function in the driver module.
need help in following cases.
How can i get access to the driver code from a user program ?.
How can i call a function that written in kernel module, from the user program ?.
thanks.
You can make your driver to react on writes (or if necessary, ioctl) to a /dev/xxx file or a /proc/xxx file. Also, you can create a new syscall, but that's more of a toy as the module would only work on custom built kernels.
Edit: try http://www.faqs.org/docs/kernel/x571.html (on character device drivers.)
It depends on what your function does, but in general:
If you want to store and show properties in the form of values (e.g. current brightness of a backlight), the standard way of doing would be using sysfs: http://kernel.org/doc/Documentation/filesystems/sysfs.txt
If you want to write/read values from a device (real or virtual), export memory or IO regions of a device to user space, or more generally control a device (e.g. setting resolution of a camera and capturing frames), you would use a character or block devices with the read/write/mmap and ioctl functions: http://luv.asn.au/overheads/chrdev-talk.html
Finally if your function just controls something from the kernel, then sysfs or procfs should be the way to go. I am not sure why people are still using procfs nowadays, except for misc devices maybe.
So in general, you need to export your kernel functions to user space through files, by defining hooks that will be called when the file is opened, read, written (to copy data from/to user space), mmap'ed (to share memory areas without copying) or when an ioctl is invoked (to perform more general control).
VDSO:
http://en.wikipedia.org/wiki/VDSO
Kernel mode Linux:
http://www.yl.is.s.u-tokyo.ac.jp/~tosh/kml/
for Qn.1:
read/write/ioctl see file_operations
for Qn.2:
1) system calls
2) driver - ioctl

connecting application with device driver

This is an interview question.
I had written device driver for a char device so I know that code structure looks like this
struct file_operations something {
.owner=my_device_open;
.read=my_device_read;
.close=my_device_close;
.write=my_device_write;
}
When the device driver is active then in
/dev/mydevice
you can actually read and write into it.
But what I was not clear is how an application will read or write to this device.
I know insmod will insert the module to kernel,and register_chrdev(); will register the driver in kernel but how will application program communicate with this driver.
Let me know what will be correct answer for it.
Well Martin Beckett summed it up. It is not really more complex,
although you could say the same with slightly more detail. Here is my
try at it:
The program performs an open("/dev/mydevice", flags) syscall, then the
kernel reads /dev/mydevice from disk. It is just an inode, with no
associated data blocks, but it holds two important pieces of
information: the major number and the minor number. From these numbers,
the kernel finds the struct file_operations that you provided through
register_chrdev(), and it calls it's .open field. It returns to the
program a file descriptor that it associated with this particular
struct file_operations. Next, when the kernel receives a syscall like
write(fd, buf, count), it will call the .write field and so on.
In unix it simply opens the device node as a file and sends/receives data and commands from it.
The beauty of Unix is that from an app's point of view there is nothing special about devices - they are just files (except for ioctls to set some modes). There is work to do in the kernel to accomodate this but that's the kernel modules problem.
Or were you asking something more complex?

Access block level storage via kernel

How to access block level storage via the kernel (w/o using scsi libraries)?
My intent is to implement a block level storage protocol over network for learning purpose, almost the same way SCSI works. Requests will be generated by initiator and sent to target (both userspace program) which makes call to kernel module and returns the data using TCP protocol to initiator.
So far, I have managed to build a simple "Hello" module and run it (I am new at kernel programming), but unable to proceed with block access.
After searching a lot, I found struct buffer_head * bread(int dev,int block) in linux/fs.h, but the compiler throws error.
error: implicit declaration of function ‘bread’
Please help, also feel free to advice on starting with kernel programming.
Thank you!
bread as used in old kernels.
Looking into struct request *blk_get_request(struct request_queue *, int, gfp_t); in linux/blkdev.h
Accessing the block device has to be accomplished via kernel.
Not a kernel developer, but a few comments:
The implicit declaration error means that the definition you've found somehow isn't in scope when you call the function. Maybe it's hidden in an #ifdef or maybe you forgot to include linux/fs.h somehow.
As far as advice on linux kernel programming, you might want to check out kernelnewbies.org.
There have been various books written on kernel programming, but be aware that the details in the kernel change very rapidly. Most of the concepts in the older books will still be valid, but at least some of the details in some areas will have changed.
Finally, you might have to brave the linux kernel mailing list. It's rather intimidating, I'm sorry to say, so try to have your questions well thought out before you post them.
A block level storage protocol is itself a fair bit of work. Perhaps you want to get the protocol in place in user space first, with the target doing direct access to, eg, /dev/sdc before diving into the kernel.
As I read your question more closely, it appears your main interest is in the storage protocol aspect of this project. If so, why do you need to modify the kernel. If you have a locally attached disk, say /dev/sdX on the target, then you can do something like this from user space:
fd = open("/dev/sdX", O_RDWR);
pwrite(fd, buf, len, offset);
pread(fd, buf, len, offset);
So, unless you're specifically interested in playing around inside the kernel, I don't think you need to do any kernel module to do a basic storage protocol between user processes.

how to acess and change variable of kernel space from user space

i,
I have posted query previously and i am repeating same I want to modify igmpv3 (Linux)
which is inbuilt in kernel2.6.-- such that it reads a value from a file and appropriately decides reserved(res 1) value inside the igmpv3 paket which is sent by a host.
I want to add more to above question by saying that this is more a generic question of changing variable
of kernel space from user space.
Thanks in advance for your help.
Regards,
Bhavin
From the perspective of a user land program, you should think of the driver as a "black box" with well defined interfaces instead of code with variables you can change. Using this mental model, there are four ways (i.e. interfaces) to communicate control information to the driver that you should consider:
Command line options. You can pass parameters to a kernel module which are then available to it during initialization.
IOCTLs. This is the traditional way of passing control information to a driver, but this mechanism is a little more cumbersome to use than sysfs.
proc the process information pseudo-file system. proc creates files in the /proc directory which user land programs can read and sometimes write. In the past, this interface was appropriated to also communicate with drivers. Although proc looks similarly to sysfs, newer drivers (Linux 2.6) should use sysfs instead as the intent of the proc is to report on the status of processes.
sysfs is a pseudo-file system used to export information about drivers and devices. See the documentation in the kernel (Documentation/filesystems/sysfs.txt) for more details and code samples. For your particular case, pay attention to the "store" method.
Depending on when you need to communicate with the driver (i.e. initialization or run time), you should add either a new command line option or a new sysfs entry to change how the driver treats the value of reserved fields in the packet.
With regard to filp_open, the function's comment is
/**
* This is the helper to open a file from kernelspace if you really
* have to. But in generally you should not do this, so please move
* along, nothing to see here..
*/
meaning there are better ways than this to do what you want. Also see this SO question for more information on why drivers generally should not open files.
You normally can't. Only structures exposed in /proc and /sys or via a module parameter can be modified from userspace.

Resources