ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
In a kernel driver I am writing, I have a need to maintain context information pertaining to multiple users who may be simultaneously using the driver.
I have decided that the easiest way to maintain this context information is by tracking the file handles associated with userspace open() or fopen() calls. In fact, I don't really see another way to do it; the file handle information is all I have to reliably go by. However there is a high wall between kernel space and user space, and I am having a lot of trouble figuring out how to get the necessary information across that wall.
Now, these open files are device files, and the basic problem is this. After opening a device file, the userspace applications often have a need to send commands to the driver to configure the device in a specific fashion. Further, this configuration may and usually will vary from userspace application to userspace application AT THE SAME TIME, and when the driver talks to the device for the user, it has to configure it properly for what that user wants to do.
My problem is that the open() and fopen() commands are defined by the system in terms of what they do, and I need a way to relate the file handle that is returned in the userspace application to the file handle the kernel maintains so that when the userspace application sends a command it can also send along the file handle so that the kernel driver knows what user is configuring it.
I cannot use inodes because multiple users might have the same device file open; they would show the same inodes.
I have been writing some test code to traverse the kernel file structure, looking for useful information, but there are a lot of sub-structures and sub-sub-structures under it, and so far I have not found useful information.
Someplace in the kernel, the file handle returned to a userspace application is related to the file structure that is kept in the kernel. This relationship might include the PID of the userspace process; I don't know, but I could deal with that.
Does anyone here know where that information is kept?
I think kernel is not the place where you will find the user FILE struct that you might be looking for, glibc is the place, as the struct FILE that is is typedef'd to _IO_FILE contains the file descriptor, _fileno as a member, that gets returned when fopen calls open() internally.
kernel maintains struct file (lowercase), as I am sure you must have figured out, and each fd has its mapping struct file when open is used.
My assumptions to your driver is that, for every file handle, there is one corresponding device? or there is only one device, and many applications are accessing it at the same time? If it is the later case, have you consider mutual exclusions? since you said may applications can configure it at the same time? or am I just mistaken this phrase?
Quote:
from userspace application to userspace application AT THE SAME TIME
I think you can use the inode, perform an ioctl with process id as your argument (can be in a struct with other information you need)
Code:
struct pid_t {
int num;
/* other info */
}
in app:
pid_t pid;
pid.num = getpid();
ioctl(fd, IOCTL_KNOW_USER, &pid);
in kernel driver:
my_fops.ioctl = my_ioctl;
my_ioctl(struct.... )
{
...
case IOCTL_KNOW_USER:
pid_t tmp;
copy_from_user(&tmp, __user &arg, ...)
...
}
sorry I forgot the syntax of copy_from_user. But I hope you get my point.
file->fown_struct in kernel contains the pid information, you might want to get that information back to user space. My only question is ; how does this help you? If I understand the question correctly, it means to say that different processes might have configured the device in different manners, how does the driver know which process should get what services.
So either have a filter in the user-space that knows what it is asking for and then deciding if it should use it (bad idea), or the driver in kernel space should know as to what capabilities/services are being configured for a particular process.
This should be do-able, as you can map just the pid to capabilities.
My assumptions to your driver is that, for every file handle, there is one corresponding device? or there is only one device, and many applications are accessing it at the same time? If it is the later case, have you consider mutual exclusions? since you said may applications can configure it at the same time? or am I just mistaken this phrase?
One device, many users. No mutual exclusions; this is real-time and on the fly, and the driver has to handle configuration issues to satisfy each user. I have built that capability into it, but am trying to find a way to uniquely identify the users. I can use PID so long as I can also uniquely identify the open() or fopen() with that PID.
file->fown_struct in kernel contains the pid information, you might want to get that information back to user space. My only question is ; how does this help you? If I understand the question correctly, it means to say that different processes might have configured the device in different manners, how does the driver know which process should get what services.
Well now, that is the problem. I have defined a user_context structure that the driver maintains with all information for this user in it. When the user does a read() for instance, the driver identifies the user, checks the context struct, configures the device, reads the data, and returns it. The issue is that the read() command leads to a pointer to a kernel file structure being passed into the driver's read routine, and somehow I need to extract information from that file structure that lets me identify the user uniquely.
I believe you meant to say that file->f_owner contains PID information (f_owner is type fown_struct), but the member file->f_owner.pid contains a zero when I look at it.
Quote:
So either have a filter in the user-space that knows what it is asking for and then deciding if it should use it (bad idea), or the driver in kernel space should know as to what capabilities/services are being configured for a particular process.
This should be do-able, as you can map just the pid to capabilities.
Well, that is the idea. But when I find a zero for the pid in that member, I find myself at a bit of a loss.
specifically, the line:
printk("<1> PID is %x\n",filp->f_owner.pid);
is returning "PID is 0" when placed at the bottom of the driver's open routine, just ahead of the return statement.
cant you just use "current" macro to get the pid? I mean, the read calls have to be in process context, and current should give you the calling process' PID. This unless I am missing something. Another way to get this info could be to do an fcntl from each process to set owner for that 'struct file'. like so :
Code:
fcntl(filedesc,F_SETOWN, getpid());
I found it to work, you can use the wrapper inline functions to get the pids from the struct pid:
Code:
pid_nr(fi->f_owner.pid)
which returns pid_t. I found this to give me the pid.
I hope this is something that you are looking for.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.