1 ファイル入出力と プロセス間通信 (1) 2004 年 12 月 10 日 海谷 治彦. 2 目次 まずはマニュアルをみよう. –2 章 システムコールインタフェース –3 章 汎用関数定義 アンバッファー化入出力 (Unbuffered I/O) –open, read, write... –lseek,

Slides:



Advertisements
Similar presentations
プログラミング演習 II 2005 年 1 月 19 日(第 9 回) 理学部数学科・木村巌. 前回までの復習 共用体( union type ) 共用体( union type ) 列挙 (enumerated type ) 列挙 (enumerated type ) 構造体、構造体のポインタ、
Advertisements

10: ファイル入出力 Linux にログインし、以下の講義ページ を開いておくこと teachers/w483692/CPR1/ C プログラミング入門 総機 1 ( 月 1) 1.
ネットワーク・プログラミ ング カーネルの役割とプロセス生成. 1.1 OS の役割 仮想マシン OS はハードウェアの多様性 をカプセル化し、利用者を 複雑な処理から開放する。 プロセス管理 時間多重化により各プロセ スに CPU を割当てる。 メモリ管理 メモリ空間の多重化により、 各プロセスにメモリを割当.
システムプログラミング 第7回、8回 ファイルシステム関連の システムコール
情報処理演習C2 ファイル操作について (2).
情報基礎演習B 後半第5回 担当 岩村 TA 谷本君.
システムプログラミング 第6回、7回 main関数の引数 usageメッセージ システムコールのエラーメッセージ ファイル
数理情報工学演習第一C プログラミング演習 (第3回 ) 2014/04/21
リダイレクト パイプ 標準入出力プログラム コマンド行引数 関数 system()
システムプログラミング 第5回 情報工学科 篠埜 功 ヒアドキュメント レポート課題 main関数の引数 usageメッセージ
第2回ネットワークプログラミング 中村 修.
Javaのインタフェース についての補足 2006年5月17日 海谷 治彦.
システムプログラミング 第11回 シグナル 情報工学科  篠埜 功.
第13回 プログラミングⅡ 第13回
オペレーティングシステム (OSの機能と構造)
第8回 プログラミングⅡ 第8回
担当:青木義満 情報工学科 3年生対象 専門科目 システムプログラミング システムプログラミング プロセス間通信(パイプ) 担当:青木義満
情報処理Ⅱ 第13回 2006年1月20日(金).
Linuxカーネルについて 2014/01.
オペレーティングシステム i386アーキテクチャ(2)
システムプログラミング 第11回 シグナル 情報工学科  篠埜 功.
ファイル操作と文字列の利用.
担当:青木義満 情報工学科 3年生対象 専門科目 システムプログラミング 第11回 プロセス間通信4 仮想FTPの実現 担当:青木義満
情報処理Ⅱ 第13回 2004年01月25日(火).
10: ファイル入出力 C プログラミング入門 基幹2 (月4) Linux にログインし、以下の講義ページ を開いておくこと
モバイルプログラミング第4回 Cプログラミングの基礎( 3 )
プログラミング 2 ファイル処理.
プログラミング論 ファイル入出力
システムプログラミング 第6回、7回、8回 情報工学科 篠埜 功.
ファイル入出力と プロセス間通信 (2) 2004年12月16日 海谷 治彦.
オペレーティングシステム2006 第1回 概要 2006年10月12日 海谷 治彦.
Cプログラミング演習.
マルチスレッド処理 マルチプロセス処理について
情報・知能工学系 山本一公 プログラミング演習Ⅱ 第2回 ファイル処理 情報・知能工学系 山本一公
プログラミング 4 記憶の割り付け.
リダイレクト パイプ 標準入出力プログラム コマンド行引数 関数 system()
プログラミング演習I 2003年6月25日(第10回) 木村巌.
画像処理プログラムの説明.
プログラミング論 ファイル処理 (中級編)
オペレーティングシステム イントロダクション
演習1の解答例の解説 2004年10月21日 海谷 治彦.
第7回 プログラミングⅡ 第7回
プログラミング論 ファイル入出力
演習1の解答例の解説 2006年11月8日 海谷 治彦.
TCP/IPとプロセス間通信 2007年1月12日 海谷 治彦.
システムプログラミング 第7回、8回 ファイルシステム関連の システムコール
第4回 ファイル入出力方法.
オペレーティングシステム i386アーキテクチャ(1)
システムプログラミング 第7回、8回 ファイルシステム関連の システムコール
OSが管理している、デフォルトの入出力装置 入力:stdin キーボード 出力:stdout モニタ(コマンドプロンプトの画面)
オペレーティングシステム (OSの機能と構造)
プログラミング演習I 2003年7月2日(第11回) 木村巌.
システムプログラミング 第6回 システムコールのエラーメッセージ ファイルシステム 情報工学科 篠埜 功.
オペレーティングシステムJ/K 2004年10月4日
ファイルの読み込み, ファイルからのデータの取り出し, ファイルの書き出し
11.1 標準ライブラリ関数 11.2 関数呼び出しのオーバーヘッド 11.3 大域変数 11.4 プロトタイプ宣言 11.5 関数引数
ネットワーク・プログラミング デバイスドライバと環境変数.
高度プログラミング演習 (11).
情報処理Ⅱ 2007年1月26日(金).
モジュール分割.
プログラミング 4 文字列.
アルゴリズムとデータ構造 補足資料6-1 「サンプルプログラムcat1.c」
ネットワーク・プログラミング 1対多のプロセス間通信.
オペレーティングシステム (OSの機能と構造)
Cp-1. Microsoft Visual Studio 2019 C++ の使い方 (C プログラミング演習,Visual Studio 2019 対応) 金子邦彦.
システムプログラミング 第11回 シグナル 情報工学科  篠埜 功.
四則演算,変数 入力文,出力文,代入文, ライブラリ関数
情報処理Ⅱ 2005年11月25日(金).
プログラミング演習II 2004年11月 16日(第5回) 理学部数学科・木村巌.
ネットワーク・プログラミング プロセスとファイルシステム管理.
Presentation transcript:

