この章の目次にもどる
前頁:1.7 イベント管理にもどる
次頁:1.9 時計管理にすすむ

1.8 デバイス管理

1.8.1 デバイス管理機能の概要

デバイス管理機能では、 アプリケーションが各種のデバイスを統一的に取り扱うためのインタフェース機能、 および各種のデバイスに対応したデバイスドライバの登録/管理機能、 デバイスドライバとのインタフェース機能を提供している。 ここでは、アプリケーションインタフェースのみについて記述する。

また、OS 核のファイル管理機能やイベント管理機能では、 内部的にデバイス管理機能を経由して実際のデバイス操作を行なうことになる。

以下にデバイス管理機能の位置付けを示す。

デバイス管理機能の位置付け
図 14 : デバイス管理機能の位置付け

使用されるデバイスとしては以下のようなものがある。

  1. ビットマップディスプレイ (CRT, LCD, 等)
  2. キーボード (KD)
  3. ポインティングデバイス (PD)
  4. 各種ディスク装置 (FD, HD, OD, CD-ROM, 等)
  5. 各種のプリンタ
  6. 通信回線 (RS-232C, モデム、各種ネットワーク, 等)
  7. スピーカ
  8. イメージ処理装置
  9. その他

これらのデバイスのうち、 ビットマップディスプレイに対するアプリケーションインタフェースは、 デバイス管理機能とは独立したディスプレイ関数群として提供される。

これらのディスプレイ関数群は通常ドライバと一体となっているためドライバインタフェースも適用されないことになり、 デバイス管理機能とは基本的に独立した存在となる。

また、キーボードとポインティングデバイスに対するアプリケーションインタフェースはイベント管理機能として提供されるが、 ドライバとのインタフェースはデバイス管理でサポートしている。

各種のディスク装置の場合は、 通常はファイルとして使用されるが、 デバイスとして直接取り扱うためのアプリケーションインタフェースも用意される。

1.8.2 デバイス

デバイスのタイプ

デバイスは文字型デバイスとブロック型デバイスの 2 種類に分類される。 文字型デバイスは基本的にバイト単位でデータの入出力をシーケンシャルに行なうもので、 ブロックデバイスはデバイス毎に定められた大きさのデータブロック単位での入出力を行なうものでブロック単位でのランダムなアクセスが可能である。

各種のディスク装置はブロック型デバイスであり、 その他のほとんどのデバイスは文字型デバイスとなる。

また、デバイスは実デバイスと仮想デバイスに分類される。 実デバイスは物理的に実際に存在する通常の意味でのデバイスであり、 仮想デバイスはある種の資源を仮想的に 1 つのデバイスとして取り扱うものである。 仮想デバイスの代表的なものとしては画面上の 1 つのウィンドウを仮想的に1つのコンソールとして取り扱う仮想コンソールがあげられる。

論理デバイス名

デバイスは、 論理デバイス名と呼ばれるユニークな文字列によりシステムに登録され、 識別される。論理デバイス名は、基本的に以下に示す 3 つの要素から構成される。

種別:
デバイスの種類を表わす名称であり、"hd"(ハードディスク)、 "fd"(フロッピーディスク)等がある。
ユニット:
同一種別のデバイスが複数個存在する場合に、 個々のデバイスを識別するために使用され、通常、 "a" 〜 の英文字1文字が使用される。
サブユニット:
1つのユニットを論理的に複数に分割した場合に、個 々の分割単位を識別するために使用され、 "0"〜"254"の最大3桁の連続した数字で表わされる。

種別 + ユニット を、特にユニット名と呼び、OS で識別される単位となる。 OS 側では種別とユニットの区別は認識せず、 両方を合わせた名称であるユニット名により、 デバイスを識別する。ユニット名の最後の文字は数字であってはいけない。

論理デバイス名は、「ユニット名+サブユニット番号」で表わされ、 全体として最大 8 文字 ( 16 バイト ) の文字列となる。 サブユニット番号は前に 0 の付かない 3 桁までの数字である。 サブユニットが存在しない場合、 ユニット名がそのまま論理デバイス名と成り得る。 論理デバイス名の最後の文字が数字である場合は、 その論理デバイス名はサブユニットを表わしているものと見なされる。 サブユニット全体を表わす場合、 サブユニット番号は付けず、ユニット名そのものが論理デバイス名となる。

