在Linux的学习中,我们经常会听到缓冲区的概念。那么什么是缓冲区呢?在之前学习C语言和C++的时候,我们知道这相当于一个容器,用来暂时存储我们的输入输出数据。相对来说,这块空间可以提高我们I/O的效率。
在学习的过程中,我们也明白库函数就是对于系统调用函数进行一个封装,比如printf函数是write函数的封装。只不过我们的printf在使用的时候,对write进行了一些处理,最明显的就是加了一个缓冲区。printf函数实际上是向用户空间的I/O缓冲区进行写操作。当缓冲区被写满的情况下才会调用write进行内核的写操作,这样就做到了提高效率。
既然说到了缓冲区就不得不提缓冲区刷新的问题了。在Linux中缓冲区的刷新分为三类。
- 全缓冲
全缓冲指的是系统在填满标准IO缓冲区之后才进行实际的IO操作;注意,对于驻留在磁盘上的文件来说通常是由标准IO库实施全缓冲。 - 行缓冲
在这种情况下,标准IO在输入和输出中遇到换行符时执行IO操作;注意,当流涉及终端的时候,通常使用的是行缓冲。 - 无缓冲
无缓冲指的是标准IO库不对字符进行缓冲存储;注意,标准出错流stderr通常是无缓冲的。
接下来,我们就利用缓冲区的知识来实现一个内存条。第一个版本是我们用C语言实现的。具体代码如下。
**********************************************************
> File Name: bar.c
> Author: monster
> Mail: 1104306242@qq.com
> Created Time: Wed 28 Jun 2017 04:47:51 PM CST
**********************************************************
#include<stdio.h>
#include<unistd.h>
void mybar()
{
char bar[101]={'\0'};
int i=0;
char str[]={'|','/','-','\\'};
printf("\033[?251\033[41m");
fflush(stdout);
printf("\033[0m");
while(i<=100)
{
printf("\033[42m\033[1m");
printf("[%c]%s%3d%% \r\033[0m",str[i%4],bar,i);
fflush(stdout);
usleep(30000);
bar[i]=' ';
i++;
}
printf("\n\033[?25h");
}
int main()
{
mybar();
return 0;
}
在这里需要注意的是printf的刷新方式是行缓冲,所以每当我们在缓冲区进行写操作时,一定要将缓冲区刷新。在这里因为考虑到美观,我对底板进行了配色,看起来更像一个我们平时见到的缓冲区。出来的效果是随着进度条的执行,绿色部分一直向前走,前面的|也会转起来。最终图如下。
第二个版本我是用脚本实现的。实现的效果也是如上。但是用脚本的实现是有一些不同的。用脚本写的时候,我们需要注意的是不用刷新,因为这里其实是没有缓冲的。具体代码是如下。
###########################################################
# File Name: bar.sh
# Author: monster
# mail: 1104306242@qq.com
# Created Time: Wed 28 Jun 2017 03:06:16 PM CST
###########################################################
#!/bin/bash
i=0
index=0
bar=(' ')
lable=('|' '/' '-' '\\')
printf "033[?251\033[41m"
printf "%69s\r"
printf "\033[0m"
while [ $i -le 100 ]
do
printf "\033[42m\033[1m"
printf "[%c%-100s %d%%]\r\033[0m" "${lable[$index]}" "$bar" "$i"
bar=#$bar
let i++
let index++
let index%=4
usleep 30000
done
printf "\n\033[?25h"