http://blog.chinaunix.net/u1/38994/showart.php?id=1348852
init
= > handle_device_fd 收到uevent信息
= > handle_device_event
= >
static void handle_device_event( struct uevent * uevent)
{
. . .
/* are we block or char? where should we live? */
if ( ! strncmp ( uevent- > path, "/block" , 6) ) {
block = 1;
base = "/dev/block/" ; //根据uevent路径改变该节点路径
mkdir( base, 0755) ;
} else {
block = 0;
/* this should probably be configurable somehow */
if ( ! strncmp ( uevent- > path, "/class/graphics/" , 16) ) {
base = "/dev/graphics/" ; // 根据uevent路径
改变该uevent需要创建节点的路径
mkdir( base, 0755) ;
} else if ( ! strncmp ( uevent- > path, "/class/oncrpc/" , 14) ) {
base = "/dev/oncrpc/" ;
mkdir( base, 0755) ;
} else if ( ! strncmp ( uevent- > path, "/class/adsp/" , 12) ) {
base = "/dev/adsp/" ;
mkdir( base, 0755) ;
} else if ( ! strncmp ( uevent- > path, "/class/input/" , 13) ) {
base = "/dev/input/" ; // 根据uevent路径
改变该uevent需要创建节点的路径
mkdir( base, 0755) ;
} else if ( ! strncmp ( uevent- > path, "/class/sensors/" , 15) ) {
base = "/dev/sensors/" ;
mkdir( base, 0755) ;
} else if ( ! strncmp ( uevent- > path, "/class/mtd/" , 11) ) {
base = "/dev/mtd/" ; // 根据uevent路径
改变该uevent需要创建节点的路径
mkdir( base, 0755) ;
} else if ( ! strncmp ( uevent- > path, "/class/misc/" , 12) & &
! strncmp ( name, "log_" , 4) ) {
base = "/dev/log/" ; // 根据uevent路径
改变该uevent需要创建节点的路径
mkdir( base, 0755) ;
name + = 4;
} else if ( ! strncmp ( uevent- > path, "/class/sound/" , 13) ) {
base = "/dev/snd/" ;
mkdir( base, 0755) ;
} else
base = "/dev/" ;
}
snprintf( devpath, sizeof ( devpath) , "%s%s" , base, name) ;
if ( ! strcmp ( uevent- > action, "add" ) ) {
make_device( devpath, block, uevent- > major, uevent- > minor) ; //创建节点文件文件devpath
return ;
}
. . .
}
static void make_device( const char * path, int block, int major, int minor)
{
unsigned uid;
unsigned gid;
mode_t mode;
dev_t dev;
if ( major > 255 | | minor > 255)
return ;
mode = get_device_perm( path, & uid, & gid) | ( block ? S_IFBLK : S_IFCHR) ; //获取将要创建的节点是否需要重设它的mode数值
dev = ( major < < 8) | minor;
mknod( path, mode, dev) ;
chown( path, uid, gid) ;
}
get_device_perm函数会比较path路径是否和下面的devperms[ ] 数组中的inode路径相一致, 如果一致, 那么返回devperms[ ] 数组中指定的uid, gid和mode数值, 这样make_device就会向/ dev这个tmpfs'内存虚拟物理盘' 创建inode节点, 同时改变该inode的uid和gid.
于是在devperms[ ] 数组中我们就可以方便的控制生成的/ dev文件的uid, gid和mode了.
static struct perms_ devperms[ ] = {
{ "/dev/null" , 0666, AID_ROOT, AID_ROOT, 0 } ,
{ "/dev/zero" , 0666, AID_ROOT, AID_ROOT, 0 } ,
{ "/dev/full" , 0666, AID_ROOT, AID_ROOT, 0 } ,
{ "/dev/ptmx" , 0666, AID_ROOT, AID_ROOT, 0 } ,
{ "/dev/tty" , 0666, AID_ROOT, AID_ROOT, 0 } ,
{ "/dev/random" , 0666, AID_ROOT, AID_ROOT, 0 } ,
{ "/dev/urandom" , 0666, AID_ROOT, AID_ROOT, 0 } ,
{ "/dev/ashmem" , 0666, AID_ROOT, AID_ROOT, 0 } ,
{ "/dev/binder" , 0666, AID_ROOT, AID_ROOT, 0 } ,
{ "/dev/m2d" , 0666, AID_ROOT, AID_ROOT, 0 } ,
{ "/dev/bmm" , 0666, AID_ROOT, AID_ROOT, 0 } ,
{ "/dev/innodev" , 0666, AID_ROOT, AID_ROOT, 0 } ,
{ "/dev/innodev0" , 0666, AID_ROOT, AID_ROOT, 0 } ,
{ "/dev/innodev1" , 0666, AID_ROOT, AID_ROOT, 0 } ,
{ "/dev/innodev2" , 0666, AID_ROOT, AID_ROOT, 0 } ,
/* logger should be world writable (for logging) but not readable */
{ "/dev/log/" , 0662, AID_ROOT, AID_LOG, 1 } ,
/* these should not be world writable */
{ "/dev/android_adb" , 0660, AID_ADB, AID_ADB, 0 } ,
{ "/dev/android_adb_enable" , 0660, AID_ADB, AID_ADB, 0 } ,
{ "/dev/ttyMSM0" , 0660, AID_BLUETOOTH, AID_BLUETOOTH, 0 } ,
{ "/dev/alarm" , 0664, AID_SYSTEM, AID_RADIO, 0 } ,
{ "/dev/tty0" , 0666, AID_ROOT, AID_SYSTEM, 0 } ,
{ "/dev/graphics/" , 0666, AID_ROOT, AID_GRAPHICS, 1 } ,
{ "/dev/hw3d" , 0660, AID_SYSTEM, AID_GRAPHICS, 0 } ,
{ "/dev/input/" , 0660, AID_ROOT, AID_INPUT, 1 } ,
{ "/dev/eac" , 0660, AID_ROOT, AID_AUDIO, 0 } ,
{ "/dev/cam" , 0660, AID_ROOT, AID_CAMERA, 0 } ,
{ "/dev/video0" , 0660, AID_ROOT, AID_CAMERA, 0 } ,
{ "/dev/mved" , 0660, AID_SYSTEM, AID_CAMERA, 0 } ,
{ "/dev/pmem" , 0660, AID_SYSTEM, AID_GRAPHICS, 0 } ,
{ "/dev/pmem_gpu" , 0660, AID_SYSTEM, AID_GRAPHICS, 1 } ,
{ "/dev/pmem_adsp" , 0660, AID_SYSTEM, AID_AUDIO, 1 } ,
{ "/dev/pmem_camera" , 0660, AID_SYSTEM, AID_CAMERA, 1 } ,
{ "/dev/oncrpc/" , 0660, AID_ROOT, AID_SYSTEM, 1 } ,
{ "/dev/adsp/" , 0660, AID_SYSTEM, AID_AUDIO, 1 } ,
{ "/dev/sensors/" , 0666, AID_SYSTEM, AID_SYSTEM, 1 } ,
{ "/dev/mt9t013" , 0660, AID_SYSTEM, AID_SYSTEM, 0 } ,
{ "/dev/akm8976_daemon" , 0640, AID_COMPASS, AID_SYSTEM, 0 } ,
{ "/dev/akm8976_aot" , 0640, AID_COMPASS, AID_SYSTEM, 0 } ,
{ "/dev/akm8976_pffd" , 0640, AID_COMPASS, AID_SYSTEM, 0 } ,
{ "/dev/msm_pcm_out" , 0660, AID_SYSTEM, AID_AUDIO, 1 } ,
{ "/dev/msm_pcm_in" , 0660, AID_SYSTEM, AID_AUDIO, 1 } ,
{ "/dev/msm_pcm_ctl" , 0660, AID_SYSTEM, AID_AUDIO, 1 } ,
{ "/dev/msm_mp3" , 0660, AID_SYSTEM, AID_AUDIO, 1 } ,
{ "/dev/smd0" , 0640, AID_RADIO, AID_RADIO, 0 } ,
{ "/dev/qmi" , 0640, AID_RADIO, AID_RADIO, 0 } ,
{ "/dev/qmi0" , 0640, AID_RADIO, AID_RADIO, 0 } ,
{ "/dev/qmi1" , 0640, AID_RADIO, AID_RADIO, 0 } ,
{ "/dev/qmi2" , 0640, AID_RADIO, AID_RADIO, 0 } ,
{ "/dev/htc-acoustic" , 0640, AID_RADIO, AID_RADIO, 0 } ,
{ "/dev/snd/" , 0666, AID_ROOT, AID_AUDIO, 1 } ,
{ NULL , 0, 0, 0, 0 } ,
} ;