2011.12.16
前へ
次へ
目次へ戻る
ホームページトップへ戻る

パソコンをつくろう!(パソコン自作のすすめ)
組み立てキットを使って自作に挑戦!

[第271回]


●パラレルポート出力プログラム(2)

このところ何回か書いております、Ubuntu11.10用のパラレルポート出力プログラムは、こちら(http://funini.com/kei/io/)のサイトにありましたものをほとんどそのまま拝借して使わせていただきました。

自分で考えたのではなくて人様がお書きになったものをそのまま拝借したりいたしますと、自分では十分理解しないままいただいてしまうことになりがちです。
ことにプログラムを書くときなどは、そういうことにならないよう、納得できるところまでよく考えることが必要だと思います。
そうすることで、借り物ではなくて、自分自身の知識として身につけることができます。

何回も登場しております、これがいわば借り物の、パラレルポート出力プログラムです。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/io.h>
#define OUT_PORT 0x378
 
int main(void){
  int i;
  ioperm(OUT_PORT, 4, 1);
  for(i = 0; i < 10; i++){
    outb(0xff, OUT_PORT);
    sleep(1);
    outb(0x00, OUT_PORT);
    sleep(1);
  }
  return 0;
}

ものごとが少しずつ理解できてきますと、借り物ゆえのおかしなところに気がつくようになります。

実は。
[第269回]で引用しました、iopermの英語のマニュアルページを読んでおりますときに、あれえ?
あることに気が付きました。

これが、その英文のマニュアルです。

#include <unistd.h> /* for libc5 */
#include <sys/io.h> /* for glibc */

int ioperm(unsigned long from, unsigned long num, int turn_on);

DESCRIPTION
ioperm() sets the port access permission bits for the calling process for num
bytes starting from port address from to the value turn_on. If turn_on is
nonzero, the calling process must be privileged (CAP_SYS_RAWIO).

(上記はhttp://www.kernel.org/doc/man-pages/online/pages/man2/ioperm.2.htmlからの引用です)

気が付いたのは#includeの記載です。

●libc5とglibc

#include <unistd.h> /* for libc5 */
#include <sys/io.h> /* for glibc */

for libc5 と for glibc のコメントがついています。

libc5とはなんぞや?
glibcとはなんぞや?
ネットで調べてみましたら。

libc5はリナックスの標準Cライブラリ(バージョン5)のことなのだそうで、glibcはGNU Cライブラリのことだそうです。
これだけではなんだかよくわかりませんから、英文のサイトを検索いたしました。

すると、こんな文をみつけました。
以下はLinux/m68k Frequently Asked Questions(http://www.linux-m68k.org/faq/glibcinfo.html)からの引用です。

What's the difference between glibc and libc6?
libc is the C library; basically, it contains all of the system functions that most (if not all) programs need to run on Linux. It's similar to a combination of dos.library and exec.library on Amigas, but it also contains a lot of things that are in the C runtime library (like, for example, ixemul.library or the .lib files included with SAS/C and other compilers for AmigaOS).

libc6 and glibc are the same version of libc; officially, it's version 2 of the GNU C Library (but it's the sixth major version of the Linux C library). You can read more about glibc at the GNU C Library pages.
(下線は筆者)

libc6(libcのバージョン6)とglibc(バージョン2)とは同じものなのだそうです。
libc5はその前のバージョンということになります。

その何が問題なの?
ということなのですが。
え?
皆様。
何か、お気づきになりませんでしょうか?

何回かお見せしております、パラレルポート出力プログラムの冒頭部分です。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/io.h>

下線で示しました2つの文にご注目ください。
これって、ここまでの説明のどこかにありませんでした?

そうです。
iopermの説明にありました。
上のところで、まさに問題にしておりました、この部分です。

#include <unistd.h> /* for libc5 */
#include <sys/io.h> /* for glibc */

で、この2つのコメント部分の由来をはるばる海外のサイトまで出かけて行って調べました結果、上のところに書きましたように、どうやらリナックス標準Cライブラリのバージョンの違いに由来するものらしいことがわかりました(ちょっと乱暴な切り方ですけれど)。

すると。
このパラレルポート出力プログラムはおかしくはないか?
単にライブラリのバージョンの違いによるヘッダーファイルを2つも抱え込む必要があるだろうか?

つまり上で引用した英文のマニュアルによれば、現在使っているOS(リナックス)のCライブラリがlibc5ならば、iopermはunistd.hにあるが、もしもCライブラリがglibcならばiopermはsys/io.hにある、というように読めます。

その解釈が正しいとすると、この2つのヘッダーファイルを共にインクルードするのはおかしいではないか?
という突然の降って湧いたような疑問です。

バージョンの違いから考えますと、どうもsys/io.hに一日の長がありそうな気がするのでありますが。
果たしてどうなのでしょうか。

そういうことになりますと、ここはやっぱり実際にプログラムを書いて確認してみるのが何よりの近道です。

●#include <sys/io.h>を削除してみる

まずは#include <sys/io.h>を削除したらどうなるか、を試してみました。
/* outtest3.c */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define OUT_PORT 0x378
 
int main(void){
  int i;
  ioperm(OUT_PORT, 4, 1);
  for(i = 0; i < 10; i++){
    outb(0xff, OUT_PORT);
    sleep(1);
    outb(0x00, OUT_PORT);
    sleep(1);
  }
  return 0;
}

これをコンパイルしました。


”outb”が未定義である、というエラーが出てコンパイルできませんでした。
”ioperm”は通ったようです。

うーん。
iopermと同じように考えて、実はoutbも探ってみたのですけれど。
以下はiopermの書式について参照したLinux Programmer’s Manual(英文サイト)のoutbについてのページ(http://www.kernel.org/doc/man-pages/online/pages/man2/outb.2.html)からの引用です。

NAME
outb, outw, outl, outsb, outsw, outsl, inb, inw, inl, insb, insw, insl,
outb_p, outw_p, outl_p, inb_p, inw_p, inl_p - port I/O
DESCRIPTION
This family of functions is used to do low-level port input and output. The
out* functions do port output, the in* functions do port input; the b-suffix
functions are byte-width and the w-suffix functions word-width; the _p-suffix
functions pause until the I/O completes.

They are primarily designed for internal kernel use, but can be used from user
space.

You compile with -O or -O2 or similar. The functions are defined as inline
macros, and will not be substituted in without optimization enabled, causing
unresolved references
at link time.

You use ioperm(2) or alternatively iopl(2) to tell the kernel to allow the
user space application to access the I/O ports in question. Failure to do
this will cause the application to receive a segmentation fault.
(下線は筆者)

残念なことに、ここにはiopermのページにはあった#include文がありません。
ですからどのヘッダーファイルに含まれているのか不明なのです。
しかし#include<sys/io.h>を削除したら、”outb”が未定義である、というエラーが出てしまったことからしますと、outbはsys/io.hで定義されているらしいということが推測されます。

ところで上記マニュアルでは−O または −O2 をつけてコンパイルしないと、unresolved referencesエラーになると書いてあります。
んでも#include<sys/io.h>を削除する前は−Oオプションをつけなくてもエラーにはならなかったわけですから、それはちょっと違うのではないかと。
でもまあ、ついでですから−O、−O2オプションをつけてやってみましたが。


結果は変わりませんでした。

ところで(このように「ところで」で話をつないでいくのは最もへたくそな書き方だということになっているのだそうでありますが)。
ここで出てきましたgccのオプション−O、−O2を、私は−0、−02だと思ってしまいました(このように書きましても、同じじゃないの?と思ってしまいますでしょう)。

おかしい、変だ、オプションを認識してくれない。
とそこでしばし悩んでおりました。
こんな具合です。


−Oは−0(数字のゼロ)ではなくてアルファベットOの大文字だったのですよね。
上でお見せしましたように、マニュアルページからコピーして貼り付けてみてはじめて0(ゼロ)ではなくてO(オー)らしいことがわかりました。
You compile with -O or -O2 or similar.

でももとのページをそのまま見ましたら、どう見たってゼロでありましょう?


せめてプログラムに関わる表記は一見してそれとわかる書体にしていただきたいものであります。

●ゼロとオーの区別

その昔、プログラムのコーディングが手書きでありましたころは、0(ゼロ)とO(オー)、あるいは2とZ(ゼット)などの区別を明瞭に書き分けることはプログラマのイロハでありました。


あー。
どんどん本題から離れていってしまうのでありますが。
ゼロとオーの区別ができる書体につきましてネットを検索いたしましたら、ここ(http://wiki.fdiary.net/font/?unixuser200403-1)に行きつきました。
そこで紹介されておりました「アニト等幅フォント」は、その両者の区別がつくフォントとのことでありました。
そのページにありましたアニト等幅フォントへのリンクは切れておりましたので、「アニト等幅フォント」でgoogle検索をいたしました。
こちら(http://www.type-labo.jp/Hanpuanito.html)のサイトです。
おお。
ゼロに斜線がついております。

http://www.type-labo.jp/GIF.IMAGE/Anitomono.gif)より一部分をコピーいたしました。

そういえばUbuntu11.10の「端末」ではちゃんと0(ゼロ)は区別がついておりました。

私はもっぱら斜線をつけておりましたが、真中に点をつけてゼロを表記するというルールもあったように記憶しております。
一方こちらはWindowsのMSDOSプロンプトです。

よく見れば幅の違いによって区別はつきますけれど、うっかりすると間違ってしまいそうです。

あっ。
そういえば…。
今、気がついたのですけれど。
これはUbuntu11.10のテキストエディタ(gedit)です。

なんと。
ちゃんとゼロは区別がつくようになっておりました。
さすが!
リナックスです。

余計なことばかりを書いておりますうちに、時間がなくなってしまいました。
今回は完全に脱線してしまいましたので、そもそもの本題につきましては次回にあらためて書くことにいたします。

パソコンをつくろう![第271回]
2011.12.16upload

前へ
次へ
目次へ戻る
ホームページトップへ戻る