1 ファイル入出力と プロセス間通信 (1) 2004 年 12 月 10 日 海谷 治彦

2 目次 まずはマニュアルをみよう. –2 章 システムコールインタフェース –3 章 汎用関数定義 アンバッファー化入出力 (Unbuffered I/O) –open, read, write... –lseek, dup.... 標準入出力ライブラリ –fopen, fscanf, fprintf... 標準入力,標準出力,標準エラー –stdin, stdout, stderr 汎用ポインタ,システムデータ型 –void*, size_t, pid_t 等

3 Linux オンラインマニュアル いまさらですが・・・・ システムコールは 2 章,ライブラリ関数は主 に 3 章,コマンドは 1 章にあります. プログラマから見れば,システムコール ( 正確 にはシステムコールインタフェース ) もライブ ラリも単なるライブラリ関数です. しかし, OS の観点からは結構違うことを既に 理解してると思います. わかっている人にしかわからないような不親 切な記述が多いですが,それでもがんばって 読んで.

4 1 章 コマンド

5 2 章 システムコール

6 システムコールとライブラリの 違い システムコール ( インタフェース ) – カーネル (OS) に処理を依頼する. ユーザーモードでは直接扱えないハードウェア 等の資源へのアクセスを依頼する. ライブラリ関数 – カーネルに処理依頼の必要がない処理. 例えば, strlen() 等. – システムコールのラッパー open() に対する fopen() や, read() に対する fscanf() 等.

7 データがデバイスに届くまで ユーザープロセス カーネル ディスク 等 キャッシュ fprintf() 等 write() 等 sync(), fsync() 等 で同期 fflush() 等で同期 write() 等 バッファ

8 何段かのコピー 前スライドのように,データが物理的に記録 されるまで,何段かのコピーを作っている. – 加えて, CPU 側でさらにキャシュしている場合も ある. 少なくとも,標準入出力関数を使うより,シ ステムコールを使ったほうがコピー回数が少 ない. しかし,一般に標準入出力関数のほうが使い 勝手が良い場合が多い. – 書式設定等ができるなど.

9 ファイル関係のシステムコー ル int open(const char *pathname, int flags); – ファイルを開ける関数,いいかえれば, – プロセスがファイルを操作可能な状態にす る関数. – ファイルディスクリプタを返す. ssize_t read(int fd, void *buf, size_t count); – 読む関数. ssize_t write(int fd, const void *buf, size_t count); – 書く関数

10 シーケンシャルアクセス read もしくは write を行う場合, ( 後述の lseek 等を使わなければ, ) ファイルの中 身を順次アクセスしかできない. – 読みきった部分には戻れない. よってファイルの後戻りをしたい場合, – プログラム内に配列等として読み込んでお く. –lseek で読み位置を戻す. ただし,どんなファイルでも戻せるわけじゃな い. のどちらかの対処が必要.

11 ファイル・ディスクリプタ File Descriptor, 値は自然数値 (0, 1, 2...) 実体は,カーネル内にある file 構造体のイン スタンスを指している. file 構造体が保持している情報として重要なの は,「ファイル内の次に処理を行われる位 置」 複数のファイルディスクリプタで同一の file 構 造体のインスタンスを指すことができる. ⇒ 異なるファイルディスクリプタ番号で同じファイ ルを操作できる. ⇒ さらに,異なるプロセスが 1 つの file 構造体を共有 することもできる.

12 概念図 ( 全部カーネルの中 ) files_struct 構造体 メンバー変数 fd file 構造体 のインスタンス file 構造体 のインスタンス file 構造体 のインスタンス task_struct 構造体

13 lseek と dup off_t lseek(int fildes, off_t offset, int whence) – 特定のファイルディスクリプタの現在の読み出し 位置を変更する. – ファイルを配列のようにランダムアクセスできる 感じ. – 読み位置を変更できないファイルもある. ( パイプ 等 ) int dup(int oldfd) – ファイルディスクリプタの複製を作る. – 要は前ページの赤字の状態を作る. – 新たに利用されるディスクリプタの値は使ってい ない最小値となることが保障されている.

