I think it would be better to illustrate what I mean. Actually, the open()
operation itself is not important for me, since the driver does nothing on
open(). What is important are ioctl() calls that establish the calling
process's temporary ownership upon driver's internal data objects.
When 2 processes do that at the same time, it looks like this
P1: open()
P2: open()
P2: ioctl(acquire a resource) -> driver: resource_cnt--
P2: ioctl(acquire a resource) -> driver: resource_cnt--
Here P2 is forcibly terminated without calling special ioctl()s to free
the resources it has acquired but nobody issues the close() call to the
driver, though the process 2 doesn't exist anymore!!!
P1: ioctl(acquire a resource) -> driver: resource_cnt--
P1: ioctl(acquire a resource) -> driver: resource_cnt--
And now we have a situation when 4 resources are marked busy, but
Process1 uses only 2 and 2 others are stall until the P1 terminates no
matter how, but, at this time, the close() will be issued by the O/S
because the _last_ file descriptor is gone.
I would like to be able to automatically free the 2 resources when the P2
was terminated, but system doesn't give me a chance to know about the
termination (or I don't know how to ask it).
The system, FreeBSD 2.2.6, gives struct proc* to each of ioctl() and
close() calls. In described example, my close() is called only once
and sees only the ptr to P1 and never the ptr to P2.
When I planned the driver, I made the assumption that I will see close()
for each process, when the process's last file descriptor to my driver is
closed, and I planned to use struct proc* to "tag" acquired resources.
Yesterday I looked into "Linux device drivers" by A.Rubini and found out
that Linux device driver functions are given struct file* instead of
struct proc*. I'll be working on the Linux version soon, so it would be
interesting to see whether the same problem exists in Linux. I'm looking
forward to try to use struct file* for the same purpose.
In NT, there is no such problem, since O/S creates a "file object" when it
opens a device. This "file object" is process-specific and drivers always
see close( file object*) when the process dies, so the automatic cleanup
is based on using this file object* as a tag.
So, here is my problem. I might be making a principial mistake trying to
do it this way, maybe I shouldn't be a characted device driver to be able
to play a role of server for processes (with process-specific resource
allocation). If so, what should I be instead?
Thank you.
> I'm not quite sure at what you're driving at, sorry for the pun.
> But what you're probably looking for is the u as defined in
> sys/user.h. You may consider registering the u.u_procp in your
> open() and comparing them in your close(). However, this
> solution is highly un-portable, uses an undocumented interface,
> and is causing me mountains of trouble right now, since I
> haven't found a good way of getting rid of it.
> Good luck.
> : Hi All,
> : I'm writing a character dev.driver that provides services to processes.
> : The process calls open(), then several ioctl()s and finally close().
> : The driver is supposed to allow several processes to have it open at the
> : same time. The driver allocates some resources on behalf of the process
> : and then frees those resources when the process calls close(). The problem
> : is that the driver's close routine is only called when _the last_ process
> : calls close(). Thus, no cleanup is possible until the last file descriptor
> : is closed.
> : I hoped to use struct proc* parameter of driver ioctl() and close()
> : functions to "tag" and then free the resources but run into the problem.
> : What is it possible to do to receive a notification on each process
> : termination? Did I make a design error when I had planned to do it this
> : way? If so, what is the "official" way to achieve an automatic
> : process-specific cleanup?
> : Thank you,
> : Stan