サブユニット ( パーティション ) を表わすために最大 3 桁の数字 ( サブユニット番号 ) が使用されるが、 サブユニットの分割を無視した 1 つのユニットとして取り扱う場合は、 サブユニット番号を含めない論理デバイス名 ( ユニット名 ) を使用する。これは、主にサブユニットの分割 (即ち、ディスクのパーティショニング ) を行なうために使用される。 なお、サブユニット番号を含まない論理デバイス名 ( ユニット名 ) を特に物理デバイス名と呼ぶ。

論理デバイス名
図 15 : 論理デバイス名

デバイスの登録は、実際には対応するデバイスドライバの登録を意味し、 デバイスドライバはユニット単位でユニット名により定義される。 即ち、1 つのユニットに含まれるすべてのサブユニットは 1 つのデバイスドライバで処理される。 通常、デバイスドライバはデバイスの種別に対応して用意され、 1 つのデバイスドライバで複数のユニットを処理する場合が多いが、 複数のユニットを複数のデバイスドライバで処理してもよい。

なお、今後単にデバイス名と言った場合は、 論理デバイス名を意味するものとする。

デバイスのアクセス制御

ディスク等のデバイスでは、システムの安全性を保つために、 そのデバイスを使用できるユーザを制限することが望ましい。 このため、プロセスのユーザレベルによるデバイスのアクセス制御が行なわれる。

各デバイスには以下に示す 1 ワードのアクセスモードが保持されており、 これによりデバイスのアクセス権がチェックされる ( これはファイルに於ける一般アクセスレベルに相当するものである )。

デバイスのアクセスモード
図 16 : デバイスのアクセスモード

即ち、読込可能なユーザレベルを持つプロセスからのみデバイスの読込用 ( D_READ) のオープンが可能で、 書込可能なユーザレベルを持つプロセスからのみデバイスの書込用 ( D_WRITE ) のオープンが可能となる。 また、 アクセス可能なユーザレベルを持つプロセスからのみ、 そのデバイスをファイルシステムとして取り扱うことが可能であり、 ファイルシステムの接続 / 切断 / 管理情報読込みのファイル管理のシステムコールを実行できる。

デバイスのアクセスモードは、 デバイスの登録時に R = W = F = 15 に設定される。 登録後はユーザレベル 0 のプロセスからのみ変更可能となる。

1.8.3 データ / 定数の定義

□ オープンモード

#define D_READ      0x0001      /* 読み込み専用オープン */
#define D_WRITE     0x0002      /* 書き込み専用オープン */
#define D_UPDATE    0x0003      /* 更新用オープン */
#define D_EXCL      0x0100      /* 排他モード指定 */
#define D_WEXCL     0x0200      /* 排他書き込みモード指定 */
#define D_NOWAIT    0x8000      /* 待ちなしモード指定 */

□ デバイス管理情報

typedef struct dev_state {
    UW  attr;       /* デバイスの属性 */
    UW  mode;       /* アクセスモード */
    W   blksz;      /* 物理ブロックサイズ( -1 :不明) */
    W   wprt;       /* 書き込み可否( 0:許可 1:禁止 -1:不明) */
} DEV_STATE;

□ デバイス情報

#define L_DEVNM     8   /* デバイス名の長さ */
typedef struct {
    UW  attr;           /* デバイスの属性 */
    W   nsub;           /* サブユニット数 */
    TC  name[L_DEVNM];  /* ユニット名 */
} DEV_INFO;

□ デバイスの属性 (attr : IIII IIII IIII IIII CRxx xxxx KKKK KKKK)

#define DA_DEVINFO      0xFFFF0000  /* デバイス/メディア依存情報 */
#define DA_CHARDEV      0x8000      /* 文字型デバイス */
#define DA_REMOVABLE    0x4000      /* 取り外し可能 */

#define DA_DEVKIND      0xFF        /* デバイス/メディア種別 */
#define DA_DEVTYPE      0xF0        /* デバイス/メディアタイプマスク */

