3

Here is my understanding in opening to a file for reading/writing.

In the application layer, I can invoke the fopen() function.

The fwrite() function will invoke a system call open().

After the OS receives the open() call, it will pass the command to VFS(virtual file system).

VFS looks up the file name, including any directories needed and does the necessary access checks.

If this is in RAM cache then no disk access is needed. If not, the VFS sends a read request to the specific file system which is probably EXT4.

Then the EXT4 file system driver will determine in what disk block that directory is located in. It will then send a read command to the disk device driver.


So now let's say I want to read an i2c device A attached to the board. And the file directory is /dev/i2c/A

  • Is there a major number for all devices? For example, Linux OS sets 180 as the major number for USB. So at the device side, is there a major number 180 in each USB device?

  • If the answer to 1st question is NO, then how can the Linux OS determine which type of device A is, is it just according to the file directory?

  • I think the answer to 2nd question maybe: at the boot initialization stage, there are some certain codes that have already mount that port to the file system using something like export()? So in fact, right after the booting stage, file directory /dev/i2c/A exists there and it is bind with a major number for i2c devices. So when I want to open dev/i2c/A, the OS will find the right i2c driver for me, not the SPI or USB driver.I'm not sure about this part, i need more information on this.

  • The above situation happens when the device is mounted to the file system right after the booting stage. so what happened if I have a usb, how can this usb be mounted to the file system with the right major number 180 after it is plugged in? And I guess there is a irq when the usb is plugged in before the mounting stage starts?

artless noise
  • 21,212
  • 6
  • 68
  • 105