14 file 構造体の共有を例示 main(){ int newfd; char buf[100]; // 標準入力を dup で複製 if((newfd=dup(0))<0) exit(1); // dup fail. fprintf(stderr, "%d is duplicated.\n", newfd); // 複製した方で読み位置を進めて見る if((int)lseek(newfd, 200, SEEK_CUR)<0) exit(2); // seek fail. // 複製もとの 0 から値を読んで,標準出力に表示すると, read(0, buf, 100); write(1, buf, 100); // 先頭からではなく, // さっき 200B 進めた位置から 100B 表示される. }

15 データがデバイスに届くまで ユーザープロセス カーネル ディスク 等 キャッシュ fprintf() 等 write() 等 sync(), fsync() 等 で同期 fflush() 等で同期 write() 等 バッファ 再録

16 sync() と fsync() ともに,カーネル内のキャッシュを実 際のディスク等の装置に書き戻すシス テムコール. 無論,カーネルは定期的にこれらを実 行しているが,気になる人はアプリ ケーションから呼び出してもよいだろ う. sync() 等をする前に OS やマシンが異常終 了 ( 例えば停電 ) すれば,無論,データは 飛んでしまう.

17 標準入出力関数 fopen, fprintf, fscanf 等,お馴染みの関数 群. これらはストリーム ( データの流れ,と いうか列 ) に対する操作が中心となる. しかし,最大の特徴はバッファリング (buffering) である.

18 バッファリング (buffering) 前述の図のように,いきなり read/write システ ムコールを呼び出すのではなく, 記憶領域 ( コレのことを buffer と呼ぶ ) にデータ をある程度溜め込んでから入出力を行うこと. 結果としてシステムコールの呼び出し回数を 減らすことができ,プログラムを効率化でき る. しかし,現実には「書いたつもりのデータが すぐに書かれない」等が起こり,プログラマ には悩みの種. ( かも )

19 三種類のバッファリング 完全なバッファリング – バッファーのサイズ ( マクロ BUFSIZ で規定 ) 一杯に buffering を する. – ディスク上のファイルはこの方式がデフォルト. 行バッファリング – 改行がくるか buffer サイズを超えるまで buffering をする. – 端末装置とつながっている場合,この方式をとる. –stdin, stdout は通常コレ. アンバッファド –buffering をしない. – 可能な限り速やかに入出力を行う. –stderr は通常コレ. – 無論,システムコール呼び出しは頻繁になる.

20 バッファリング方式の変更 setbuf, setvbuf 関数 ( システムコールでは無論ない ) で, バッファリング方式を変更できる. 以下の例では stdout を強制的に完全バッファリングに している. 結果として, getchar() で文字を読んだあとの printf 命 令が実行されるまで, Hello は出力 ( 表示 ) されない. #include main(){ setvbuf(stdout, NULL, _IOFBF, BUFSIZ); printf("Hello "); getchar(); printf("World %d\n", BUFSIZ); }

21 ファイルディスクリプタとスト リーム FILE *fdopen (int fildes, const char *mode) – を用いて,ディスクリプタからストリームを生成 することができる. すなわち,ディスクリプタに使いやすい皮を かぶせることができる. fopen で開けられない特殊なファイル ( 通信装 置等 ) を使いやすくする際に用いられるらしい. int fileno( FILE *stream) – 逆にストリームからディスクリプタを得ることも できる.

22 ストリームの読書き 数えられないくらい関数があるのはご存知の 通り. 読み用 –fscanf, fgets, fgetc, fread.... 書き用 –fprintf, fputs, fputc, fwrite... バイナリファイルとテキストファイルの扱い 等,微妙に異なる場合があるので厄介なこと がある. –read, write システムコールの場合,バイナリ,テキ ストの区別はない.

23 ストリームの位置決め (1) long ftell( FILE *stream) – 現在の読み位置 int fseek( FILE *stream, long offset, int whence) – 特定位置まで移動させる. lseek に対応する. – しかし,テキストファイルでは多少問題が あるらしい. void rewind( FILE *stream) – 先頭までまき戻す. – これは結構よく見る.

24 ストリームに位置決め (2) int fgetpos( FILE *stream, fpos_t *pos) – 現在位置を *pos に保存. – あとで fsetpos で使う. int fsetpos( FILE *stream, fpos_t *pos) –*pos で指定された位置に移動する. 上記のほうが (1) のよりお勧めらしい.

25 使い分けについて read, write と fprintf, fscanf を混ぜて使う ことは不可能ではない. しかし,バッファリング問題もあり, わけわかんなくなるので, 1 つの入出力 先ではどちらかに統一したほうが良い だろう. アプリケーション寄りのものは標準入 出力関数を用いて,システム寄りはシ ステムコールを使うのが一般的 か・・・

26 汎用ポインタとシステムデー タ型 汎用ポインタ void* – どの型のポインタにもマッチする ( 明示的 にキャストしなくていい ) ポインタ. – 結果としてメモリを扱う関数では char* にか わり使われるようになった. システムデータ型 なんとか _t – 実体は int や long 等なのだが,ソースコード の移植性をよくするために,昨今では使わ れる. –sys/types.h に主に定義されているようだ. –ssize_t, pid_t, fpos_t 等.