#define DK_UNDEF        0x00        /* 未定義/不明 */
#define DK_DISK         0x10        /* ディスクタイプ */

#define DK_DISK_UNDEF   0x10        /* その他のディスク */
#define DK_DISK_RAM     0x11        /* RAM ディスク */
#define DK_DISK_ROM     0x12        /* ROM ディスク */
#define DK_DISK_FLA     0x13        /* FLASH ROM / SS ディスク */
#define DK_DISK_FD      0x14        /* フロッピーディスク */
#define DK_DISK_HD      0x15        /* ハードディスク */
#define DK_DISK_CDROM   0x16        /* CD-ROM */

□ サスペンド要求モード

#define D_SUSPEND   0x0001  /* サスペンドする */
#define D_DISSUS    0x0002  /* サスペンドを禁止する */
#define D_ENASUS    0x0003  /* サスペンドを許可する */
#define D_CHECK     0x0004  /* サスペンド禁止カウントを調べる */
#define D_FORCE     0x8000  /* 強制サスペンド指定 */

1.8.4 システムコール

opn_dev
 
デバイスのオープン

【形式】

WERR    opn_dev(TC* dev, W o_mode, W* error)

【パラメータ】

TC* dev       対象デバイス名

W   o_mode    オープンモード
    ( D_READ ‖ D_WRITE ‖ D_UPDATE ) | [ D_EXCL ‖ D_WEXCL ]
                            | [ D_NOWAIT ]
    D_READ    読み込み用オープン(Rアクセス権が必要)
    D_WRITE   書き込み用オープン(Wアクセス権が必要)
    D_UPDATE  更新(読み込み/書き込み)用オープン(RWアクセス権が必要)
    D_EXCL    排他モード
    D_WEXCL   排他書き込みモード
    D_NOWAIT  待ち無し指定
              文字型デバイスの場合、オープン時にデバイスがレディ状態になる
              まで待たずにリターンする。この指定でオープンした場合は、
              rea_dev(), wri_dev() で入力データが得られなかったり、出力が
              ビジー状態の場合には、待たずにリターンする。

W*  error     詳細エラー情報格納領域
              *error には、デバイスドライバから戻されたエラー情報が設定される。
              エラー情報の内容は、各デバイスドライバによって異なる。
              error が NULL の場合、エラー情報は格納しない。

【リターン値】

>0    正常(デバイスディスクリプタ)
<0    エラーコード

【解説】

指定したデバイスを指定したモードでオープンする。 デバイスをオープンするためにはオープンモードに対応するアクセス権が必要である。
排他モード、および排他書込モードはファイルに対するものと全く同様の機能であり、 1つのデバイスの同時オープンを制限することになる。 なお、物理デバイス名によるオープンは、対象とするユニットのすべての論理デバイス に対するオープンを同時に行なったものとみなされた排他制御が行なわれる。 例えば、"hda" の D_EXCL オープンは、"hda#" が1つもオープンされていない場合のみ可能であり、逆に "hda" をD_EXCL オープンした後は、どの "hda#" のオープンも不可となる。

【エラーコード】

ER_ACCES    : デバイス(dev)のアクセス権(R,W)がない。
ER_ADR      : アドレス(dev,error)のアクセスは許されていない。
ER_BUSY     : デバイス(dev)は既に排他的にオープンされている為、
              同時にデバイスをオープンすることができない、
              またはファイルシステムとして接続されている。
ER_DEV      : デバイス(dev)に対しての読込みまたは書込み操作は許されていない。
ER_ERDEV    : 装置異常が発生した。
ER_IO       : 入出力エラーが発生した。
ER_LIMIT    : 同時オープン可能な最大デバイス数を越えた。
ER_MINTR    : メッセージハンドラが起動されたため、処理が中断された。
ER_NODEV    : デバイス(dev)へのアクセスができない。
ER_NOEXS    : デバイス(dev)は存在していない(登録されていない)。
ER_NOMDA    : デバイス(dev)のメディアが存在しない。
ER_NOSPC    : システムのメモリ領域が不足した。
ER_PAR      : パラメータが不正である(o_modeが不正)。
ER_RONLY    : デバイス(dev)は書込不可である。
cls_dev
 
