Character Device Driver Read/Write in Linux - c

I've written a character device driver that, I believe, should work.
I want to test the read/write functions. On another stack overflow question, apparently this can be done by writing to the device file in /dev and echoing the output.
I don't understand how this works:
When I load up my device driver by allocating a major number and calling mknod to create the file, is the file "open"? If it isn't open, then reading/writing shouldn't work like that from the command line, or so I thought?
What state is the device driver in when it has been initialized in /proc/devices and a file created in /dev?
Does this initialization need to happen before attempting to open the device file in a c program?
These answer are extremely difficult to find online, and many resources are outdated. Thanks

One good resource is Linux device driver. A shorter and simpler explanation can be found here.
When you create a file driver, you will implement some functions among file operations (fops):
open
close
read
write
seek
...
Not all function have to be implemented. If write is not implemented for instance, your device won't support writting.
When I load up my device driver by allocating a major number and calling mknod to create the file, is the file "open"?
When the /dev file is created, your module is only inited. A function like init_module is called
When the file is removed, your module is deinited. A function like module_cleanup is called.
What state is the device driver in when it has been initialized in /proc/devices and a file created in /dev?
In that case, the module is inited, the file are not open.
If it isn't open, then reading/writing shouldn't work like that from the command line, or so I thought?
When you read a file from command line, the file is open, read then closed, as a user, you don't have to care to open/close file explicitly.
Things are different if you are a C programmer, in that case, you explicitly have to open, read, close the files.
You can check that adding traces in your kernel code (using printk to print some info to kernel console, reading it with dmesg) or using strace that will trace the system calls.
Does this initialization need to happen before attempting to open the device file in a c program?
Let's resume:
The first function called will be module_init before it's called, the file doesnot exist in /dev
The last function called will be module_cleanup after it's called, the file doesnot exist in /dev
between init and cleanup, you can call the different open, close, read and write function.
Generally read/write are called between open and close.

Related

Device xxx_init not getting called

I wrote a simple stream driver to learn device drivers, in that i am just having DLLEntry, Init and DeInit functions and also I have exported all the functions in a .def file .
I also added the registry settings for the driver in HKLM/Drivers/Sample.
I wrote a application to test its working, where i called ActivateDeviceEx with the following path .
My DLLEntry function is getting called, but Init function is not getting called. I am using RETAILMSG macros to print the debug information.
I also have seen the post 1 where he is also facing the same issue
But i dont understood what we have to do for it to work...
The fact that DllEntry gets called but Init does not hints at an issue with the function exports. A stream driver must export at least the following:
Init
Deinit
Open
Close
Read
Write
Seek
IOControl
Also, unless the Flags value in the registry includes DEVFLAGS_NAKEDENTRIES, each function must be prefixed with the device name, so if the driver supports, say, an XYZ device, the functions must be named XYZ_Init, XYZ_Deinit, etc.

get linux file system information via kernel function

I have to write a linux module and I can't find a proper function to list all mounted file system and their information. I know command "df -T" can achieve this and sadly I can't use that. Is there a kernel function that can do this or other way?
Why not see the kernel code which fills /proc/mounts
mountstats_open() in base.c
refer get filesystem mount point in kernel module
Your code could open/read the /proc/mounts file, line by line. It contains everything that is mounted, including many mount points that you would not expect.
In general, the format is the same as the /etc/fstab file, but will also include all the mounts that the OS adds.

error: asm/uaccess.h: No such file or directory

I'm running linux kernel no. 2.6.15.51 on a ubuntu system.
I created a custom system call and added it to the kernel (containing a struct), compiled, and booted into the new kernel. Now I'm trying to create a c file that calls that system call (for testing purposes). Because I have a struct declared in my system call file, I am including the header in my test file so I can use that same struct. However, when I try including my system call file (which makes a call to access_ok() method), I get an error saying asm/uaccess.h (the file where access_ok() is declared) does not exist. Any ideas why I could be having this problem? Thank you!

Possible reasons of linux open call returning EINVAL

I am trying to make a system call in my source code as follows.
int file;
file = open(argv[index], O_RDONLY);
Where the command line arguement is a path to a binary file in my filesystem. But this call throws me an EINVAL error. I have checked the existence of file and the required permissions to access it.
Any suggestions on what circumstances the EINVAL error will be thrown out.
The official documentation suggests that this is because your implementation of open() does not support synchronized IO for the file you are trying to open.
Cause of failure:
There were two processes say (process-1 and process-2) that were executing in close sequel and was trying to open this binary file. Since my system (embedded device) will crash after this open call, the debugs splitted out weren't proper and it made me to suspect the process-1. But the actual culprit is process-2 who was opening the binary with O_RDWR flag. But my file system (network mount) was mounted as "read only file system".
Points to be taken care:
Refining the perror prints it should be the right cause of the problem as "Read Only File System". So my initial perror description must be a uncleared value of any of the previous erroneous call. One learning here is to use perror with care, so as avoid analysing misleading error message.
Possible circumstances the EINVAL error will be thrown out:
The open call will show an EINVAL if we use O_SYNC (or) related flags for the file which we are not supposed to use. I conclude this based on the documentation as previously mentioned by Rafe.
If you are sure that argv[index] actually contains the filename and that O_RDONLY hasn't been overridden somehow (O_RDONLY should equal 0), check your system log via the dmesg command and make sure that nothing funky has happened in-kernel.

Where would a driver "output" to if using printf?

If I were to create a driver, which, say hooks the windows function for opening a file. If in my driver I told the hook to printf("something"), when the driver is switched on and I opened a file, where would printf display the text to?
If you want to output text from a driver for debugging and experimental purposes, use DbgPrintEx. The output can be viewed via Sysinternals DebugView or a debugger.
printf is written to the stream stdout which is declared in stdio.h. It is opened the first time you touch one of the standard streams stdin, stdout, stderr. The standard streams stdin, stdout, and stderr are macros that call a stdio library function which opens the streams and returns an array those streams. The macro definitions index the array to get the right stream out. If the application has no console, the output goes to the "null" device.
You can view the debug output of your driver (compiled with debug config)
using DbgView
or WinDbg utility available on microsofts website
also to give print statements you could use following functions defined in wdm.h
DbgPrint(...)
DbgPrintEx(...)

Resources