17

Why is it that every function in most device drivers are static? As static functions are not visible outside of the file scope. Then, how do these driver function get called by user space applications?

Flexo
  • 87,323
  • 22
  • 191
  • 272
Yogesh R.L
  • 609
  • 7
  • 17
  • Possible duplicate of: http://stackoverflow.com/questions/12917198/linux-device-driver-program-where-the-program-starts/12923107#12923107 You are overlooking the fact that some of these static functions are used in the *operation* structure, which allow these static routines to be indirectly accessed through a standard driver interface (e.g file ops). – sawdust Jan 21 '13 at 09:16

3 Answers3

13

Remember than in C everything is addresses. That means you can call a function if you have the address. The kernel has a macro named EXPORT_SYMBOL that does just that. It exports the address of a function so that driver functions can be called without having to place header declarations since those functions are sometimes not know at compile time. In cases like this the static qualifier is just made to ensure that they are only called through this method and not from other files that may include that driver code (in some cases it's not a good idea to include driver code headers and call them directly).

EDIT: Since it was pointed out that I did not cover userspace.

Driver functions are usually not called through userspace directly (except for x86 implementation of SYSCALL instruction which does some little tricks to save the context switch sometimes). So the static keyword here makes no difference. It only makes a difference in kernel space. As pointed out by @Cong Wang, functions are usually place into a structure of function pointers so that they may be called by simply having structures point to this structure (such as file_ops, schedulers, filesystems, network code, etc...).

Jesus Ramos
  • 22,940
  • 10
  • 58
  • 88
  • "called through this method" .What is this method . you mean the EXPORT_SYMBOL macro? – sr01853 Jan 20 '13 at 09:59
  • @Sibrajas Yes, it's mostly to make sure that you don't rely on dynamic drivers (which are not always available). – Jesus Ramos Jan 20 '13 at 10:12
  • 1
    This "answer" is bogus yet has the most votes?! Exported symbols in a driver are only usable by other kernel routines, and are not accessible from user space. Just because you "know" an address does not mean a user space program can access that location. Linux is a protected kernel that uses a MMU. – sawdust Jan 21 '13 at 09:31
  • 1
    @sawdust I realize this but I'm talking about accessing from within the kernel itself. I think it's plainly obvious that you can't call a driver directly from userspace without ioctl or going through some other system call. What I'm talking about is that even though it's declared static in a file you can get the address (in the kernel) and still call the function but that isn't wise to call directly. – Jesus Ramos Jan 21 '13 at 18:22
10

Because these static function are not supposed to be used directly outside of the module. They are called by other functions in the module, among which can be the interface to an ioctl or whatever callbacks. This is why they can be called from user-space, they are just in the call path.

Take a look at the network dummy module:

dummy_dev_init() is obviously static:

static int dummy_dev_init(struct net_device *dev)
{
        dev->dstats = alloc_percpu(struct pcpu_dstats);
        if (!dev->dstats)
                return -ENOMEM;

        return 0;
}

but it is a callback of ->ndo_init() which is called when registering this network device.

static const struct net_device_ops dummy_netdev_ops = {
        .ndo_init               = dummy_dev_init,
        .ndo_uninit             = dummy_dev_uninit,
        .ndo_start_xmit         = dummy_xmit,
        .ndo_validate_addr      = eth_validate_addr,
        .ndo_set_rx_mode        = set_multicast_list,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_get_stats64        = dummy_get_stats64,
        .ndo_change_carrier     = dummy_change_carrier,
};

And obvious no one should call dummy_dev_init() directly.

Cong Wang
  • 2,001
  • 12
  • 13
2

The kernel has thousands of modules and they are (or used to be) all object files, loaded dynamically via a process similar to linking --or are actually linked-- into the executable. Can you imagine how many name clashes there would be if they were all to export all their function names, as is the default C behavior unless static is specified?

Userspace applications cannot call driver functions directly, but there are other ways to interact.

aib
  • 45,516
  • 10
  • 73
  • 79
  • By calling them directly I meant compile time method call of a specific driver without doing ioctl or registering itself as a device or something along those lines. It's always possible to just make a header or extern the functions and remove static keyword :P – Jesus Ramos Jan 21 '13 at 06:44