デバイスのクローズ

【形式】

ERR cls_dev(W dd, W eject, W* error)

【パラメータ】

W   dd      デバイスディスクリプタ

W   eject   イジェクト指定
            = 0  イジェクトしない
            ≠ 0  イジェクトする(イジェクト不可能なデバイスの時は無視)

W*  error   詳細エラー情報格納領域
            *error には、デバイスドライバから戻されたエラー情報が設定される。
            エラー情報の内容は、各デバイスドライバによって異なる。
            error が NULL の場合、エラー情報は格納しない。

【リターン値】

= 0    正常
<0    エラーコード

【解説】

オープンしたデバイスをクローズする。
デバイスをオープンしたプロセスが終了したときには、自動的にそのデバイスはクローズされる。

【エラーコード】

ER_ADR      : アドレス(error)のアクセスは許されていない。
ER_DD       : デバイスディスクリプタは存在していない。
ER_IO       : 入出力エラーが発生した。
ER_MINTR    : メッセージハンドラが起動されたため、処理が中断された。
rea_dev
 
デバイスのデータ読み込み

【形式】

ERR rea_dev(W dd, W start, B* buf, W size, W* a_size, W* error)

【パラメータ】

W   dd      デバイスディスクリプタ

W   start   読み込み開始データ番号
            ≧0      固有データ
            < 0     属性データ

B*  buf     読み込みデータの格納領域

W   size    読み込みデータサイズ
            固有データ   単位はデバイス依存
            属性データ   単位はバイト

W*  a_size  読み込んだデータサイズ
            固有データ   単位はデバイス依存
            属性データ   単位はバイト

W*  error   詳細エラー情報格納領域
            *error には、デバイスドライバから戻されたエラー情報が設定される。
            エラー情報の内容は、各デバイスドライバによって異なる。
            error が NULL の場合、エラー情報は格納しない。

【リターン値】

= 0    正常
<0 エラーコード

【解説】

オープンしたデバイスのデータを指定した開始データ番号から指定したサイズだけ読み込む。
size = 0 の時は実際の読み込みは行わずに、a_size に読み込み可能なデータサイズを戻す。
文字型デバイスの場合は、オープン時の指定により以下に示す動作となる(詳細は個々のデバイスに依存する)。
D_NOWAIT 指定の時:
その時点で得られたバイト数(size で指定したバイト数以下)のデータだ けを読み込む。何もデータが無い場合は、*a_size に0がセットされ、 ER_BUSY のエラーとなる。
D_NOWAIT 指定でない時:
size で指定したバイト数のデータが得られるか、データが終了となるま で待つ。

【エラーコード】

ER_ADR      : アドレス(buf,a_size,error)のアクセスは許されていない。
ER_BUSY     : データは得られなかった(D_NOWAITオープン時)
ER_DD       : デバイスディスクリプタは存在していない、
              または D_WRITE オープンである。
ER_DEV      : デバイス(dd)に対しての読込み操作は許されていない。
ER_ERDEV    : 装置異常が発生した。
ER_IO       : 入出力エラーが発生した。
ER_MINTR    : メッセージハンドラが起動されたため、処理が中断された。
ER_NODEV    : デバイス(dd)へのアクセスができない。
ER_NOMDA    : デバイス(dd)のメディアが存在しない。
ER_PAR      : パラメータが不正である(size< 0,start不正)。
wri_dev
 
デバイスへのデータ書き込み

【形式】

ERR wri_dev(W dd, W start, B* buf, W size, W* a_size, W* error)

【パラメータ】

W   dd      デバイスディスクリプタ

W   start   書き込み開始データ番号
            ≧0      固有データ
            < 0     属性データ

B*  buf     書き込みデータ

W   size    書き込みデータサイズ
            固有データ   単位はデバイス依存
            属性データ   単位はバイト

W*  a_size  書き込んだデータサイズ
            固有データ   単位はデバイス依存
            属性データ   単位はバイト

