6672 closei (ip, rw) int *ip; { register *rip; register dev, maj; rip = ip; dev = rip->i_addr[0]; maj = rip->i_addr[0].d major; switch (rip->i_mode&IFMT) { case IFCHR: (*cdevsw[maj].d_close)(dev,rw); break; case IFBLK: (*bdevsw[maj].d_close)(dev,rw); } iput(rip); }
This example has a number of interesting features.
The declaration for “d_major” is
struct { char d_minor; char d_major; }
so that the value assigned to “maj” is the hiqh order byte of the value assigned to “dev”.
In this example, the “switch” statement has onlv two non-null cases, and no “default”. The actions for the recognised cases, e.g.
(*bdevsw[maj].d_close)(dev,rw);
look formidable
First it should be noted that this is a procedure call, with parameters “dev” and “rw”.
Second “bdevsw” (and “cdevsw”) are arrays of structures, whose “d_close” element is a pointer to a function, i.e.
bdevsw[maj]
is the name of a structure, and
bdevsw[maj].d_close
is an element of that structure which happens to be a pointer to a function, so that
*bdevsw[maj].d_close
is the name of a function. The first pair of parentheses is “syntactical sugar” to put the compiler in the right frame of mind!