2

inb_p( ) でポートを読み取ろうとすると、セグメンテーション違反が発生します。Intel D525 デュアルコア システム (Advantech PCM 9389 SBC) で 2.6.6 カーネルを実行している Debian システムでこれをコンパイルしています。segfault を説明するサンプル プログラムを次に示します。

考えられる原因は何ですか?これを修正するにはどうすればよいですか?

現在、接続しているデバイスはありません。これはセグメンテーション違反を引き起こす可能性がありますか? ゼロまたはランダムなバイトのいずれかを取得することを期待していましたが、セグメンテーション違反は想定していませんでした。

私が試した他のこと:1)入力変数をcharではなくintとして宣言しました。2) ioperm() の代わりに iopl() を使用

/*
 * ioexample.c: very simple ioexample of port I/O
 * very simple port i/o
 * Compile with `gcc -O2 -o ioexample ioexample.c',
 * and run as root with `./ioexample'.
 */
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/io.h>

#define BASEPORT 0x0100 /* iobase for sample system */
#define FLIPC 0x01
#define FLIPST 0x0
#define DIPSWITCH 0x25

int main()
{
char cinput;

  cinput = 0xff;
  setuid(0);
  printf("begin\n");
  /* Get access to the ports */
  if (ioperm(BASEPORT+DIPSWITCH, 10, 1)) 
  {
     perror("ioperm");
     exit(EXIT_FAILURE);
  }

  printf("read the dipswitch with pause\n");
  cinput = inb_p(BASEPORT+DIPSWITCH); // <=====SEGFAULT HERE

  /* We don't need the ports anymore */
  if (ioperm(BASEPORT+DIPSWITCH, 10, 0))
  {
     perror("ioperm");
     exit(EXIT_FAILURE);
  }

  printf("Dipswitch setting: 0x%X", cinput); 
  exit(EXIT_SUCCESS);
}

/* end of ioexample.c */

出力:

root@debian:/home/howard/sources# ./ioexample
begin
read the dipswitch with pause
Segmentation fault

編集: /proc/ioports はアドレス 0x100 で何もリストしなかったので、リストされている他のいくつかのポート アドレスを試しましたが、同じ結果でした。次に、既知のパラレル ポートの場所 (0x0378) への出力を試みることにしましたが、outb は segfault を引き起こしませんでした。ただし、0x378 または 0x379 を読み取ろうとすると、セグメンテーション違反発生しました。問題がハードウェアに関連しているのではないかと疑い始めています。

4

1 に答える 1

6

問題が見つかりました。inb_p() の呼び出しには、読み取るポートに加えて、ポート 0x80 へのアクセスが必要です。

どうやら、iopl() を試したときに、正しく呼び出せなかったようです。

次のコードは、segfault を排除しました。

  /* Get access to the ports */
  if (ioperm(0x80, 1, 1)) 
  {
     perror("ioperm");
     exit(EXIT_FAILURE);
  }
  if (ioperm(BASEPORT+DIPSWITCH, 10, 1)) 
  {
     perror("ioperm");
     exit(EXIT_FAILURE);
  }
于 2012-12-05T17:15:59.823 に答える