W*  error   詳細エラー情報格納領域
            *error には、デバイスドライバから戻されたエラー情報が設定される。
            エラー情報の内容は、各デバイスドライバによって異なる。
            error が NULL の場合、エラー情報は格納しない。

【リターン値】

=0   正常
<0   エラーコード

【解説】

オープンしたデバイスへ指定した開始データ番号から指定したサイズだけデータを書き込む。
size = 0 の時は実際の書き込みは行わずに、a_size に書き込み可能なデータサイズを戻す。
文字型デバイスの場合は、オープン時の指定により以下に示す動作となる(詳細は個々 のデバイスに依存する)。
D_NOWAIT 指定の時:
その時点で得られたバイト数(size で指定したバイト数以下)のデータだ けを読み込む。何もデータが無い場合は、*a_size に0がセットされ、 ER_BUSY のエラーとなる。
D_NOWAIT 指定でない時:
size で指定したバイト数のデータが得られるか、データが終了となるま で待つ。

【エラーコード】

ER_ADR      : アドレス(buf,a_size,error)のアクセスは許されていない。
ER_BUSY     : データは書き込めなかった(D_NOWAITオープン時)。
ER_DD       : デバイスディスクリプタは存在していない、
              または D_READ オープンである。
ER_DEV      : デバイス(dev)に対しての書込み操作は許されていない。
ER_ERDEV    : 装置異常が発生した。
ER_IO       : 入出力エラーが発生した。
ER_MINTR    : メッセージハンドラが起動されたため、処理が中断された。
ER_NODEV    : デバイス(dd)へのアクセスができない。
ER_NOMDA    : デバイス(dd)のメディアが存在しない。
ER_PAR      : パラメータが不正である(size< 0,start不正)。
ER_RONLY    : デバイス(dev)は書込不可である。
chg_dmd
 
デバイスのアクセスモード変更

【形式】

ERR chg_dmd(TC* dev, W mode)

【パラメータ】

TC* dev     対象デバイス名

W   mode    アクセスモード

【リターン値】

=0     正常
<0     エラーコード

【解説】

指定したデバイスのアクセスモードを変更する。 本システムコールはユーザレベル 0 のプロセスからのみ可能である。

【エラーコード】

ER_ACCES    : レベル 0 のユーザでない。
ER_ADR      : アドレス(dev)のアクセスは許されていない。
ER_NOEXS    : デバイス(dev)は存在していない(登録されていない)。
ER_PAR      : パラメータが不正である(modeが不正)。
dev_sts
 
デバイスの管理情報の取得

【形式】

ERR dev_sts(TC* dev, DEV_STATE* buf)

【パラメータ】

TC* dev 対象デバイス名

DEV_STATE* buf  デバイス管理情報の格納領域

typedef struct dev_state {
    UW  attr;       /* デバイスの属性 */
    UW  mode;       /* アクセスモード */
    W   blksz;      /* 物理ブロックサイズ(−1:不明) */
    W   wprt;       /* 書き込み可否(0:許可 1:禁止 ー1:不明) */
} DEV_STATE;

  attr   デバイスの属性を示す。
  mode   デバイスのアクセスモードを示す。
  blksz  デバイスの物理ブロックサイズをバイト数で示したもので、
         rea_dev(), wri_dev() での単位となる値である。
         文字型デバイスの場合は常に "1" となる。
  wprt   デバイスへの書込みが禁止されているか否かを示す状態であり、書込み禁止
         の時は "1" となり、書込み許可の時は "0" となる。

【リターン値】

=0    正常
<0    エラーコード

【解説】

指定したデバイスの管理情報を取り出す。

【エラーコード】

ER_ADR      : アドレス(dev,buf)のアクセスは許されていない。
ER_NOEXS    : デバイス(dev)は存在していない。
get_dev
 
デバイス名の取得

【形式】

WERR    get_dev(TC* dev, W devno)

【パラメータ】

TC* dev     デバイス名の格納領域

W   devno   デバイス番号

【リターン値】

≧0    正常(デバイスのサブユニット数)
<0    エラーコード

【解説】

