df와 df -h가 다른 값을 표시하는 이유는 무엇입니까? df -h는 어떻게 계산을 수행합니까?

df와 df -h가 다른 값을 표시하는 이유는 무엇입니까? df -h는 어떻게 계산을 수행합니까?

df -h가 정확히 어떻게 작동하나요? 를 실행하면 df다음과 같은 결과를 얻습니다.

Filesystem     1K-blocks    Used Available Use% Mounted on
/dev/simfs      41943040 7659828  34283212  19% /

를 실행하면 df -h다음과 같은 결과를 얻습니다.

Filesystem      Size  Used Avail Use% Mounted on
/dev/simfs       40G  7.4G   33G  19% /

문제는 같은 숫자를 얻는 방법입니다.

41943040 / 1024 / 1024 = 40 자, 나머지는 1024로 나누자.

7659828 / 1024 / 1024 = 7,304981

그럼 아마 1000까지요?

7659828 / 1000 / 1000 = 7,659828

7.4G는 어떻게 df -h얻었나요?

34283212 / 1024 / 1024 = 32,695, which is ±33G

df는 오픈 소스이지만 저는복제됨저장소를 확인하고 코드를 확인했습니다. 그것이 내가 찾은 것입니다:

for (col = 0; col < ncolumns; col++)
    {
      char *cell = NULL;
      char const *header = _(columns[col]->caption);

      if (columns[col]->field == SIZE_FIELD
          && (header_mode == DEFAULT_MODE
              || (header_mode == OUTPUT_MODE
                  && !(human_output_opts & human_autoscale))))
        {
          char buf[LONGEST_HUMAN_READABLE + 1];

          int opts = (human_suppress_point_zero
                      | human_autoscale | human_SI
                      | (human_output_opts
                         & (human_group_digits | human_base_1024 | human_B)));

          /* Prefer the base that makes the human-readable value more exact,
             if there is a difference.  */

          uintmax_t q1000 = output_block_size;
          uintmax_t q1024 = output_block_size;
          bool divisible_by_1000;
          bool divisible_by_1024;

          do
            {
              divisible_by_1000 = q1000 % 1000 == 0;  q1000 /= 1000;
              divisible_by_1024 = q1024 % 1024 == 0;  q1024 /= 1024;
            }
          while (divisible_by_1000 & divisible_by_1024);

          if (divisible_by_1000 < divisible_by_1024)
            opts |= human_base_1024;
          if (divisible_by_1024 < divisible_by_1000)
            opts &= ~human_base_1024;
          if (! (opts & human_base_1024))
            opts |= human_B;

          char *num = human_readable (output_block_size, buf, opts, 1, 1);

          /* Reset the header back to the default in OUTPUT_MODE.  */
          header = _("blocks");

          /* TRANSLATORS: this is the "1K-blocks" header in "df" output.  */
          if (asprintf (&cell, _("%s-%s"), num, header) == -1)
            cell = NULL;
        }
      else if (header_mode == POSIX_MODE && columns[col]->field == SIZE_FIELD)
        {
          char buf[INT_BUFSIZE_BOUND (uintmax_t)];
          char *num = umaxtostr (output_block_size, buf);

          /* TRANSLATORS: this is the "1024-blocks" header in "df -P".  */
          if (asprintf (&cell, _("%s-%s"), num, header) == -1)
            cell = NULL;
        }
      else
        cell = strdup (header);

      if (!cell)
        xalloc_die ();

      hide_problematic_chars (cell);

      table[nrows - 1][col] = cell;

      columns[col]->width = MAX (columns[col]->width, mbswidth (cell, 0));
    }

저는 이 언어에 대한 경험이 없지만 제가 이해한 대로 각 열의 값이 1024 또는 1000으로 나눌 수 있는지 확인하고 옵션에 대한 값을 렌더링하는 데 더 나은 것을 선택하려고 시도합니다 -h. 그런데 1000으로 나누든 1024로 나누든 같은 값이 나오지 않습니다. 왜일까요?

왜 그런지 알 것 같아요. 1000 또는 1024로 나누는지 확인합니다.분할.

          if (divisible_by_1000 < divisible_by_1024)
            opts |= human_base_1024;
          if (divisible_by_1024 < divisible_by_1000)
            opts &= ~human_base_1024;
          if (! (opts & human_base_1024))
            opts |= human_B;

그럼 7659828 / 1024 / 1024 = 7,304981을 해독해 보겠습니다. -h의 대답을 했다7.4G

7659828 / 1024 = 7480,xxx
7659828 / 1000 = 7659,xxx

7659는 7480보다 크므로 1024로 나눕니다.

여전히 큰 숫자입니다. 계속해 보겠습니다.

7659828 / 1024 / 1024 = 7,xxx  (7,3049..)
7659828 / 1024 / 1000 = 7,xxx  (7,4803..)

지금은 1000이 걸리고 7,48이 나오네요.믿다코드 어딘가에 반올림되어 "더 많은 것보다 적은 것이 더 낫다"고 말하면서 7.4G의 데이터를 넣을 수 있지만 7.5G는 넣을 수 없습니다.

33.4G에서도 같은 이야기

34283212 / 1024 / 1000 = 33.47...

그래서 33G가 됩니다.

답변1

게시한 코드는 첫 번째 행의 텍스트를 생성하는 "get_header" 함수에서 가져온 것입니다. 귀하의 경우 이는 "1K-블록"이라는 제목에 적용됩니다( df -B1023차이점을 확인하려면 전화하세요).

중요 사항: "1K"는 1000바이트 블록이 아닌 1024바이트 블록을 나타냅니다("1kB 블록"으로 표시됨, 참조 df -B1000).

사람이 읽을 수 있는 형식의 숫자 계산은 "human_reader"(human.c:153) 함수에 의해 처리됩니다. df.c:1571에서 플래그와 함께 호출할 때 사용되는 옵션을 찾을 수 있습니다 -h.

case 'h':
    human_output_opts = human_autoscale | human_SI | human_base_1024;
    output_block_size = 1;
    break;

모든 계산은 사람이 읽을 수 있는 형식("-h")의 기본 1024를 사용하여 수행됩니다. 표시된 human_output_opts 외에도 여기에 적용되는 기본 설정이 있습니다(human.h, 열거형 선언 참조).

/* The following three options are mutually exclusive.  */
/* Round to plus infinity (default).  */
human_ceiling = 0,
/* Round to nearest, ties to even.  */
human_round_to_nearest = 1,
/* Round to minus infinity.  */
human_floor = 2,

human_output_opts에는 human_round_to_nearest 또는 human_floor가 포함되어 있지 않으므로 기본값인 human_ceiling을 사용합니다. 따라서 계산된 모든 값은 반올림됩니다.

설정을 확인하기 위해 다음의 1K 블록을 기반으로 사람이 읽을 수 있는 형식을 계산해 볼 수 있습니다 df.

Size = ceil(41943040/1024/1024) = ceil(40) = 40
Used = ceil(7659828/1024/1024) = ceil(7.305) = 7.4
Available = ceil(34283212/1024/1024) = ceil(32.695) = 33

의 출력과 동일합니다 df -h.

(... 그리고 1000바이트 형식을 선호하는 경우 간단히 를 호출할 수 있습니다 df -H).

답변2

dfFreeBSD의 프로그램(원래 df -h출처임)이나 dfSolaris의 구현 모두 이런 식으로 동작하지 않습니다 .

Solaris 소스는 OpenSource이므로 dfOS에서 컴파일할 수 있는지 확인할 수 있습니다.

관련 정보