なぜ真実と偽がそんなに大きいのか

いくつかの一般的なコマンド( read など)が実際にはBash組み込みコマンドであることがわかった後(そしてプロンプトでそれらを実行すると、実際には組み込みコマンドに転送する2行のシェルスクリプトを実行します)。同じことが true false にも当てはまるかどうかを調べていました。

まあ、彼らは間違いなくバイナリです。

sh-4.2$ which true
/usr/bin/true
sh-4.2$ which false
/usr/bin/false
sh-4.2$ file /usr/bin/true
/usr/bin/true: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=2697339d3c19235
06e10af65aa3120b12295277e, stripped
sh-4.2$ file /usr/bin/false
/usr/bin/false: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=b160fa513fcc13
537d7293f05e40444fe5843640, stripped
sh-4.2$

しかし、私が最も驚いたのはその大きさでした。 true は基本的には exit 0 false exit 1 。

sh-4.2$ true
sh-4.2$ echo $?
0
sh-4.2$ false
sh-4.2$ echo $?
1
sh-4.2$

しかし、驚いたことに、両方のファイルのサイズは28KBを超えています。

sh-4.2$ stat /usr/bin/true
  File: '/usr/bin/true'
  Size: 28920           Blocks: 64         IO Block: 4096   regular file
Device: fd2ch/64812d    Inode: 530320      Links: 1                     
Access: (0755/-rwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2018-01-25 19:46:32.703463708 +0000
Modify: 2016-06-30 09:44:27.000000000 +0100
Change: 2017-12-22 09:43:17.447563336 +0000
 Birth: -
sh-4.2$ stat /usr/bin/false
  File: '/usr/bin/false'
  Size: 28920           Blocks: 64         IO Block: 4096   regular file
Device: fd2ch/64812d    Inode: 530697      Links: 1                     
Access: (0755/-rwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2018-01-25 20:06:27.210764704 +0000
Modify: 2016-06-30 09:44:27.000000000 +0100
Change: 2017-12-22 09:43:18.148561245 +0000
 Birth: -
sh-4.2$

だから私の質問は:なぜ彼らはそんなに大きいのですか?リターンコード以外の実行可能ファイルには何がありますか。

シモンズ:私はRHEL 7.4を使用しています

79
追加された 著者 Calvin,
@ user1024スペルミスですか?私はメッセージよりもコードを見たと思います...
追加された 著者 Calvin,
@BasileStarynkevitch私の答えはDebianバイナリに基づいており、それらの選択肢の側面について話しています。
追加された 著者 Calvin,
@フィリップ素晴らしいもの、良い発見。
追加された 著者 Calvin,
@フィリップ:GNU true のバージョン5.93と5.94の間で何が変わったのでしょうか。私は彼らが --help のテキストの綴りや句読点の誤りを修正したと思います。
追加された 著者 Armandas,
また、プロンプトで組み込みコマンドを入力しても、 '[組み込み]にリダイレクトする2行のスクリプトを実行する'ことはできません。それ以外の場合は、 cd ulimit shopt のようにシェルの状態を変更します。シェルではなく、 find xargs nohup nice などのようなシェルを使用しないプログラムから実行しようとした場合
追加された 著者 dave_thompson_085,
私のDebianシステムでは、 true --help --version の両方の引数を受け付けるので、それらを処理するためのコードがあります
追加された 著者 Basile Starynkevitch,
必須 - false の最小の実装です。 com /〜breadbox/software/tiny/teensy.html
追加された 著者 Retne,
それが終了コード0を返す有効なshプログラムだったので、unixの初期のバージョンのいくつかは真に空のファイルを持っていました。空のファイルから真のユーティリティの歴史について何年か前に読んだ記事を見つけることができたらそれは今日の怪しげさですが、私が見つけることができたのはこれだけです: /~jc/humor/ATT_Copyright_true.html
追加された 著者 WayToDoor,
@Philip同僚がSVR4の真のシェルスクリプトがバージョン1.6であることを知ったとき、彼は「最初の5つのバージョンにはどんなバグがあったのだろうか」と言った。 (彼らはおそらく単に著作権表示を調整するか、あるリビジョン管理システムから別のものに移動していたのです。)
追加された 著者 Andreï Kostyrka,
皮肉なことに、「 true false がそれぞれ29kbなのはなぜですか?リターンコード以外の実行可能ファイルには何がありますか?」というような長い質問を書くのは皮肉なことです。
追加された 著者 John,
@meuhちょうど command -V というレコードは bash のようなシェルには一般的ですが、今日使用されているすべてのBourneライクに移植性があるわけではありません。 command -v (小文字の v )は、もっと普遍的/移植的ですが、私が見たほとんどのシェルでは組み込みコマンドや関数のコマンド名を表示するだけです。
追加された 著者 mtraceur,
true false は現代のすべてのシェルに組み込まれていますが、システムには外部プログラムバージョンも含まれています。標準システムの一部であるため、コマンドを直接呼び出す(シェルを迂回する)プログラムで使用できます。 which は組み込みコマンドを無視し、外部コマンドのみを検索します。そのため、外部コマンドだけが表示されます。代わりに type -a true type -a false を試してください。
追加された 著者 mtraceur,
which ではなく、 command -V true を使用してください。それは出力されます: trueはbash用のシェル組み込みです。
追加された 著者 user119298,
@MarkPlotnick SVR4の真と偽のシェルスクリプトについてさらにおかしなことは、「これは未公開のAT&Tの専売のソースコードです」というフレーズで始まる長いお知らせです。 AT&Tが「exit 0」というフレーズに著作権を持っていること、それが企業秘密であること、および商用オペレーティングシステムのシェルスクリプトのテキストがなんらかの形で「未発表」であるという明らかに不合理な主張。それから、その通知が6バイトのスクリプトであるべきものをほぼ1ページのテキストに拡大したという事実がありました。
追加された 著者 user273332,

4 答え

はじめに

以前は、シェルの/bin/true /bin/false は実際にはスクリプトでした。

たとえば、PDP/11 Unix System 7では、次のようになります。

$ ls -la /bin/true /bin/false
-rwxr-xr-x 1 bin         7 Jun  8  1979 /bin/false
-rwxr-xr-x 1 bin         0 Jun  8  1979 /bin/true
$
$ cat /bin/false
exit 1
$
$ cat /bin/true
$  

今日では、少なくとも bash では、 true false コマンドはシェルの組み込みコマンドとして実装されています。したがって、 bash コマンドラインおよびシェルスクリプト内で false および true ディレクティブを使用する場合、実行可能バイナリファイルはデフォルトでは呼び出されません。

bash ソースから builtins/mkbuiltins.c

char *posix_builtins[] =
    {
      "alias", "bg", "cd", "command", "**false**", "fc", "fg", "getopts", "jobs",
      "kill", "newgrp", "pwd", "read", "**true**", "umask", "unalias", "wait",
      (char *)NULL
    };

また@meuhコメントあたり:

$ command -V true false
true is a shell builtin
false is a shell builtin

そのため、 true および false 実行可能ファイルは、主に他のプログラムから呼び出されるためのものです。

今後は、Debian 9/64ビット版の coreutils パッケージに含まれる/bin/true バイナリに焦点を絞ります。 (RedHatを実行している/usr/bin/true 。RHとDebianはどちらも coreutils パッケージを使用しています。後者のコンパイル済みバージョンを分析しました)。

ソースファイル false.c に見られるように、/bin/false /bin/true <とほぼ同じソースコードでコンパイルされています。代わりにEXIT_FAILURE(1)を返すだけなので、この答えは両方のバイナリに適用できます。

#define EXIT_STATUS EXIT_FAILURE
#include "true.c"

同じサイズの両方の実行可能ファイルによっても確認できます。

$ ls -l /bin/true /bin/false
-rwxr-xr-x 1 root root 31464 Feb 22  2017 /bin/false
-rwxr-xr-x 1 root root 31464 Feb 22  2017 /bin/true

残念ながら、その答えに対する直接の質問はなぜ真と偽がそれほど大きいのか?は、その最高のパフォーマンスを気にするためのそれほど差し迫った理由がもうないためです。これらは bash のパフォーマンスには不可欠ではなく、 bash ではもう使用されていません(スクリプト)。

同様のコメントがそれらのサイズにも当てはまります。今日我々が持っている種類のハードウェアのための26KBは重要ではありません。通常のサーバー/デスクトップではスペースはそれほど貴重ではなく、2回展開されるだけなので、 false true に同じバイナリを使用する必要もありません。 coreutils を使ったディストリビューションでは

しかし、質問の本当の精神に焦点を当てて、なぜそれほど単純で小さくなるべきものがそれほど大きくなるのでしょうか。

/bin/true のセクションの実際の分布はこれらのグラフが示すとおりです。メインコード+データは26KBのバイナリのうちおよそ3KBで、/bin/true のサイズの12%に相当します。

true ユーティリティは何年にもわたって確かにもっと巧妙なコードを手に入れました。最も注目すべきは --version --help の標準サポートです。

しかし、それがそれほど大きくなることの(唯一の)主な正当化ではなく、むしろ(共有ライブラリを使用して)動的にリンクされながら、 coreutils バイナリで一般的に使用される一般的なライブラリの一部もあります。静的ライブラリとしてリンクされています。 elf 実行可能ファイルを作成するためのメタデータも、バイナリのかなりの部分を占めています。今日の標準では比較的小さいファイルです。

残りの答えは、/bin/true 実行可能バイナリファイルの構成とその結論に至った方法を詳述した以下のチャートをどのように構築したかを説明することです。

bintrue bintrue2

@Maksが言うように、バイナリはCからコンパイルされました。私のコメントにもあるように、それはcoreutilsからのものであることも確認されています。 https:// github git gnu gitの代わりに@Maks(同じソース、異なるリポジトリ - このリポジトリは)に選択されています。 > coreutils ライブラリ)

/bin/true バイナリのさまざまな構成要素がここにあります(Debian 9 - coreutils の64ビット)。

$ file /bin/true
/bin/true: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=9ae82394864538fa7b23b7f87b259ea2a20889c4, stripped

$ size /bin/true
    text       data     bss     dec     hex filename
   24583       1160     416   26159    662f true

それらのうち:

  • テキスト(通常はコード)は約24KBです。
  • データ(初期化された変数、主に文字列)は約1KBです。
  • bss(未初期化データ)0.5KB

24KBのうち、1KBは58個の外部機能を修正するためのものです。

それでも、残りのコードには約23KBが残ります。実際のメインファイル - main()+ usage()のコードは1KB前後でコンパイルされていることを以下に示し、他の22KBが何のために使われているかを説明します。

readelf -S true を使用してバイナリをさらにドリルダウンすると、バイナリは26159バイトですが、実際のコンパイル済みコードは13017バイトで、残りは各種データ/初期化コードです。

しかし、 true.c はそれだけではなく、そのファイルだけであれば、13KBは多すぎると思われます。 objdump -T true を使用すると、 main()で呼び出された関数が、elfに表示される外部関数にリストされていないことがわかります。に存在する機能:

main()内で外部的にリンクされていないこれらの追加機能は次のとおりです。

  • set_program_name()
  • close_stdout()
  • version_etc()

だから私の最初の疑いは部分的には正しかった。ライブラリは動的ライブラリを使っているが、/bin/true バイナリは大きなものだ。しかしそれだけが原因ではありません。

Cコードをコンパイルすることは、そのようなスペースを考慮に入れないために 非効率的ではありません。そのため、私の最初の疑いは間違っていました。

バイナリのサイズのほぼ90%の追加スペースは、実際には追加のライブラリ/ elfメタデータです。

バイナリの逆アセンブル/逆コンパイルにHopperを使って関数がどこにあるかを理解している間、true.c/usage()は実際には833バイトで、true.c/main()は225バイトで、およそ1KBより少し小さいです。 。静的ライブラリに埋め込まれているバージョン関数のロジックは約1KBです。

実際にコンパイルされたmain()+ usage()+ version()+ strings + varsは、最大3KBから3.5KBまでしか使用していません。

それは実に皮肉なことです、そのような小さくて謙虚なユーティリティは上で説明された理由でサイズがより大きくなった。

related question: Understanding what a Linux binary is doing

true.c main() with the offending function calls:

int
main (int argc, char **argv)
{
  /* Recognize --help or --version only if it's the only command-line
     argument.  */
  if (argc == 2)
    {
      initialize_main (&argc, &argv);
      set_program_name (argv[0]);           <-----------
      setlocale (LC_ALL, "");
      bindtextdomain (PACKAGE, LOCALEDIR);
      textdomain (PACKAGE);

      atexit (close_stdout);             <-----

      if (STREQ (argv[1], "--help"))
        usage (EXIT_STATUS);

      if (STREQ (argv[1], "--version"))
        version_etc (stdout, PROGRAM_NAME, PACKAGE_NAME, Version,  AUTHORS,  <------
                     (char *) NULL);
    }

  exit (EXIT_STATUS);
}

バイナリのさまざまなセクションの10進数のサイズ

$ size -A -t true 
true  :
section               size      addr
.interp                 28       568
.note.ABI-tag           32       596
.note.gnu.build-id      36       628
.gnu.hash               60       664
.dynsym               1416       728
.dynstr                676      2144
.gnu.version           118      2820
.gnu.version_r          96      2944
.rela.dyn              624      3040
.rela.plt             1104      3664
.init                   23      4768
.plt                   752      4800
.plt.got                 8      5552
.text                13017      5568
.fini                    9     18588
.rodata               3104     18624
.eh_frame_hdr          572     21728
.eh_frame             2908     22304
.init_array              8   2125160
.fini_array              8   2125168
.jcr                     8   2125176
.data.rel.ro            88   2125184
.dynamic               480   2125272
.got                    48   2125752
.got.plt               392   2125824
.data                  128   2126240
.bss                   416   2126368
.gnu_debuglink          52         0
Total                26211

readelf -S true の出力

$ readelf -S true
There are 30 section headers, starting at offset 0x7368:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .interp           PROGBITS         0000000000000238  00000238
       000000000000001c  0000000000000000   A       0     0     1
  [ 2] .note.ABI-tag     NOTE             0000000000000254  00000254
       0000000000000020  0000000000000000   A       0     0     4
  [ 3] .note.gnu.build-i NOTE             0000000000000274  00000274
       0000000000000024  0000000000000000   A       0     0     4
  [ 4] .gnu.hash         GNU_HASH         0000000000000298  00000298
       000000000000003c  0000000000000000   A       5     0     8
  [ 5] .dynsym           DYNSYM           00000000000002d8  000002d8
       0000000000000588  0000000000000018   A       6     1     8
  [ 6] .dynstr           STRTAB           0000000000000860  00000860
       00000000000002a4  0000000000000000   A       0     0     1
  [ 7] .gnu.version      VERSYM           0000000000000b04  00000b04
       0000000000000076  0000000000000002   A       5     0     2
  [ 8] .gnu.version_r    VERNEED          0000000000000b80  00000b80
       0000000000000060  0000000000000000   A       6     1     8
  [ 9] .rela.dyn         RELA             0000000000000be0  00000be0
       0000000000000270  0000000000000018   A       5     0     8
  [10] .rela.plt         RELA             0000000000000e50  00000e50
       0000000000000450  0000000000000018  AI       5    25     8
  [11] .init             PROGBITS         00000000000012a0  000012a0
       0000000000000017  0000000000000000  AX       0     0     4
  [12] .plt              PROGBITS         00000000000012c0  000012c0
       00000000000002f0  0000000000000010  AX       0     0     16
  [13] .plt.got          PROGBITS         00000000000015b0  000015b0
       0000000000000008  0000000000000000  AX       0     0     8
  [14] .text             PROGBITS         00000000000015c0  000015c0
       00000000000032d9  0000000000000000  AX       0     0     16
  [15] .fini             PROGBITS         000000000000489c  0000489c
       0000000000000009  0000000000000000  AX       0     0     4
  [16] .rodata           PROGBITS         00000000000048c0  000048c0
       0000000000000c20  0000000000000000   A       0     0     32
  [17] .eh_frame_hdr     PROGBITS         00000000000054e0  000054e0
       000000000000023c  0000000000000000   A       0     0     4
  [18] .eh_frame         PROGBITS         0000000000005720  00005720
       0000000000000b5c  0000000000000000   A       0     0     8
  [19] .init_array       INIT_ARRAY       0000000000206d68  00006d68
       0000000000000008  0000000000000008  WA       0     0     8
  [20] .fini_array       FINI_ARRAY       0000000000206d70  00006d70
       0000000000000008  0000000000000008  WA       0     0     8
  [21] .jcr              PROGBITS         0000000000206d78  00006d78
       0000000000000008  0000000000000000  WA       0     0     8
  [22] .data.rel.ro      PROGBITS         0000000000206d80  00006d80
       0000000000000058  0000000000000000  WA       0     0     32
  [23] .dynamic          DYNAMIC          0000000000206dd8  00006dd8
       00000000000001e0  0000000000000010  WA       6     0     8
  [24] .got              PROGBITS         0000000000206fb8  00006fb8
       0000000000000030  0000000000000008  WA       0     0     8
  [25] .got.plt          PROGBITS         0000000000207000  00007000
       0000000000000188  0000000000000008  WA       0     0     8
  [26] .data             PROGBITS         00000000002071a0  000071a0
       0000000000000080  0000000000000000  WA       0     0     32
  [27] .bss              NOBITS           0000000000207220  00007220
       00000000000001a0  0000000000000000  WA       0     0     32
  [28] .gnu_debuglink    PROGBITS         0000000000000000  00007220
       0000000000000034  0000000000000000           0     0     1
  [29] .shstrtab         STRTAB           0000000000000000  00007254
       000000000000010f  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  l (large), p (processor specific)

objdump -T true の出力(実行時に動的にリンクされた外部関数)

$ objdump -T true

true:     file format elf64-x86-64

DYNAMIC SYMBOL TABLE:
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 __uflow
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 getenv
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 free
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 abort
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 __errno_location
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 strncmp
0000000000000000  w   D  *UND*  0000000000000000              _ITM_deregisterTMCloneTable
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 _exit
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 __fpending
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 textdomain
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 fclose
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 bindtextdomain
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 dcgettext
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 __ctype_get_mb_cur_max
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 strlen
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.4   __stack_chk_fail
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 mbrtowc
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 strrchr
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 lseek
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 memset
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 fscanf
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 close
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 __libc_start_main
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 memcmp
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 fputs_unlocked
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 calloc
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 strcmp
0000000000000000  w   D  *UND*  0000000000000000              __gmon_start__
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.14  memcpy
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 fileno
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 malloc
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 fflush
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 nl_langinfo
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 ungetc
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 __freading
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 realloc
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 fdopen
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 setlocale
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.3.4 __printf_chk
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 error
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 open
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 fseeko
0000000000000000  w   D  *UND*  0000000000000000              _Jv_RegisterClasses
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 __cxa_atexit
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 exit
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 fwrite
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.3.4 __fprintf_chk
0000000000000000  w   D  *UND*  0000000000000000              _ITM_registerTMCloneTable
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 mbsinit
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 iswprint
0000000000000000  w   DF *UND*  0000000000000000  GLIBC_2.2.5 __cxa_finalize
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.3   __ctype_b_loc
0000000000207228 g    DO .bss   0000000000000008  GLIBC_2.2.5 stdout
0000000000207220 g    DO .bss   0000000000000008  GLIBC_2.2.5 __progname
0000000000207230  w   DO .bss   0000000000000008  GLIBC_2.2.5 program_invocation_name
0000000000207230 g    DO .bss   0000000000000008  GLIBC_2.2.5 __progname_full
0000000000207220  w   DO .bss   0000000000000008  GLIBC_2.2.5 program_invocation_short_name
0000000000207240 g    DO .bss   0000000000000008  GLIBC_2.2.5 stderr
110
追加された
@ Barleymanには、OpenWRT、yocto、uClinux、uclib、busybox、microcoreutils、およびその種の環境用のその他のソリューションがあります。あなたの関心を持って投稿を編集しました。
追加された 著者 Calvin,
@ Barleyman実際、gccが非常に多くのメタデータを作成し、さらに動的リンクライブラリの再配置ロジックがバイナリに追加していることを知って驚いた。それがそんなに悪いであるというわずかな考えではありませんでした。
追加された 著者 Calvin,
最近64kB + 2kBのマイクロコントローラを使ってプログラミングを行ったが、28kBはそれほど小さくはないようだ..
追加された 著者 mujahidkhaleel,
いや、いや。例えば、Yoctoは64kB以上のヒープである1メガバイト以下に詰め込まれることがあります。私は簡単な協調的マルチスレッドシステムを書き、コードが上書きされないように保護するために内蔵のメモリ保護を使用しました。ファームウェアは現在55kBを消費しているので、オーバーヘッドを増やす余地はあまりないと言っています。それらの素晴らしい2kBのルックアップテーブル..
追加された 著者 mujahidkhaleel,
確かに@PeterCordesですが、Linuxが実行可能になるまでには、さらに多くのリソースが必要です。その価値があるために、C ++もその環境では実際には機能しません。とにかく、標準ライブラリではありません。 Iostreamは約200kBなどでちょうどいいです
追加された 著者 mujahidkhaleel,
@Barleyman:バイナリ実行可能ファイルサイズに最適化している場合は、45バイトのx86 ELF実行可能ファイルで true または false を実装し、実行可能コードをパックすることができます(4 x86命令) ELFプログラムヘッダの (コマンドラインオプションはサポートされていません!) Linux用の10代のELF実行可能ファイルを作成するためのWhirlwindチュートリアル(またはLinux ELFローダーの実装の詳細によっては避けたい場合は少し大きめにしてください:P)
追加された 著者 dordio,

実装はおそらくGNU coreutilsから来ています。これらのバイナリはCからコンパイルされています。デフォルトよりも小さくするための特別な努力は行われていません。

true の簡単な実装を自分でコンパイルしようとすると、サイズがすでに数KBになっていることに気付くでしょう。たとえば、私のシステムでは、

$ echo 'int main() { return 0; }' | gcc -xc - -o true
$ wc -c true
8136 true

もちろん、あなたのバイナリはもっと​​大きいです。それは、コマンドライン引数もサポートしているからです。 /usr/bin/true --help または/usr/bin/true --version を実行してみてください。

文字列データに加えて、バイナリにはコマンドラインフラグなどを解析するロジックが含まれています。これは明らかに最大約20 KBのコードを追加します。

For reference, you can find the source code here: http://git.savannah.gnu.org/cgit/coreutils.git/tree/src/true.c

32
追加された
これは --version 、Rui F Riberoのロジックです。あなた自身の答えを見てください。あなた自身が version_etc()関数に偶数 の名前を付けます。
追加された 著者 Mr. Kraus,
両方の関数の実際のmain()+ usage()+文字列は、20 KBではなく2 KB程度です。
追加された 著者 Calvin,
これは引数の論理ではなく、Cは非効率的ではない ...はインラインライブラリ/ハウスキーピングタスクです。ゴーリーの詳細については私の答えを見てください。
追加された 著者 Calvin,
@JdeBP version_etc()だけに名前を付けません。コンパイルされたversion_etcの長さはそれほど長くはありません。その作業の多くは動的にリンクされたライブラリを介して行われます。静的ライブラリは約9KBのコードを占め、 --version 以上のことをします。私の円グラフが間違っています...
追加された 著者 Calvin,
グラフはより明確になりました。
追加された 著者 Calvin,
--version/version機能用の@JdeBPロジック1KB、 - useage/ - help 833バイト、main()225バイト、バイナリ全体の静的データ1KB
追加された 著者 Calvin,
参考までに私は彼らのバグトラッカーでこれらのcoreutilsの実装について文句を言っていました、しかしそれを直すチャンスはありません。 "rel =" nofollow noreferrer "> lists.gnu.org/archive/html/bug-coreutils/2016-03/msg00040.ht‌ ml
追加された 著者 Sarge Borsch,
これは、コンパイルされたマシンコード(Cまたはそれ以外のもの)が膨大な量のスペースを必要とすることを示唆するので誤解を招きます。実際のサイズオーバーヘッドは、コンパイラによってインライン化される大量の標準Cライブラリ/ランタイムボイラープレートと関係があります。 Cライブラリ(glibc、おそらくあなたのシステムが何か他のものを使っているのを聞いたことがない限り)、そしてそれほどではないがELFヘッダ/メタデータ(それらの多くは厳密に必要ではないが十分価値があると考えられる)デフォルトのビルドに含める)。
追加された 著者 mtraceur,

それらをコア機能まで取り除いてアセンブラで書くと、はるかに小さいバイナリが得られます。

オリジナルのtrue/falseバイナリはCで書かれていて、その性質上さまざまなライブラリ+シンボル参照を引き込みます。 readelf -a/bin/true を実行すると、これは非常に顕著です。

352 bytes for a stripped ELF static executable (with room to save a couple bytes by optimizing the asm for code-size).

$ more true.asm false.asm
::::::::::::::
true.asm
::::::::::::::
global _start
_start:
 mov ebx,0
 mov eax,1     ; SYS_exit from asm/unistd_32.h
 int 0x80      ; The 32-bit ABI is supported in 64-bit code, in kernels compiled with IA-32 emulation
::::::::::::::
false.asm
::::::::::::::
global _start
_start:
 mov ebx,1
 mov eax,1
 int 0x80
$ nasm -f elf64 true.asm && ld -s -o true true.o     # -s means strip
$ nasm -f elf64 false.asm && ld -s -o false false.o
$ ll true false
-rwxrwxr-x. 1 steve steve 352 Jan 25 16:03 false
-rwxrwxr-x. 1 steve steve 352 Jan 25 16:03 true
$ ./true ; echo $?
0
$ ./false ; echo $?
1
$

あるいは、ちょっと厄介で独創的なアプローチ( stalkr )、独自のELFヘッダを作成し、 132 127 バイトに下げます。ここにコードゴルフの地域を入力しています。

$ cat true2.asm
BITS 64
  org 0x400000   ; _start is at 0x400080 as usual, but the ELF headers come first

ehdr:           ; Elf64_Ehdr
  db 0x7f, "ELF", 2, 1, 1, 0 ; e_ident
  times 8 db 0
  dw  2         ; e_type
  dw  0x3e      ; e_machine
  dd  1         ; e_version
  dq  _start    ; e_entry
  dq  phdr - $$ ; e_phoff
  dq  0         ; e_shoff
  dd  0         ; e_flags
  dw  ehdrsize  ; e_ehsize
  dw  phdrsize  ; e_phentsize
  dw  1         ; e_phnum
  dw  0         ; e_shentsize
  dw  0         ; e_shnum
  dw  0         ; e_shstrndx
  ehdrsize  equ  $ - ehdr

phdr:           ; Elf64_Phdr
  dd  1         ; p_type
  dd  5         ; p_flags
  dq  0         ; p_offset
  dq  $$        ; p_vaddr
  dq  $$        ; p_paddr
  dq  filesize  ; p_filesz
  dq  filesize  ; p_memsz
  dq  0x1000    ; p_align
  phdrsize  equ  $ - phdr

_start:
  xor  edi,edi         ; int status = 0
      ; or  mov dil,1  for false: high bytes are ignored.
  lea  eax, [rdi+60]   ; rax = 60 = SYS_exit, using a 3-byte instruction: base+disp8 addressing mode
  syscall              ; native 64-bit system call, works without CONFIG_IA32_EMULATION

; less-golfed version:
;      mov  edi, 1    ; for false
;      mov  eax,252   ; SYS_exit_group from asm/unistd_64.h
;      syscall

filesize  equ  $ - $$      ; used earlier in some ELF header fields

$ nasm -f bin -o true2 true2.asm
$ ll true2
-rw-r--r-- 1 peter peter 127 Jan 28 20:08 true2
$ chmod +x true2 ; ./true2 ; echo $?
0
$
26
追加された
また、この優れた記事もご覧ください。 tiny/teensy.html
追加された 著者 Xaisoft,
コメントは詳細な議論のためではありません。この会話はに移動されましたチャット
追加された 著者 Jamal,
64ビットの実行ファイルで int 0x80 32ビットのABIを使用しています。珍しいがサポートされている syscall を使用しても何も節約できません。 ebx の上位バイトは無視されるため、2バイトの mov bl、1 を使用できます。またはもちろん xor ebx、ebx が0の場合。 Linuxは整数レジスタを0に初期化するので、1 = __NR_exit(i386 ABI)を得るためには inc eax できます。
追加された 著者 dordio,
あなたのゴルフの例のコードを64ビットのABIを使うように更新し、 true のために127バイトにゴルフしました。 (32ビットのABIを使用したり、Linuxのゼロがプロセスの起動時に登録されるという事実を利用する以外に、 false に128バイト未満を管理する簡単な方法はわかりません。 mov al、252 (2バイト)は動作します。 push imm8 / pop rdi lea の代わりに動作します。 edi = 1 を設定しても、REXプレフィックスなしで mov bl、1 になる可能性がある32ビットのABIには勝てません。
追加された 著者 dordio,
l $(which true false)
-rwxr-xr-x 1 root root 27280 Mär  2  2017 /bin/false
-rwxr-xr-x 1 root root 27280 Mär  2  2017 /bin/true

私のUbuntu 16.04でもかなり大きいです。まったく同じサイズ?何がそれらをそんなに大きくしますか?

strings $(which true)

(抜粋:)

Usage: %s [ignored command line arguments]
  or:  %s OPTION
Exit with a status code indicating success.
      --help     display this help and exit
      --version  output version information and exit
NOTE: your shell may have its own version of %s, which usually supersedes
the version described here.  Please refer to your shell's documentation
for details about the options it supports.
http://www.gnu.org/software/coreutils/
Report %s translation bugs to 
Full documentation at: <%s%s>
or available locally via: info '(coreutils) %s%s'

ああ、真実と偽のための助けがあるので、それを試してみましょう:

true --help 
true --version
#

何もないああ、この他の行がありました:

NOTE: your shell may have its own version of %s, which usually supersedes
    the version described here.

私のシステムでは、/ usr/bin/trueではなく/ bin/trueです。

/bin/true --version
true (GNU coreutils) 8.25
Copyright © 2016 Free Software Foundation, Inc.
Lizenz GPLv3+: GNU GPL Version 3 oder höher 
Dies ist freie Software: Sie können sie ändern und weitergeben.
Es gibt keinerlei Garantien, soweit wie es das Gesetz erlaubt.

Geschrieben von Jim Meyering.

LANG=C /bin/true --version
true (GNU coreutils) 8.25
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later .
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Jim Meyering.

そのため、国際化のためのライブラリーにバインドして、助けがあり、バージョン情報があります。これはサイズの大部分を説明します、そしてシェルはとにかくそしてほとんどの場合その最適化されたコマンドを使います。

2
追加された
静的ライブラリ、およびelfメタダ用のバイナリの半分のサイズを含みます。私の答えを見てください。
追加された 著者 Calvin,