linux设备major和minor

在内核2.6.0之前,major和minor都是8位,合并组成16位的设备号(即syscall.stat中的dev_t)

 static inline u16 old_encode_dev(dev_t dev)
{
	return (MAJOR(dev) << 8) | MINOR(dev);
}
static inline dev_t old_decode_dev(u16 val)
{
	return MKDEV((val >> 8) & 255, val & 255);
}

http://elixir.free-electrons.com/linux/latest/source/include/linux/kdev_t.h#L38

然而在2.6.0之后,major和minor因为需要支持更多数量的设备,修改为12位major和20位minor,组成32位的dev_t,为了兼容旧版本,在组成dev_t时拆出8位major和8位minor组成dev_t的低16位,高16位由剩下的填补   

static inline u32 new_encode_dev(dev_t dev)
{
	unsigned major = MAJOR(dev);
	unsigned minor = MINOR(dev);
	return (minor & 0xff) | (major << 8) | ((minor & ~0xff) << 12);
}
static inline dev_t new_decode_dev(u32 dev)
{
	unsigned major = (dev & 0xfff00) >> 8;
	unsigned minor = (dev & 0xff) | ((dev >> 12) & 0xfff00);
	return MKDEV(major, minor);
}

而即时是2.6.0之后的版本,在也只有在64位机上会使用new的方式

#if BITS_PER_LONG == 32
#  define choose_32_64(a,b) a
#else
#  define choose_32_64(a,b) b
#endif

#define valid_dev(x)  choose_32_64(old_valid_dev(x),true)
#define encode_dev(x) choose_32_64(old_encode_dev,new_encode_dev)(x)

http://elixir.free-electrons.com/linux/latest/source/fs/stat.c#L289

glibc提供的反解方式/usr/include/sys/sysmacros.h,看起来这种方式考虑了major比12位更大的情况

# if defined __GNUC__ && __GNUC__ >= 2 && defined __USE_EXTERN_INLINES
__extension__ __extern_inline __attribute_const__ unsigned int
__NTH (gnu_dev_major (unsigned long long int __dev))
{
  return ((__dev >> 8) & 0xfff) | ((unsigned int) (__dev >> 32) & ~0xfff);
}
__extension__ __extern_inline __attribute_const__ unsigned int
__NTH (gnu_dev_minor (unsigned long long int __dev))
{
  return (__dev & 0xff) | ((unsigned int) (__dev >> 12) & ~0xff);
}

__extension__ __extern_inline __attribute_const__ unsigned long long int
__NTH (gnu_dev_makedev (unsigned int __major, unsigned int __minor))
{
  return ((__minor & 0xff) | ((__major & 0xfff) << 8)
          | (((unsigned long long int) (__minor & ~0xff)) << 12)
          | (((unsigned long long int) (__major & ~0xfff)) << 32));
}
# endif
__END_DECLS

/* Access the functions with their traditional names.  */
# define major(dev) gnu_dev_major (dev)
# define minor(dev) gnu_dev_minor (dev)
# define makedev(maj, min) gnu_dev_makedev (maj, min)
#endif

#endif /* sys/sysmacros.h */

最后自己写了一个golang的反解

func getDiskMajorMinor(path string) (major, minor int, err error) {
	stat := syscall.Stat_t{}
	err = syscall.Stat(path, &stat)
	if nil != err {
		return 0, 0, err
	}

	//refer to "dev_t new_decode_dev(u32 dev)" defined in the kernel header file linux/kdev.h
	major = int(((uint32(stat.Dev)) >> 8) & 0xfff)
	minor = int((stat.Dev & 0xff) | ((stat.Dev >> 12) & 0xfff00))

	return major, minor, nil
}

参考 http://www.makelinux.net/ldd3/chp-3-sect-2

转载于:https://my.oschina.net/u/3211934/blog/1541659

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值