next up previous
Next: Writing ioctl Callbacks Up: Using Information in fusd_file_info Previous: Registration of Multiple Devices,

The difference between device_info and private_data

As we mentioned in Section 5, the fusd_file_info structure has two seemingly similar fields, both of which can be used by drivers to store their own data: device_info and private_data. However, there is an important difference between them:

In short, device_info is used to differentiate devices. private_data is used to differentiate users of those devices.

Program 5, drums2.c, illustrates the difference between device_info and private_data. Like the original drums.c, it creates a bunch of devices in /dev/drums/, each of which ``plays'' a different sound. However, it also does something new: keeps track of how many times each device has been opened. Every read to any drum gives you the name of its sound as well as your unique ``user number''. And, instead of returning just a single line (as drums.c did), it will keep generating more ``sound'' every time a read() system call arrives.


\begin{Program}
% latex2html id marker 500\listinginput[5]{1}{drums2.c.example...
...on{drums2.c: Using both {\tt device\_info} and {\tt private\_data}}\end{Program}

The trick is that we want to keep users separate from each other. For example, user one might type:

% more /dev/drums/bam
You are user 1 to hear a drum go 'bam'!
You are user 1 to hear a drum go 'bam'!
You are user 1 to hear a drum go 'bam'!
...

Meanwhile, another user in a different shell might type the same command at the same time, and get different results:

% more /dev/drums/bam
You are user 2 to hear a drum go 'bam'!
You are user 2 to hear a drum go 'bam'!
You are user 2 to hear a drum go 'bam'!
...

The idea is that no matter how long those two users go on reading their devices, the driver always generates a message that is specific to that user. The two users' data are not intermingled.

To implement this, Program 5 introduces a new drum_info structure (lines 1-4), which keeps track of both the drum's name, and the number of time each drum device has been opened. An instance of this structure, drums, is initialized on lines 4-8. Note that the call to fusd_register (line 45) now passes a pointer to a drum_info structure. (This drum_info * pointer is shared by every instance of a client that opens a particular type of drum.)

Each time a drum device is opened, its drum_info structure is retrieved from device_info (line 15). Then, on line 18, the num_users field is incremented and the new user number is stored in fusd_file_info's private_data field. To reiterate our earlier point: device_info contains information global to all users of a device, while private_data has information specific to a particular user of the device.

It's also worthwhile to note that when we increment num_users on line 18, a simple num_users++ is correct. If this was a driver inside the kernel, we'd have to use something like atomic_inc() because a plain i++ is not atomic. Such a non-atomic statement will result in a race condition on SMP platforms, if an interrupt handler also touches num_users, or in some future Linux kernel that is preemptive. Since this FUSD driver is just a plain, single-threaded user-space application, good old ++ still works.


next up previous
Next: Writing ioctl Callbacks Up: Using Information in fusd_file_info Previous: Registration of Multiple Devices,
Jeremy Elson 2003-08-20