指定したデバイス番号のデバイスのユニット名を取り出し、デバイスのサブユニット数を関数値として戻す。サブユニットが存在しないときは関数値は "0" となる。
指定するデバイス番号はデバイスイベントとして得られたデバイス番号である。

【エラーコード】

ER_ADR      : アドレス(dev)のアクセスは許されていない。
ER_NOEXS    : デバイス番号(num)は存在していない。
lst_dev
 
登録済みデバイスの取得

【形式】

WERR    lst_dev(DEV_INFO* dev, W ndev)

【パラメータ】

DEV_INFO*   dev   デバイス情報の格納領域(配列)
                  NULL  格納しない

typedef struct {
    UW  attr;           /* デバイスの属性 */
    W   nsub;           /* サブユニット数 */
    TC  name[L_DEVNM];  /* ユニット名 */
} DEV_INFO;

W          ndev   デバイス情報の格納領域(配列)の要素数
                  0  格納しない

【リターン値】

≧0    正常(登録されているデバイス数)
<0    エラーコード

【解説】

登録済みのデバイス(ユニット)の情報を取り出し、登録済みのデバイス(ユニット)数を関数値として戻す。
登録済みのデバイスの数が ndev より小さいときは登録されている数だけ dev に格納され、登録済みのデバイスの数が ndev より多い場合は ndev 個のみ dev に格納される。
dev = NULL または ndev = 0 は、登録済みのデバイスの数を取り出すために使用する。

【エラーコード】

ER_ADR  : アドレス(dev)のアクセスは許されていない。
ER_PAR  : パラメータが不正である(ndev< 0)。
sus_dev
 
サスペンド要求

【形式】

WERR    sus_dev(UW mode)

【パラメータ】

mode ::= ( D_SUSPEND ‖ D_DISSUS ‖ D_ENASUS ‖ D_CHECK ) | [D_FORCE]

    D_SUSPEND   0x0001  サスペンドする
    D_DISSUS    0x0002  サスペンドを禁止する
    D_ENASUS    0x0003  サスペンドを許可する
    D_CHECK     0x0004  サスペンド禁止カウントを調べる
    D_FORCE     0x8000  強制サスペンド指定

【リターン値】

≧0 正常 (D_CHECK のときはサスペンド禁止要求カウント数)
<0 エラーコード

【解説】

システムのサスペンドの制御を行う。
D_SUSPEND
サスペンドおよび強制サスペンド許可状態なら、サスペンドを行う。サスペンド状態から復帰(リジューム)すると、システムコールからリターンする。
D_DISSUS
サスペンドを禁止する。
D_ENASUS
サスペンドを許可する。 D_DISSUS の要求回数はカウントされ、同じ回数だけ D_ENASUS を要求して初めてサスペンドが許可される。
初期状態は、サスペンド許可である。
D_CHECK
現在のサスペンド禁止要求カウント数を調べ、リターン値に返す。0ならサスペンド許可状態である。
D_FORCE が指定されると、強制サスペンドに関する操作となる。
D_FORCE|D_SUSPEND
強制サスペンド許可状態なら、サスペンドを行う。D_DISSUS による通常のサスペンド禁止は無視される。
D_FORCE|D_DISSUS
強制サスペンドを禁止する。
D_FORCE|D_ENASUS
強制サスペンドを許可する。
D_FORCE|D_DISSUS の要求回数はカウントされ、同じ回数だけ D_FORCE|D_ENASUS を 要求して初めて強制サスペンドが許可される。 初期状態は、強制サスペンド許可である。
D_FORCE|D_CHECK 現在の強制サスペンド禁止要求カウント数を調べ、リターン値に返す。0なら強制サスペンド許可状態である。
サスペンドおよび強制サスペンドを禁止したプロセスが終了すると、そのプロセスが行った禁止要求は解除される。

【エラーコード】

ER_BUSY     : サスペンド禁止状態のためサスペンドできなかった。
ER_PAR      : パラメータが不正である。
ER_LIMIT    : サスペンド禁止要求カウントがシステムの制限を超えた。
ER_MINTR    : メッセージハンドラが起動されたため、処理が中断された。

この章の目次にもどる
前頁:1.7 イベント管理にもどる
次頁:1.9 時計管理にすすむ