2017-10-04 47 views
2

编辑:@abhink指出,没有调用Size()如何正确地获取块设备的尺寸?

我试了两种不同的去法,然后再比较df。当然,所有3给出不同的结果:

package main 

import (
    "os" 
    "syscall" 
    "fmt" 
) 

func main() { 
    disk := "/dev/sda1" 
    statout, err := os.Stat(disk) 
    if err != nil { 
     fmt.Errorf("Error %x", err) 
     os.Exit(1) 
    } 
    println("os.Stat Size : ", statout.Size()) 

    var stat syscall.Statfs_t 
    syscall.Statfs(disk, &stat) 
    println("syscall.Statfs_t Type: ", stat.Type) 
    println("syscall.Statfs_t Bsize: ", stat.Bsize) 
    println("syscall.Statfs_t Blocks: ", stat.Blocks) 
} 

运行程序:

$ main 
os.Stat Size : 0 
syscall.Statfs_t Type: 16914836 
syscall.Statfs_t Bsize: 4096 
syscall.Statfs_t Blocks: 2560 

和DF:

$ df /dev/sda1 
Filesystem   1K-blocks  Used Available Use% Mounted on 
/dev/sda1    65792556 43694068 18726712 70% /var 

网:

  • os.Stat()0它不是,但可能是一个OS问题。
  • syscall.Statfs()给出2560块* 4096块大小= 10,485,760。更现实的,但仍然不正确
  • df给65792556 1K块* 1024个字节/ K = 67,371,577,344

如何可靠地获得一个块设备的大小,而不安装呢?

本质上,我正在寻找相当于设备上的ioctl呼叫。

ioctl(fd,BLKGETSIZE64,&size) 
+3

'os.Stat'返回'os.FileInfo'类型,是一个接口类型。 'Size'是返回类型的方法,而不是字段。 '0xc420031f58'是函数'Size'的地址。 https://golang.org/pkg/os/#FileInfo – abhink

+2

旁注:'fmt.Errorf'不是你所想的那样。就像打印os.FileInfos Size字段一样。如何查找所有使用的函数/方法的文档? – Volker

+0

哦,哎呀。我应该做'Size()'。很好的接收。 – deitch

回答

5

当调用syscall.Statfs(),你必须通过路径,其中设备被安装,例如/,而不是设备文件(不是/dev/sda1)。在你的情况下,这是/var

您得到的结果值为syscall.Statfs_t。解读:

var stat syscall.Statfs_t 
if err := syscall.Statfs("/", &stat); err != nil { 
    panic(err) 
} 

size := stat.Blocks * uint64(stat.Bsize) 
free := stat.Bfree * uint64(stat.Bsize) 
avail := stat.Bavail * uint64(stat.Bsize) 
fmt.Println("Size:", size) 
fmt.Println("Free:", free) 
fmt.Println("Available:", avail) 
fmt.Println("Used:", size-free) 

看到这个可能重复:Get amount of free disk space using Go

+1

啊,非常好,谢谢@icza。那么,我怎样才能真正得到它_without_装入?我可以在C中使用正确的'ioctl'调用(已编辑的问题),是否有一种本地方法? – deitch