废话

最近有试着用C语言输出自己土豆服务器上NAS的占用情况。环境还是Debian 10。

通过调用statfs.h头文件获取文件系统信息。

我的代码(nasstat2.c):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <stdio.h>
#include <sys/statfs.h>
#include <sys/types.h>


int main(){
struct statfs nas;
if(statfs("/home/nas",&nas) == -1){
printf("Bad FileSystem\n");
}
else{
unsigned long long totalBlocks = nas.f_bsize;
//(Bytes)
unsigned long long totalSize = totalBlocks * nas.f_blocks;
//(GiB)

//套公式换算
size_t totalGSize = (((totalSize / 1024 ) / 1024 ) / 1024);
unsigned long long freeSize = nas.f_bfree*totalBlocks;
size_t freeGSize = (((freeSize / 1024 ) / 1024 ) / 1024 );

double p = ((double)freeGSize / (double)totalGSize) * 100.0;

printf("NAS %dG %0.0f%",totalGSize,p);
putchar('\n');
int blankblock = (int)((p / 100.0) * 16.0);
int sharpblock = 16 - blankblock;

for(int i = 0; i < sharpblock;i++)putchar('|');
for(int i = 0; i < blankblock;i++)putchar(' ');

putchar('\n');
}

return 0;
}

在输出totalGSize(GB单位的挂载点总容量)和p(剩余容量百分比)前,需要对单位进行换算。我选择套公式。

我也参考了其他前辈的的方法,改良后是这样(nasstat3.c):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <sys/statfs.h>
#include <sys/types.h>


int main(){
struct statfs nas;
if(statfs("/home/nas",&nas) == -1){
printf("Bad FileSystem\n");
}
else{
unsigned long long totalBlocks = nas.f_bsize;
//(Bytes)
unsigned long long totalSize = totalBlocks * nas.f_blocks;
//(GiB)
size_t totalGSize = totalSize >> 30;

unsigned long long freeSize = nas.f_bfree*totalBlocks;
size_t freeGSize = freeSize >> 30;

double p = ((double)freeGSize / (double)totalGSize) * 100.0;



printf("NAS %dG %f%\n", totalGSize, p);

int blankblock = (int)((p / 100.0) * 16.0);
int sharpblock = 16 - blankblock;

for(int i = 0; i < sharpblock;i++)putchar('|');
for(int i = 0; i < blankblock;i++)putchar(' ');

putchar('\n');
}

return 0;
}

二者输出的结果几乎没有区别。

输出p时只保留了整数……

结果

不省略的结果


虽然说二进制移位运算这个很容易理解,但我还是没有很好地运用呢,就干脆温习一下吧。

终于到了正文

二进制的位运算中,异或取反都和逻辑运算没有多大的区别。

而移位运算也不难理解。

移位运算分为左移右移,对应的运算符分别是<<>>

  • 左移:各二进制位向左移若干位,高位丢弃,低位补0。二进制左移x位后面就加x个0再去掉前面的0
  • 右移:各二进位全部右移若干位,对无符号数,高位补0,有符号数,各编译器处理方法不一样,有的补符号位(算术右移),有的补0(逻辑右移)通常右移x位就在前面加x位0(正数加0,复数加1)并去掉后面x位

例子

左移

0011 0111 << 2 = 1101 1100

0011 0111 << 2 = 00 1101 1100 = 1101 1100

右移

0011 0111 >> 2 = 0000 1101

0011 0111 >> 2 = 0000 1101 11 = 0000 1101

到这里就很好理解了。

左移一个二进制位等同于该数化为十进制后乘以2,右移一个二进制位相当于该数化为十进制后除以2。

末尾

那么前面通过右移30个二进制位将字节换算为GB的方法就没有那么难理解了。

(完,又水了一篇)