henryyao
  • 1,758
  • 6
  • 23
  • 37
  • 1
    This question's title does not match the content. The content is about *How does Linux determine which driver will be open for a particular path in the `/dev/` tree*. The question of *what driver is selected for a device* is completely different: i.e. identification of peripherals by heuristic probing, or with help from a "plug and play" system. – Kaz Feb 21 '13 at 00:22
  • See also: [Difference between platform and normal device driver](http://stackoverflow.com/questions/15610570/what-is-the-difference-between-platform-driver-and-normal-device-driver). – artless noise Jun 06 '14 at 17:02
  • [A very similar question](https://stackoverflow.com/questions/57540366/which-is-the-most-correct-modern-way-to-create-drivers-for-i2c-devices) which was also closed. – artless noise Aug 18 '19 at 04:35

2 Answers2

9

See: hotplug doc. If you run the sample code, you can see that a netlink event is sent when a device is added/removed from USB. This is part of the driver model. Each driver should attach to a BUS; this can be platform, USB, I2C, SPI, PCI, etc. As well, with in the sysfs, there will be entries to identify the particular device. Often an I2C address can be used to identify a particular client/slave chip. The driver model also facilitates suspend, resume, ordered shutdown, etc.

The files in /dev/ are created by udev or mdevuser-space programs . They associate a name with a device node (major,minor,char/block). You can use sysfs and/or your udev script to create a device name that you want based on netlink information; most of which is available to udev scripts.

Edit: For i2c the bus master driver discovers the address of devices by running a probeNote 1. A device is associated with a particular driver with a table. For example, the stargate machine file has imote2_i2c_board_info which associates i2c addresses with drivers. A similar table exists for SPI devices. PlatformNote 2 devices are added with platform_add_devices(). USB and PCI devices are identified by similar BUS specific ids of a device. Usually a machine file (or more recently device tree) associates the two.
See Also: Linux Journal - I2C Drivers pt1, Linux Journal - I2C Drivers pt2

I believe a source of confusion is that all drivers/devices are those you see in the /dev/ directory. This is not true. Only top level drivers are seen by users. Many Linux drivers/devices are used by a master device. They can form a hierarchy of devices. Usually only the top level device is exposed to the user. There are functions such as spi_write(), that a higher level driver can use to talk via SPI, the SPI device is not exposed to user space. Sound and media/tv capture cards often use an SPI device, but the user never knows this BUS exists and is being used. Often multiple card vendors will use the same chip-sets underneath. Instead of writing drivers for every card, only some glue for the card is written. Then a generic collection of chip drivers are used with the glue to tie it all together at the top of the hierarchy; this is the top level driver that is exposed to user space. This also allows smartTM chip vendors to create good drivers that system integrators can use.

Note 1: By i2c probe, I mean an I2C message that requests all registered addresses on the bus. I am not sure if probe is the correct i2c nomenclature.

Note 2 Platform devices are SOC devices. They have no associated BUS, so platform is a catch-all. Typically, platform devices are integrated with the CPU (SOC stands for system on chip).

artless noise
  • 21,212
  • 6
  • 68
  • 105
  • one quick question, what is the platform devices? And does GPIO need a driver? – henryyao Feb 21 '13 at 01:46
  • 3
    Platform devices are `SOC` devices. They have no associated `BUS`, so platform is the catch-all for these. Typically, they are integrated with the CPU (SOC stands for *system on chip*). You don't need a `gpio` driver. There is a library for it. You can pass a `GPIO` pin to a driver (maybe an Ethernet driver wants to flash a LED). On different boards, different `GPIO` pins are used, but the Ethernet driver wouldn't care which pin, it just uses some `platform data` that is passed to it. Often, just `function pointers` are passed which will ultimately use `GPIO`, as this gives more flexibility. – artless noise Feb 21 '13 at 02:14
  • O, that's clear now. Still I'm not sure why there are some drivers having .probe function while other drivers having a different function set, such as open() write(). – henryyao Feb 21 '13 at 04:45
  • 2
    @henryyao, if a driver maintains a file somewhere (a device node, a file in debugfs or whatever else), it specifies the callbacks like `open()`, etc., in `struct file_operations` and registers that structure when it creates the file. These callbacks will be called when an application opens the file, reads from or writes to it, calls `ioctl()` for it and so on. Some drivers use that to manage the data transfer to/from user space, to adjust the parameters, etc. – Eugene Feb 21 '13 at 07:07
  • @Eugene So in which case should functions like .prob be used? Shouldn't the drivers contains .prob also have .open function? since all devices need to be opened as a file, right? – henryyao Feb 21 '13 at 14:41
  • 1
    @Henryyao. Some drivers are not public to `user space`. Most people don't want to use `i2c` directly. Typically the **top-level** device is the one with `open()`, `read()`, etc. For instance, an audio card will have an SSI interface, a codec chip and maybe lots of `GPIO`. The codec chip may use `SPI` or `I2C`; this is used to set *volume*, *mixer*, etc; `user space` does this with an `ioctl()`. The actual PCM audio data goes over `SSI`, from the main CPU memory to the codec. There are `SSI` drivers on the CPU side and these have to be hooked to the codec; these are generic. – artless noise Feb 21 '13 at 14:47
  • 1
    @Henryyao. Finally, there is a top-level machine driver that puts all of these things together. The *sound/soc* directory has common *infra-structure* for this; `user space` may talk via this *infra-structure*, but the top-level machine driver routes data/requests to different buses, etc. See: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=sound/soc/soc-io.c;hb=HEAD for sound abstraction of `I2C`/`SPI`. – artless noise Feb 21 '13 at 14:50
  • @BillPringlemeir Here is my understanding regarding your response: in a nutshell, the top level drivers have open(), write() functions accessible to user space, while the lower level drivers only have functions like .prob() and .release() that cannot be can only be used by kernels? – henryyao Feb 21 '13 at 17:18
  • @Henryyao: That seems correct, except for an extra *cannot* in the last sentence. Maybe you can take some time and edit your question? I think somethings you stated are just to show "what you do know", so people don't tell you that again? – artless noise Feb 21 '13 at 18:12
  • @BillPringlemeir Well, the thing is that the answer from you guys are too complicated for me, I'm just a newbie in the linux driver so I can only understand 50% of the answer. So I post my understanding, or you can say my guess, to see if it is correct. – henryyao Feb 21 '13 at 18:59
1

Every device has a major and minor number. You can see them by doing ls -n /dev For some drivers, like the disk, the major numbers are hard coded. For others it is dynamic. Minor numbers can be assigned dynamically as devices are discovered at runtime, not just at boot. The kernel maintains an internal device switch table that maps the dev numbers to the correct driver.

stark
  • 12,615
  • 3
  • 33
  • 50