オペレーティングシステム
オペレーティングシステム(operating system、略称:OS、オーエス)とは、コンピュータのオペレーション(操作・運用・運転)を司るシステムソフトウェアである。
オペレーティングシステムは通常、ユーザーやアプリケーションプログラムとハードウェアの中間に位置し、ユーザーやアプリケーションプログラムに対して標準的なインタフェースを提供すると同時に、ハードウェアなどの各リソースに対して効率的な管理を行う。現代のOSの主な機能は、などの補助記憶装置管理、仮想記憶などのメモリ管理、マルチタスクなどのプロセス管理、更にはGUIなどのユーザインタフェース、TCP/IPなどのネットワーク、などがある。パーソナルコンピュータからスーパーコンピュータまでの各種のコンピュータや、スマートフォンやゲーム機などを含む各種の組み込みシステムで、内部的に使用されている。
商品として(ないし製品として)のOSには、デスクトップ環境やウィンドウシステムなど、あるいはデータベース管理システム (DBMS) などのミドルウェア、ファイル管理ソフトウェアやエディタや各種設定ツールなどのユーティリティ、ウェブブラウザや時計などのアクセサリが、マーケティング上の理由などから一緒に含められていることもある。
スマートフォンのOSおよびそのシェアは、2021年9月時点でAndroidが約72%、iOSが約27%である。Androidは広い意味でのLinuxの一種であり、Linuxのカーネルを一部改編し他のオープンソース・ソフトウェアを組み合わせたものである。
ノートPCやデスクトップPCのOSおよびそのシェアは、2021年時点でWindows 75.4%、macOS 15.93%、ChromeOS 2.59%、Linux 2.33%となっている。macOSはFreeBSDを基にしたUnix系のOSである。
スーパーコンピュータのOSは、2000年ころはUNIXが9割ほどを占めていたが、その後の10年間でそのほぼ全てがLinuxに置き換わり、2021年現在では世界のスーパーコンピュータのTOP500のほぼ100%がLinuxである。
組み込みシステムでは組み込みオペレーティングシステムと呼ばれるOSを用いる。小規模な組み込みシステムのなかには明確なOSを内蔵していないものもあるので曖昧な面もあるが、組み込みOSを搭載しているものに関しては2019年時点でのシェアでTRON(トロン)系がおよそ60%であり、24年連続トップを占める。TRON系のなかでもITRON(アイトロン)が最も普及している。TRON以外では、次いでPOSIX系つまりUNIX系、Linux類などである。米リナックスワークスのLynxOS(リンクスオーエス)、米ウィンドリバーのVxWorks(ヴイエックスワークスト)、米シンビアンのSymbian OS(シンビアン・オーエス)など。
オペレーティングシステムの主な目的は、ハードウェアの抽象化、リソースの管理、そしてコンピュータ利用効率の向上である。
コンピュータごとに、製造元が異なるなどで、実現する機能は同じでも詳細な仕様に差異があるハードウェアが搭載されていることが多い。そのようなハードウェアの統一的で抽象化された利用方法を提供することで、アプリケーションソフトウェアの開発を容易にする。
複数のアプリケーションソフトウェアを同時に利用する際に、互いに独立して動作できるように資源を管理する。プログラムからの資源要求に競合が起きた場合には、待たせる、エラーを返すなど、適切に対処する。
複数のタスクを同時に実行する際に、資源割り当ての順番や処理の割り当て時間を工夫することで、全体のスループットを向上させる。これはデスクトップ環境ではあまり恩恵を感じることはないが、ウェブサーバやデータベースなど大量のアクセスをこなす用途などでは重要になる。
オペレーティングシステムはアプリケーションソフトウェアを動作させるのが第一の目的である。このためのインタフェースがアプリケーションプログラミングインタフェース (API) とアプリケーションバイナリインタフェース (ABI) である。カーネルはシステムコールによってアプリケーションにサービスを提供する。さらに基本ライブラリも含めた形でアプリケーションに対してAPI/ABIを提供する。アプリケーションによってはオペレーティングシステム上のミドルウェアやアプリケーションフレームワークなどをAPIとして使用する場合もある。
APIはプログラミングのためのインタフェースであり、プログラムを作成する際の規則を構成する。例えば、C言語での関数やFORTRAN/Pascalなどのライブラリ呼び出しの仕様といったものがそれにあたる。
一方、ABIはコンパイルされたソフトウェアがオペレーティングシステムの機能を呼び出す際のインタフェースであり、プロセスが動作する際の規則を構成する。例えば、Unix系のオペレーティングシステムはAPIがほとんど共通だが、ABIはオペレーティングシステムによって異なる。したがって、同じCPUを使ったシステムであっても、ABIが異なれば実行ファイルが異なる。ABIには、呼出規約、システムコールの方法などが含まれる。
なお、オペレーティングシステムの垣根を越えたABIもいくつか存在する。例えば、OCMP (Open Computing Environment for MIPS Platform) というMIPS系チップを使用したUNIX機によるバイナリ共通インタフェースが日本電気やソニー、住友電気工業、日本タンデムコンピューターズなどにより定義され、その定義に沿ったUNIXオペレーティングシステムが複数販売された。
ファームウェアとデバイスドライバの助けを借り、カーネルはコンピュータの全ハードウェアデバイスの基本的制御を提供する。RAM上のプログラムのメモリアクセスを管理し、どのプログラムがどのハードウェア資源へのアクセスを得るかを決定し、常に運用が最適化されるようCPUの状態を設定し、と共にディスク、磁気テープ、フラッシュメモリといった長期的不揮発性記憶装置でのデータの編成を行う。
オペレーティングシステムはアプリケーションプログラムとコンピュータハードウェアの間のインタフェースを提供し、オペレーティングシステムに組み込まれた規則や手続きに従うことによってアプリケーションプログラムはハードウェアとやりとりできる。オペレーティングシステムはまた、アプリケーションプログラムの開発と実行を簡素化するサービス群も提供する。アプリケーションプログラムの実行にあたって、オペレーティングシステムのカーネルがプロセスを生成する。プロセスの生成には、メモリ空間などの資源の割り当て、マルチタスクシステムでのプロセスへの優先度の割り当て、プログラムのバイナリコードのメモリへのロード、アプリケーションプログラムの実行開始といった仕事が含まれる。そうして初めてユーザーやハードウェアデバイスとやりとりを開始できる。
割り込みはオペレーティングシステムの要であり、オペレーティングシステムが周囲の環境と相互作用し反応するための効率的手段となっている。非常に小さなスタック(50バイトや60バイト)しか持たない古いシステムでは、オペレーティングシステムが対応しなければならないイベントの発生源を「監視」するポーリング方式を採用していたが、現代の大きなスタックを持つシステムでは一般的ではない。現代の多くのCPUは、割り込みをベースとしたプログラミングを直接サポートしている。割り込みが発生すると、その時点のレジスタコンテキストを退避し、そのイベントに対応した特定のコードを実行する。非常に基本的なコンピュータにもハードウェア割り込み機能があり、プログラマは特定の割り込みが発生したときに実行すべきコードを設定することができる。
割り込みを受信すると、コンピュータのハードウェアは実行中のプログラムを自動的に一時停止させ、状態を退避させ、その割り込みに事前に割り当てられているコードを実行する。これは例えば読書中に電話が鳴ったとき、本にしおりを挟み、電話に出るのに似ている。現代的なオペレーティングシステムでは、割り込みはオペレーティングシステムのカーネルが扱う。割り込みはコンピュータのハードウェアが発生させる場合もあるし、実行中のプログラムが発生させる場合もある。
ハードウェアから割り込みが発生した場合、オペレーティングシステムのカーネルがそのイベントにどう対応するかを一般に何らかの処理コードを実行して決定する。割り込みには優先順位があり、それに従って実行するコードが決定される。再び人間にたとえれば、電話が鳴ると同時に火災を知らせる火災報知器の非常ベルも鳴ったら、電話には出ずに避難するだろう。ハードウェア割り込みの処理は通常、デバイスドライバと呼ばれるソフトウェアに委任される。デバイスドライバはオペレーティングシステムのカーネルの一部という場合もあるし、別のプログラムという場合もあるし、混在する場合もある。デバイスドライバは割り込みによって得た情報を各種手段を通じて動作中のプログラムに中継する。
実行中のプログラムがオペレーティングシステムに対して割り込みを発生させる場合もある。例えば、あるプログラムがハードウェアにアクセスしたい場合、オペレーティングシステムのカーネルに対して割り込みを発生させ、結果として制御をカーネルに移す。するとカーネルは必要な処理を行う。また、プログラムがメモリなどの資源を追加で要求する場合、割り込みを発生させてカーネルに知らせる。ただし、それらは一般にシステムコールと呼ばれ、ハードウェア割り込みとは実装が異なることもある。
現代的CPUには複数の運用モードがある。その場合、少なくともユーザーモードとスーパーバイザモードの2つが存在する。スーパーバイザモードはオペレーティングシステムのカーネルが使用するモードで、ハードウェアに無制限にアクセスでき、メモリの読み書きの方法を制御したり、グラフィックスカードなどのデバイスとやりとりしたりできる。一方ユーザーモードはカーネル以外のほぼ全てが使用する。アプリケーションはユーザーモードで動作し、ハードウェアとのやりとりはカーネルを通す必要がある。CPUは2つ以上のモードを持つこともあり、古いプロセッサをエミュレートするのに使ったりする。
コンピュータが起動した際は、自動的にスーパーバイザモードで動作する。BIOSやEFI、ブートローダー、オペレーティングシステムのカーネルといったごく一部のプログラムがスーパーバイザモードで動作する。このようになっているのは、ユーザーモードの環境の初期化はその外側にあるプログラムでないと行えないためである。しかし、オペレーティングシステムが他のプログラムに制御を渡す際には、CPUをユーザーモードに設定できる。
ユーザーモードでは、プログラムが使用できるCPUの命令セットが制限されている。ユーザープログラムでユーザーモードを抜け出すには、割り込みを発生させ、カーネルに制御を戻す。そのようにしてハードウェアやメモリへのアクセスといったことへの独占的制御をオペレーティングシステムが保持している。
パーキンソンの法則によると、「メモリを拡張するとプログラムはそれに伴って拡大する」という。プログラマーは無限の容量と無限の速度のメモリを理想としている。コンピュータのメモリは階層構造になっていて、最も高速なレジスタから、キャッシュメモリ、RAM、最も低速なディスク装置がある。オペレーティングシステム内のメモリ管理部はこのようなメモリを管理するもので、利用可能な部分、割り当てと解放、主記憶と二次記憶との間でのスワップなどを制御する。
マルチプログラミング・オペレーティングシステムのカーネルはプログラムが使用中の全システムメモリの管理責任を負っている。それによってあるプログラムが既に別のプログラムが使用しているメモリを誤って使用しないようにしている。プログラム群は時分割で動作するので、それぞれのプログラムの独立したメモリアクセスが可能となっている。
協調的メモリ管理は初期のオペレーティングシステムでよく使われた方式で、全プログラムが自発的にカーネルのメモリ管理機構を使い、割り当てられたメモリをはみ出さないように動作することを前提としている。プログラムにはバグがつきもので、そのために割り当てられたメモリからはみ出すこともあるため、このようなメモリ管理は今では見られない。プログラムが異常動作すると、他のプログラムが使用中のメモリを書き換えることもあった。悪意あるプログラムやウイルスが意図的に他のプログラムのメモリを書き換えたり、オペレーティングシステム自体の動作を妨げたりすることも可能である。協調的メモリ管理では、たった1つのプログラムがおかしな動作をするだけでシステム全体がクラッシュする。
カーネルによるメモリ保護により、プロセスのメモリへのアクセスが制限される。メモリ保護には様々な技法があり、セグメント方式とページング方式が代表的である。どの技法でも何らかのハードウェアサポートが必要であり(例えば、80286のMMUなど)、あらゆるコンピュータがそのようなハードウェア機構を備えているわけではない。
セグメント方式でもページング方式でも、CPU内のユーザーがアクセスできないレジスタ群でユーザープログラムがアクセス可能なメモリアドレスの範囲を設定している。その範囲外のアドレスにアクセスしようとすると割り込みが発生してCPUがスーパーバイザモードに遷移し、カーネルがその状況に対処する。これをセグメンテーション違反と呼ぶ。セグメンテーション違反は一般にプログラムの間違いから発生するので、実行を継続するような対処は困難であり、カーネルは問題のプログラムを強制終了させ、エラーを報告するのが一般的である。
Windows 3.1からWindows Meまでは何らかのメモリ保護機構を備えていたものの、それを回避するのも容易だった。そのためセグメンテーション違反の発生を知らせる一般保護違反が考案されたが、それでもシステムがクラッシュすることが多かった。
ページングやセグメントによる仮想記憶を使用することで、カーネルは任意の時点で各プログラムが使用するメモリを選択でき、同じメモリ位置を複数タスクで使用させることも可能となる。
あるプログラムが使用可能な現在のメモリ範囲だが物理メモリが割り当てられていない位置にアクセスしようとしたとき、セグメンテーション違反のように割り込みによってカーネルに遷移する。このような割り込みをUnix系ではページフォールトと呼ぶ。
カーネルがページフォールトを受け付けると、そのプログラムに割り当てられた仮想メモリ空間の調整を行い、要求されたメモリアクセスが可能になるよう物理メモリを割り当てる。これにより、カーネルはそれぞれのアプリケーションへのメモリ割り当てを自由に決定でき、さらには実際には割り当てないでおくことも可能となる。
現代的オペレーティングシステムでは、相対的にアクセス頻度が低いメモリを一時的にディスクなどの二次記憶装置に退避させ、主記憶を他のプログラムのために空けることができる。これをスワッピングと呼び、限られたメモリを複数のプログラムで使用可能にし、メモリの内容を必要に応じて退避させたり復帰させたりできる。
仮想記憶により、実際に搭載しているよりも多くのRAMを使用しているかのような感覚でコンピュータを使用することができる。
コンピュータ上の各動作はバックグラウンドであっても一般のアプリケーションであっても、内部的にはプロセスとして動作する。DOSのような機能の限定されたオペレーティングシステムは一度に1つのプロセスしか実行できない。近代的なオペレーティングシステムは一度に複数のプロセスを動作させることができる(マルチタスク)。プロセス管理は複数のプロセスを実行するためにオペレーティングシステムが行う処理である。プロセッサを1つだけ持つ一般的なコンピュータでは、マルチタスクは高速にプロセスからプロセスへ切り替えを行うことで実現される。ユーザーがより多くのプロセスを実行すれば、個々のプロセスに割り当てられる時間は少なくなっていく。多くのシステムでは、これが音声の途切れやマウスカーソルの奇妙な動作などを引き起こす。一般的なプロセス管理は、プロセスごとに優先度を与え、それによって配分される時間を決めている。
オペレーティングシステムのカーネルにはスケジューラと呼ばれるソフトウェアが含まれており、プロセッサが実行すべきプロセスの順序と一度に実行する期間を決定している。スケジューラが選択したプロセスにカーネルが制御を渡し、それによってそのプログラムがCPUとメモリにアクセス可能になる。その後何らかの機構で制御がカーネルに戻され、スケジューラが再び新たなプロセスを選択する。このようなカーネルとアプリケーション間の制御の切り替えをコンテキストスイッチと呼ぶ。
プログラム群へのCPU時間の割当方法の初期のモデルとして協調的マルチタスクがある。このモデルでは、カーネルがあるプログラムに制御を渡すと、そのプログラムは時間を制限されることなく処理を行え、カーネルには自発的に制御を戻すことになっている。したがって、悪意あるプログラムやバグのあるプログラムがあると他のプログラムにCPU時間が割り当てられなくなり、無限ループに陥っている場合はシステム全体がハングアップする。
プリエンプティブ・マルチタスクでは、動作中のプロセスから任意の時点で制御を奪うことができ、全プログラムに所定のCPU時間を割り当てることが可能である。これを実現するためオペレーティングシステムはタイマ割り込みを使用し、所定の時間が経過したら割り込みを発生させてスーパーバイザモードに制御を戻させ、カーネルがスケジューラを呼び出す。
現代的オペレーティングシステムでは、プリエンプションの考え方をユーザーモード(アプリケーション)だけでなくデバイスドライバやカーネルコードに対しても適用し、リアルタイム性を向上させている。
ホームコンピュータなどのシングルユーザー・オペレーティングシステムでは、少数のよく評価されたプログラムしか使わないことが多く、協調的マルチタスクで全く問題ない。例外として AmigaOS は初期のバージョンからプリエンプティブ・マルチタスクを実現していた。Microsoft Windows で初めてプリエンプティブ・マルチタスクを実装したのは Windows NT だが、それが一般家庭向けに発売されるのは Windows XP からだった。
ディスクに格納したデータへのアクセスは、あらゆるオペレーティングシステムの中心的機能である。コンピュータはという形でディスクにデータを格納する。ディスクの内容は高速アクセス、高信頼性、ディスク領域の利用効率などを考慮して編成される。このファイルをディスクに格納する方式をと呼び、それによってファイルに名前と属性が付与される。また、ディレクトリあるいはフォルダと呼ばれる構造を使い、ファイル群を階層構造(木構造)内に格納できる。
初期のオペレーティングシステムは一種類のディスク装置しかサポートしておらず、ファイルシステムも一種類ということが多かった。初期のファイルシステムは容量や性能が低く、ファイル名やディレクトリ構造の面で制約が多かった。そういった制約はオペレーティングシステム自体の設計上の制約を反映していることが多く、複数のファイルシステムをサポートするのもオペレーティングシステムの制約の観点から非常に困難だった。
より単純なオペレーティングシステムではストレージへのアクセス手段が限られているが、UNIXやLinuxなどのオペレーティングシステムでは仮想ファイルシステム (VFS) という機構をサポートしている。UNIXなどのオペレーティングシステムは様々なストレージデバイスをサポートしており、それらの仕様やとは独立した共通のアプリケーションプログラミングインタフェース (API) でアクセスできるようにしている。そのためプログラムはアクセスしようとしているデバイスに関する知識を持つ必要がない。VFS機構により、プログラムはデバイスドライバとファイルシステムドライバを経由してシステム上のあらゆるデバイスと様々なファイルシステムにアクセス可能となる。
ハードディスクドライブなどの補助記憶装置には、デバイスドライバを通してアクセスする。デバイスドライバは担当するデバイスのインタフェースをよく理解しており、それをオペレーティングシステムが全ディスクドライブに共通で用意しているインタフェースに変換する。UNIXでは、それがブロックデバイスのインタフェースである。
Linuxを元プラットフォームとして開発されたものにはext2、ext3、ReiserFSなどがある。また、他のプラットフォームからXFS、JFS、ファイルシステムなどが移植され、NTFSも不十分ながら読み書きが可能である。
Macintoshではまず最初にMacintosh File System (MFS) が実装されたが、ディレクトリ機能を備えていなかったためファイルブラウザFinderでフォルダをエミュレーションしていた。その後Hierarchical File System (HFS) でディレクトリ機能を実装し、現在は改良を加えたHFS+が採用されている。現在macOSで読み書きが可能なものはHFS、HFS+、UNIX File System (UFS)、FATとなる。なおUFSの使用は一般でなく、FATへの対応は他プラットフォームとのデータ交換に用いられる。NTFSは読み込みのみが可能であり、書き込みについてはCommon Internet File System (CIFS) によるネットワークを介したものに限られる。
Windowsが標準で扱えるファイルシステムは、FAT、FAT32、NTFSである。NT系のWindowsではNT3.51まではOS/2標準のHPFSにアクセス可能だった。現在Windows上ではNTFSが最も信頼性と効率が高いものとして一般的に利用される。FATはMS-DOSから採用される古いファイルシステムであるが、パーティションやファイルサイズに制限があり、大容量化したハードディスクではあまり用いられない。このためファイルサイズの制限をなくしたexFATが新たに開発された。なお、exFATはVistaや7では標準で使えるが、XPでexFATを使うためには専用のプログラムを新たにインストールする必要がある。
FATはその仕様の制限から大容量のハードディスクには向かないが、その一方構造が単純でデジタルカメラや携帯電話などの組み込みシステム向けを含むさまざまなオペレーティングシステムで読み書き可能なことから、各種メモリカードやUSBメモリなどプラットフォームを跨ぐ用途においては主流である。なお、それらフラッシュディスクの大容量化に対応するため、マイクロソフトはFATを拡張したexFATというファイルシステムを発表している。
MacintoshからWindows等へファイルを転送すると、転送先のWindows側に本体とは別のファイルが出現することがある。これはHFSやHFS+のみがサポートするリソースフォークと呼ばれるデータ構造によるもので、Macintoshではそれらを一元的に管理を行うため一つの書類に見える。このように幾つものフォークを一つのデータに格納することをマルチフォークと呼び、もとのデータを改変することなくオペレーティングシステム独自の管理情報を容易に付与できる機能だが、実質的にMacintoshでしか利用できない。
ファイルシステムには、急な電源切断などによる障害へ対応する機構を持つものがある。
ジャーナルファイルシステムが最もよく採用される機構であり、その他にもZFSのように書き込み操作をトランザクションとして扱うものもある。これらを用いることで、障害復旧時のチェックを大幅に短縮する、または完全に不要にする。一方これらの機構を持たないファイルシステムでは、ファイルシステムの整合性を保つためストレージ全体を検査する必要がある。
デバイスドライバはハードウェアとのやり取りをするためのソフトウェアである。一般にハードウェアとの通信を行うインタフェースを持ち、ハードウェアの接続される何らかの通信サブシステムやバスを経由して通信を行う。コマンドをハードウェアに送り、データの送受信を行う。また、一方でオペレーティングシステムやアプリケーションに対するインタフェースも提供する。ハードウェアに強く依存するプログラムであり、オペレーティングシステムにも依存している。これによって、オペレーティングシステムやアプリケーションがハードウェアを使って動作することが容易になっている。ハードウェアの非同期的な割り込みの処理もデバイスドライバの役割である。
デバイスドライバの主たる設計目標は抽象化である。ハードウェアは用途が同種のものであっても、機種によって動作や性能などがそれぞれ異なる。新たな機能や性能を提供するハードウェアが登場したとき、それらは従来とは異なった制御方式を採用していることが多い。オペレーティングシステムを将来にわたってあらゆるハードウェアを制御できるように設計するのは困難である。従って、個別のハードウェアの制御をオペレーティングシステムから切り離す必要がある。デバイスドライバはオペレーティングシステムとのインタフェース(関数呼び出し)をデバイス固有の処理に変換することが主たる機能となる。理論的には、新たな制御方法の新しいハードウェアが登場しても、そのハードウェア用のドライバが古いオペレーティングシステムに対応していれば、古いオペレーティングシステムでもドライバだけ置き換えればハードウェアを制御可能となる。
Vista以前のWindowsやバージョン2.6より以前のLinuxカーネルでは、ドライバ実行は協調的だった。すなわち、あるドライバが無限ループに陥ると、システム全体がフリーズした。その後のバージョンではプリエンプションが可能となり、カーネルがドライバを中断させることができるようになった。
多くのオペレーティングシステムはTCP/IPプロトコルをサポートしている。歴史的に見れば、初期のコンピュータネットワークはモデムを使って電話回線で行われていた(BSC手順など)。その後、パケット通信が使われるようになり、IBMのSNAなどの各社独自のネットワークアーキテクチャが登場した。現在では、TCP/IPを中心とした通信が主流となっている。
通信プロトコルは、トランスポート層まではカーネル内モジュールとして実装し、プレゼンテーション層より上はシステムプロセスとして実装されるのが一般的である。セッション層の実装はシステムによって異なる。
このようなネットワーク機能により、異なるオペレーティングシステム間でネットワークを形成し、計算能力 (RPC)、ファイル、プリンター、スキャナーなどのリソースを共有できる。ネットワークにより、あるコンピュータのオペレーティングシステムが遠隔のコンピュータにあるリソースをあたかも自身に直接接続されているかのように透過的に利用できる。単純な通信に始まり、分散ファイルシステム、グラフィックスやサウンドといった機能の共有まで様々な応用がある。透過的アクセスの例としては、SSHによるコマンドラインの直接使用などもある。
オペレーティングシステムが関係するセキュリティ機能は、ユーザーがリソースへの何らかのアクセスを行う際に前もって認証し、そのユーザーのアクセスレベルを決定し、管理者の方針に基づいてアクセスを制限することである。
オペレーティングシステムは、処理を許可すべき要求と処理すべきでない要求を識別できなければならない。一部のシステムは単にユーザー名などで要求者を識別し、それによって特権の有無を判断する。要求者を識別する過程を「認証」(authentication) と呼ぶ。ユーザー名を示さなければならないことが多く、ユーザー名に続いてパスワードも必要な場合がある。別の認証方法として、磁気カードや生体データを使った「認証」(certification) を行うこともある。ネットワーク経由に接続などの場合、認証を全く行わずにリソースにアクセスさせることもある(ネットワーク上で共有されたファイルを読む場合など)。