web-dev-qa-db-ja.com

bashがncursesにリンクするのはなぜですか?

私は以前にこれに気づいたと思いますが、あまり考えたことはありません。今、私は興味があります。

> ldd /bin/bash
        linux-vdso.so.1 =>  (0x00007fff2f781000)
        libtinfo.so.5 => /lib64/libtinfo.so.5 (0x00007f0fdd9a9000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007f0fdd7a5000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f0fdd3e6000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f0fddbf6000)

Libtinfoはncursesの一部です。これはFedoraシステムですが、ubuntuでも同じです。raspbian(debianバリアント)ではlibncurses自体にもリンクしています。

これの理由は何ですか?私はbashが行ったすべてがlibreadlineで実行できると思いました(不思議なことに、リンクされていません)。これは単にその代わりになりますか?

11
goldilocks

bashを次のように実行する場合:

LD_DEBUG=bindings bash

GNUシステム、およびその出力のbash.*tinfoのgrepで、次のようなものが表示されます。

   797:     binding file bash [0] to /lib/x86_64-linux-gnu/libtinfo.so.5 [0]: normal symbol `UP'
   797:     binding file bash [0] to /lib/x86_64-linux-gnu/libtinfo.so.5 [0]: normal symbol `PC'
   797:     binding file bash [0] to /lib/x86_64-linux-gnu/libtinfo.so.5 [0]: normal symbol `BC'
   797:     binding file bash [0] to /lib/x86_64-linux-gnu/libtinfo.so.5 [0]: normal symbol `tgetent'
   797:     binding file bash [0] to /lib/x86_64-linux-gnu/libtinfo.so.5 [0]: normal symbol `tgetstr'
   797:     binding file bash [0] to /lib/x86_64-linux-gnu/libtinfo.so.5 [0]: normal symbol `tgetflag'

nm -D /bin/bashの出力から、bashがtinfoからのこれらのシンボルを使用していることを確認できます。

これらの記号のいずれかのマニュアルページを持参すると、それらの目的が明確になります。

$ man tgetent
NAME
   PC, UP, BC, ospeed, tgetent, tgetflag, tgetnum, tgetstr, tgoto, tputs -
   direct curses interface to the terminfo capability database

基本的に、bash、より可能性の高いreadline(libreadlineは静的にリンクされています)エディターは、それらを使用してterminfoデータベースにクエリを実行し、端末機能について調べ、ラインエディターを適切に実行します(適切なエスケープシーケンスを送信し、キープレスを正しく識別します)。任意の端末で。

Readlineが静的にbashにリンクされている理由については、readlinebashと同じ人物によって開発され、bashのソースに含まれていることに注意する必要があります。

システムにインストールされているbashとリンクするlibreadlineをビルドすることは可能ですが、そのバージョンが互換性のあるバージョンであり、それがデフォルトではない場合のみです。コンパイル時に_--with-installed-readlineを使用してconfigureスクリプトを呼び出す必要があります。

17

bashtermcapapplicationreadlineや他のいくつかのプログラムのように、screen経由です。ほとんどのLinuxベースのシステム(Slackwareを除く)では、ncursesがtermcapの基本的な実装であると考えられます。

tgetentのマニュアルページ (名前付きcurs_termcapこれはSVr4で行われた方法です... )さんのコメント:

これらのルーチンは、termcapライブラリを使用するプログラムの変換補助として含まれています。それらのパラメーターは同じであり、ルーチンはterminfoデータベースを使用してエミュレートされます。したがって、これらはterminfoエントリがコンパイルされたエントリの機能をクエリするためにのみ使用できます。

つまり、呼び出し側プログラムが返されたデータを詳しく調べず、端末の説明を読み取って画面にデータを書き込むために従来のtermcapインターフェイスを使用する場合、元のtermcapと同じように機能します。

ほとんどのtermcapアプリケーションはそれほどよく見えません(xtermはまれな例外です FAQを参照 )。したがって、bashはncursesで機能します。

ただし、termcapライブラリはncursesよりも小さいです。かなり前にそれが問題になり、 1997年以降 ncursesにはconfigureオプション--with-termlibがあり、termcapおよびterminfo固有の部分をライブラリとしてビルドします。より高レベルのcursesライブラリ。数年が経過し、Linuxベースのディストリビューションのいくつかはそれをパッケージに組み込んだ。

bashはcurses関数(libncursesなど)を使用しないため、libtinfoに対してのみリンクするのが妥当です。

readlinebashのtermcap固有の部分です(実際、最初にbashに遭遇したとき、そのtermcapの部分はhardcoded、公式のソースがtermcapを使用していたとしても—おそらくさらに数バイトを節約するためです)。 bashがバンドルされたreadlineでビルドされている場合、バンドルされたreadlineをインストールしても意味がないため、readlineは個別のライブラリとして表示されません。 (競合する可能性がある)共有ライブラリとして。ただし、(システムによっては)libtinfoが表示される場合があります。これは、ncursesがどちらか一方(分割されているかどうかに関係なく)で構築されているためです。両方ではありません。

2
Thomas Dickey