您的位置:首页 > 运维架构 > Linux

Linux下获取块设备大小

2015-07-05 16:49 441 查看
本文对linux下块设备文件全部适用。

通过lseek

linux下并没有专门用于获取硬盘设备大小的系统调用。因为完全不需要。linux下可以通过打开设备文件(块设备),执行lseek(fd,0,2)跳转到文件结尾处,通过lseek返回值获取设备文件大小。

linux内核启动时会获取硬盘的总大小,保存在内核中,对其读取或写入时都要对总大小做判断,读取位置是否已经超出最大值。而执行lseek(fd,0,2)会将当前文件偏移值直接设置为文件总大小,并返回最大值。

以下为执行代码

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc,char *argv[])
{
int fd;

if(argc!=2)
{
printf("argv !=2 \n");
return;
}

fd=open(argv[1],O_RDONLY);

if(fd==-1)
{
printf("open file wrong \n");
return;
}

off_t off=lseek(fd,0,SEEK_END);
//多少个G
long long gs=off/1024/1024/1024;

printf("size of  %d   %lld   %lld\n",sizeof(off_t),off,gs);

return;
}


不过编译的时候要注意,32位的系统下,gcc命令要执行gcc -D_FILE_OFFSET_BITS=64,不然获取的偏移最大只能是4G。

执行时以硬盘设备名作为命令行参。

./a.out /dev/sda


通过ioctl

每个设备文件都可以执行ioctl以获取对应设备的信息。

int ioctl(int handle, int cmd,...);
返回值:成功为0,出错为-1


块设备的话可以执行它获取块设备大小

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
#include <stdint.h>
#include <unistd.h>

int main(void)
{
int fd;
uint64_t size;
int len;
int r;

if ((fd = open("/dev/sda", O_RDONLY)) < 0)
{
printf("open error %d\n", errno);
exit(-1);
}

if ((r = ioctl(fd, BLKGETSIZE64, &size)) < 0)
{
printf("ioctl error %d\n", errno);
exit(-1);
}

len = (size>>30);
printf("size of sda = %d G\n", len);

return 0;
}


通过ioctl–2

以下代码来自fdsik命令源码
//获取设备每个扇区的大小
int blkdev_get_sector_size(int fd, int *sector_size)
{
#ifdef BLKSSZGET
if (ioctl(fd, BLKSSZGET, sector_size) >= 0)
return 0;
return -1;
#else
*sector_size = DEFAULT_SECTOR_SIZE;
return 0;
#endif
}

//获取磁头,磁道,扇区数
int blkdev_get_geometry(int fd, unsigned int *h, unsigned int *s)
{
#ifdef HDIO_GETGEO
struct hd_geometry geometry;

if (ioctl(fd, HDIO_GETGEO, &geometry) == 0) {
*h = geometry.heads;
*s = geometry.sectors;
return 0;
}
#else
*h = 0;
*s = 0;
#endif
return -1;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: