システムプログラミング 第6回、7回、8回 情報工学科 篠埜 功.

Slides:



Advertisements
Similar presentations
システムプログラミング 情報工学科 篠埜 功 情報工学科 3 年生対象 専門科目 第5回 シェルスクリプトの続 き レポート課題 main 関数の引数 usage メッセージ.
Advertisements

オブジェクト指向言語・ オブジェクト指向言語演習 中間試験回答例. Jan. 12, 2005 情報処理技術基礎演習 II 2 オブジェクト指向言語 中間試験解説 1  (1) 円柱の体積(円柱の体積 = 底面の円の面積 x 高さ) を求めるプログラムを作成しなさい。ただし、出力結果は、入 力した底面の円の半径.
システムプログラミング 第10回 情報工学科 篠埜 功. 今回の内容 プロセス(続き) – execve システムコール 現在のプロセスを、引数に与えられたファイル(実行 形式ファイルあるいはシェルスクリプト等の実行可能 なファイル)を受け取り、現在のプログラムをそれで 置き換える(変身)。 fork.
情報処理概論Ⅰ 2007 第3回 2007/5/2 情報処理概論Ⅰ 第3回.
システムプログラミング 第7回、8回 ファイルシステム関連の システムコール
■パス検索 各種ファイルを操作するには、まずパス名をiノードに変換しなければならない。 以下にパス名をiノードに変換する関数の説明を行う。
コンピュータリテラシー 第3回授業の復習 基本的なUNIXコマンド
情報基礎演習B 後半第5回 担当 岩村 TA 谷本君.
システムプログラミング 第6回、7回 main関数の引数 usageメッセージ システムコールのエラーメッセージ ファイル
数理情報工学演習第一C プログラミング演習 (第3回 ) 2014/04/21
プログラミング入門2 第10回 動的な領域確保 情報工学科 篠埜 功.
プログラミング入門2 第10回 構造体 情報工学科 篠埜 功.
リダイレクト パイプ 標準入出力プログラム コマンド行引数 関数 system()
システムプログラミング 第5回 情報工学科 篠埜 功 ヒアドキュメント レポート課題 main関数の引数 usageメッセージ
システムプログラミング 第11回 シグナル 情報工学科  篠埜 功.
OSとコマンド OS:コンピュータを使うための基本プログラム コマンド:OS上で使用できる命令 OS本体であるカーネルの内部コマンド
第13回 プログラミングⅡ 第13回
記憶クラス 変数をどのような記憶領域に割り当てるかを指定するのが記憶クラス 記憶クラスには、自動変数、静的変数、外部変数などがある。
担当:青木義満 情報工学科 3年生対象 専門科目 システムプログラミング システムプログラミング プロセス間通信(パイプ) 担当:青木義満
アルゴリズムとデータ構造 補足資料6-3 「サンプルプログラムcat3.c」
担当:青木義満、篠埜 功 情報工学科 3年生対象 専門科目 システムプログラミング 第8回、第9回 シグナル処理 担当:青木義満、篠埜 功
システムプログラミング 第11回 シグナル 情報工学科  篠埜 功.
精密工学科プログラミング基礎 第9回資料 (12/11 実施)
10: ファイル入出力 C プログラミング入門 基幹2 (月4) Linux にログインし、以下の講義ページ を開いておくこと
情報工学科 3年生対象 専門科目 システムプログラミング 第5回、第6回 ヒアドキュメント レポート課題 情報工学科 篠埜 功.
プログラミング 2 ファイル処理.
プログラミング論 ファイル入出力
システムプログラミング 第9回 、10回 ハードリンク、シンボリックリンク プロセスの生成
システムプログラミング 第12回 プロセス間通信 情報工学科 篠埜 功.
情報・知能工学系 山本一公 プログラミング演習Ⅱ 第2回 ファイル処理 情報・知能工学系 山本一公
リダイレクト パイプ 標準入出力プログラム コマンド行引数 関数 system()
プログラミング演習I 2003年6月25日(第10回) 木村巌.
プログラミング入門2 第11回 情報工学科 篠埜 功.
演習1の解答例の解説 2004年10月21日 海谷 治彦.
プログラミング入門2 第11回 情報工学科 篠埜 功.
第7回 プログラミングⅡ 第7回
地域情報学 C言語プログラミング 第5回 ポインタ、関数、ファイル入出力 2017年11月17日
プログラミング論 ファイル入出力
アルゴリズムとデータ構造 補足資料6-2 「サンプルプログラムcat2.c」
演習1の解答例の解説 2006年11月8日 海谷 治彦.
プログラミング入門 第12回 情報工学科 篠埜 功.
システムプログラミング 第7回、8回 ファイルシステム関連の システムコール
精密工学科プログラミング基礎Ⅱ 第4回資料 今回の授業で習得してほしいこと: 文字列の扱い ファイル入出力の方法 コマンドライン引数の使い方
第14章 ファイル操作 14.1 ファイルへの書き込み 14.2 ファイルからの読み込み 14.3 ファイルへの追加書き込み
第4回 ファイル入出力方法.
C言語演習 情報ネットワーク特論.
情報工学科 3年生対象 専門科目 システムプログラミング 第4回 シェルスクリプト 情報工学科 篠埜 功.
システムプログラミング 第7回、8回 ファイルシステム関連の システムコール
第14章 ファイル操作 14.1 ファイルへの書き込み 14.2 ファイルからの読み込み 14.3 ファイルへの追加書き込み
Linux の世界に 触れてみよう! 情報実験 第 3 回 (2005/10/21)
プログラミング演習I 2003年7月2日(第11回) 木村巌.
システムプログラミング 第12回 プロセス間通信 情報工学科 篠埜 功.
プログラミング入門2 第13回、14回 総合演習 情報工学科 篠埜 功.
システムプログラミング 第6回 システムコールのエラーメッセージ ファイルシステム 情報工学科 篠埜 功.
ファイルの読み込み, ファイルからのデータの取り出し, ファイルの書き出し
システムプログラミング 第12回 プロセス間通信 情報工学科 篠埜 功.
ネットワーク・プログラミング デバイスドライバと環境変数.
プログラミング入門 第12回 情報工学科 篠埜 功.
システムプログラミング 第9回 、10回 ハードリンク、シンボリックリンク プロセスの生成
高度プログラミング演習 (11).
モジュール分割.
情報工学科 3年生対象 専門科目 システムプログラミング 第3回 makeコマンド 動的リンクライブラリ 情報工学科 篠埜 功.
情報工学科 3年生対象 専門科目 システムプログラミング 第3回 makeコマンド 動的リンクライブラリ 情報工学科 篠埜 功.
ネットワーク・プログラミング 1対多のプロセス間通信.
プログラミング入門2 第6回 関数 情報工学科 篠埜 功.
システムプログラミング 第11回 シグナル 情報工学科  篠埜 功.
プログラミング入門2 第5回 配列 変数宣言、初期化について
プログラミング入門2 第3回 条件分岐(2) 繰り返し文 篠埜 功.
第14章 ファイル操作 14.1 ファイルへの書き込み 14.2 ファイルからの読み込み 14.3 ファイルへの追加書き込み
岩村雅一 知能情報工学演習I 第7回(後半第1回) 岩村雅一
Presentation transcript:

システムプログラミング 第6回、7回、8回 情報工学科 篠埜 功

今日からの内容 Linuxのシステムコールを用いたCプログラムの作成 今日の内容 Cプログラムのmain関数の引数について Usage メッセージについて システムコールのエラーメッセージについて

Cのmain関数の引数について /* コマンド名および引数を表示 */ #include<stdio.h> int main (int argc, char *argv[ ]) { for ( ; *argv; argv++) printf ("%s\n", *argv); return 0; } (実行例) $ gcc 1.c $ ./a.out abc 234 ./a.out abc 234 $

main関数の第3引数 #include<stdio.h> main関数は第3引数に環境変数の情報の配列が渡される場合がある。(ISO規格で定められているわけではなく、処理系依存。) #include<stdio.h> int main (int argc, char *argv[ ], char *envp[ ]) { for ( ; *envp; envp++) printf ("%s\n", *envp); return 0; } 芝浦工大の環境では第3引数を受け取れる。第3引数はなくてもよい。環境変数はライブラリ関数getenv()で取得できるのでそれを使えばよい。

スタートアップルーチン すべてのC言語プログラムは、実行形式ファイルにするときに、スタートアップルーチンとリンクされる。 スタートアップルーチンは、/usr/lib/crt1.oにある。 $ nm /usr/lib/crt1.o で確認。この出力結果に U main という行が含まれており、スタートアップルーチンがmain関数を呼び出していることがここに反映されている。 スタートアップルーチン部分で引数の個数、引数の文字列配列、環境変数配列をmain関数に渡す。

コマンドのオプションについて オプションはハイフンのあとに1文字(-oなど) オプションのあとにオプションの引数があることもある (例) gcc –o main main.c など。 いくつかのオプションをまとめて記述することもある 例 ls –la は、ls –l –a をまとめて書いたものである。 --helpのように、ハイフンが2つの場合もある。(これは-h –e –l –pを-helpと書いた場合との区別のため)

Usage メッセージ オプションが正しく与えられなかった場合 (2) コマンドの引数に過不足があった場合 例えば、 $ cp のようにcpコマンドを引数無しで実行すると、Usageメッセージが表示される。

例(打ち込んで確認) (実行例) $ gcc usage.c $ ./a.out Usage: ./a.out filename #include<stdio.h> int main (int argc, char * argv[]) { if (argc!=2) fprintf (stderr, "Usage: %s filename\n", argv[0]); return 0; } (実行例) $ gcc usage.c $ ./a.out Usage: ./a.out filename

システムコールについて システムコールとは、カーネル内のコードを呼び出すためのC関数 ファイル、ネットワーク、キーボード等、ハードウェアとのやりとりはすべてカーネルが行う。ユーザはシステムコールを通じてカーネルにハードウェア操作を依頼する。 例えば、ファイルからデータを読み出す場合、getc, fgetcなどのライブラリ関数を呼ぶが、どんなライブラリ関数を呼んだとしても、最終的にはreadシステムコールが呼ばれ、カーネル内部のコードが実行される。

システムコールの実装 システムコールは、Cの関数であり、ライブラリファイル /usr/lib/libc.a に入っている。 $ ar t /usr/lib/libc.a | less でlibc.aの中身のオブジェクトファイルリストが表示される。write.o, read.oなどが入っている。

システムコールの番号 1 exit 2 fork 3 read 4 write 5 open 6 close 7 wait 8 creat 9 link 10 unlink 11 exec 12 chdir … 今後の講義でシステムコールを少しずつ紹介する。各システムコールのC関数が番号の設定を行うので番号は知らなくてよい。

システムコールのマニュアル システムコールはmanコマンドでマニュアルを表示できる。 例えば、 $ man -S 2 write $ man write とすると、writeコマンドのマニュアルが表示される。 $ man –a write とすると、writeの名前のマニュアルがすべて(PAGERがlessの場合はqを押すごとに)順番に表示される。 manコマンドの-Sの引数には分類番号を入れる。1はコマンド、2はシステムコール、3はライブラリ関数となっている。

システムコールのエラーメッセージ システムコールがエラーになった場合、エラー番号がerrnoという外部変数に代入されている。この番号を用いてエラーメッセージを出力するライブラリ関数perrorがあるのでそれを用いる。(errnoを直接使うプログラムは書かないほうがよい。) 例えば、$ ls aaa のように、lsコマンドで存在しないファイル名を指定した場合に、そのようなファイルは存在しないといったメッセージが出力される。ここではperror関数が用いられている。(そのようにlsコマンドが実装されている。)

ライブラリ関数perror void perror (char *s)

ファイルの1文字目を表示する例 (入力して実行、後で詳述) #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #define ERR -1 int main (void) { int fd, n; char c; if ((fd = open ("test", O_RDONLY)) == ERR) { perror ("open"); exit(1); } /* 続き */ if ( (n = read (fd, &c, 1) ) > 0 ) printf ("1文字目は%cです。\n", c); if (n==ERR) { perror ("read"); exit(1); } if (close (fd) == ERR) { perror ("close"); return 0;

演習課題 さきほどのプログラムを参考にして、テキストファイルの2文字目まで表示するプログラムをopenシステムコール, readシステムコールを使って作成せよ。 (さきほどと同様、printfは使うことにする。)

ファイル、プロセス OS(Linux)は、ファイルとプロセスを木構造で管理する。 まず、ファイルの木構造について学習する。

ファイル操作のシステムコール ファイルはOS(Linux)が管理している。 ファイルの操作等を行うためのシステムコールが提供される。 open, creat, close, read, write, lseek, dup, dup2等がある。 今日はopen, close, read, writeの解説を行う。この前に、まず、ファイルの基本事項の説明を行う。

ファイルとは UNIX系OSではファイルは1つの木構造で管理される。ルートディレクトリ以外は、すべてのファイルには親(ディレクトリ)がある。 ディレクトリもファイルの一種であり、そのディレクトリの子供のファイルの名前を保持しているファイルである。ディレクトリファイルも、(ルートディレクトリ以外は)何らかのディレクトリの子供である。 すべてのファイルはルートディレクトリから親子関係を辿ることによって到達できる。

デバイスファイル UNIXでは、端末、ディスク、磁気テープ、プリンタなどの周辺機器やメモリなどの装置のそれぞれに対応するファイルがある。特殊ファイル、あるいはスペシャルファイルとも呼ばれる。これらのファイルは通常/devディレクトリ以下にある。 デバイスは次の2種類に分けられる。  キャラクタデバイス --- 端末やプリンタなど、文字単位で入出力を行う装置  ブロックデバイス --- ディスクや磁気テープ装置など、データをある程度まとまったブロック単位で処理する装置 デバイスファイルも普通のファイルと同様に扱える(UNIXの利点)

ファイル名、パス名 ファイルには、名前がある。それをファイル名という。ディレクトリが違えば同じファイル名であっても別のファイルである。 パス名は、経路(パス)をファイル名の前につけたものである。 ファイル名は255文字以内、パス名は4095文字以内。大文字、小文字、数字、ピリオド、ハイフン、アンダーバーが使える。ファイル名に日本語は使えるが、現状では使わないのが無難。

絶対パス、相対パス 絶対パス --- ルートディレクトリから下向きに辿るパス 相対パス --- 現在のディレクトリからの相対的な経路で表すパス名、上に行くこともある。 ピリオド --- 現在のディレクトリ(current directory)を表す。 ピリオド2つ --- 親ディレクトリを表す。 (例) ../.. は2つ上の親のディレクトリを表す。

ピリオドの役割 ピリオド . はカレントディレクトリを表す。カレントディレクトリの実行形式ファイルを実行するとき、 $ ./test のようにして実行する。単にファイル名を $ test のように打った場合は、testという実行形式ファイルを、シェル(例えばtcsh)が、シェル変数PATHに格納されているディレクトリを順番に探すことになる。PATHに . が指定されていない場合は、カレントディレクトリにtestがあっても実行できない。また、testという名前の実行ファイルがシェルの内部コマンドだったり(実際は違うが)、他のPATHの(順番が先になっている)ディレクトリにあると、そちらが実行される。(実際に、/usr/bin/testが存在する。)

ホームディレクトリ ログイン時のディレクトリをホームディレクトリという。通常、/homeの下に作成される。(rootというユーザ(スーパーユーザ)のホームディレクトリは/rootである)。演習室では、(私sasanoの場合)/home/sitの下にある。ディレクトリを変更するコマンドがcd(シェルの内部コマンド)であり、これはchdirシステムコールを使って実現されている。ホームディレクトリはチルダ~で表される。

ファイルの保護 ファイルを他人(他のユーザ)に見られないように、permissionの指定ができる。 $ ls –al で確認できる。 d rwx rwx rwx の最初の桁以外は変更できる。 最初がdだとディレクトリ、-は一般のファイル。 そのあとは、owner, group, otherに対する読み書き実行の許可を表す。 (例) -rw-r—r--だと、一般ファイルで、所有者は読み書き、グループメンバーとその他のユーザは読み出しのみ許可。

Permissionの変更 Permissionの変更はchmodコマンドで行う。 $ chmod モード ファイル名 モードは、rwxの組を3桁の2進数と考え、これを8進1桁で表わし、8進3桁で指定することができる。例えば、rw-r--r--にしたい場合は644とする。 chmodは、chmodシステムコールを使って実現されている。

ファイルの所有者 ファイルには所有者、グループが関連づけられている。 $ ls –l で確認できる。 ファイルの所有者の変更はchownコマンド、グループの変更はchgrpコマンドで行う。これらはchownシステムコールを使って実現されている。ただし、所有者とスーパーユーザ以外は変更できない。

ディレクトリファイル ディレクトリファイルには、ファイル名からiノード番号(iノードはindex nodeの略)への対応がファイルの数だけ格納されている。(実際のデータ構造は、ハッシュテーブルや線形リストなど。) ファイルのiノード番号は $ ls –li 等、lsに-iオプションを与えると確認できる。

ファイルシステムの実装 ファイルシステムは、ブートブロック、スーパーブロック、iノードリスト、データブロックの4つの領域から構成される。 ブートブロック --- OSを起動するためのプログラムを格納。 スーパーブロック --- ファイルシステムの大きさ、ブロック数、ブロックサイズ、空きブロック、iノードリストの大きさ、空きiノードリストの情報などを格納。 iノードリスト --- iノードのリスト。iノードには各ファイルの種類、所有者、permission、変更時刻、ファイルサイズ、データブロック内の場所などが格納されている。 データブロック --- ファイルの中身が格納されている。

openシステムコール ファイルからのデータの読み込み、ファイルへのデータの書き込みをするには、まずファイルをオープンする。これを行うのがopenシステムコールである。 openシステムコールを使う場合、types.h, stat.h, fcntl.hをインクルードする。

openシステムコールの引数 openシステムコールは、パス名、フラグの2引数あるいは、これらにモードを加えた3引数で呼び出す。 パス名で指定されたファイルを、フラグに従ってオープンし、ファイル記述子(file descriptor, int型)を返す。フラグがO_CREATの場合、モードが必要。 ファイル記述子は、利用者ファイル記述子表の 何番目かを表す。 オープンするとは、データ入出力用のバッファを確保し、利用者ファイル記述子表中の1つの構造体を割り当て、構造体の各メンバーに初期値を設定することをいう。 利用者ファイル記述子表についてはdupシステムコールの説明時に説明する。

openシステムコールの代表的なフラグ O_RDONLY --- 読みだしのみ O_WRONLY --- 書き込みのみ O_RDWR --- 読み出し、書き込みの両方を行う O_CREAT --- ファイルが存在しない場合作成する。第3引数のモードでファイルのpermission等を設定する。 これらのフラグはfcntl.hに記述されているので、インクルードして使う。

モード openシステムコールの第3引数に与えられるモードでは、ファイルのpermissionおよびセットユーザIDビット、セットグループIDビット、stickyビット(/tmpなどで使用)を12桁の2進数で表す。代表的な数値はstat.hでマクロとして提供されているが、数値で直接指定してよい。 (例)S_IRWXU --- 所有者はread, write, executeができる。 その他にもあるが、 $ man –S 2 open で確認。

readシステムコール ファイルからデータを読み出すためのシステムコールがreadシステムコールである。 unistd.hをインクルードする。 ファイル記述子、データ格納領域へのポインタ、読み出しバイト数を引数に与える。返り値は読み出したバイト数。これが0のときはファイルの最後まで読み終わっているということになる。 readシステムコールが正常終了しなかった場合は-1が返ってくる。このときはperrorでエラーメッセージを表示する。

writeシステムコール ファイルへデータを書き込むためのシステムコールがwriteシステムコールである。 unistd.hをインクルードする。 ファイル記述子、書き込むデータが格納されている領域へのポインタ、書き込みバイト数を引数に与える。返り値は書きこんだバイト数。 writeシステムコールが正常終了しなかった場合は-1が返ってくる。このときはperrorでエラーメッセージを表示する。

closeシステムコール closeシステムは、ファイル記述子を引数に受け取り、そのファイルをクローズする。 クローズするとは、入出力用バッファを解放し、利用者記述子表内の構造体を解放することをいう。 (同時に開けるファイル数に制限があるので、閉じるのがよい。閉じなければプロセス終了時に閉じられる。)

例1:テキストファイルの先頭にaを書き込む #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> int main (void) { int fd, n; char c = 'a'; if ((fd = open ("test", O_WRONLY)) == -1) { perror ("open"); exit(1); } /* 続き */ if (write (fd, &c, 1) != 1){ perror ("write"); exit(1); } if (close (fd) == -1) { perror ("close"); return 0;

演習課題2 テキストファイル(ファイル名はtestなど)の先頭文字を読み取り、その文字を2文字目に書きこむ。Openシステムコールの第2引数(フラグ)はO_RDWRにする。 read, writeシステムコールを呼ぶたびに、読み書きのためのポインタ(システムコール内部のポインタ)が1つ進むので、readで読み取ったあとにwriteで書き込めば、2文字目に書きこまれることになる。

例2 /* 続き */ if ((fd = open (argv[1], O_RDONLY)) == -1) { perror ("open"); exit(1); } while ((n = read (fd, &c, 1) ) > 0) printf ("%c", c); if (n==-1) { perror ("read"); if (close (fd) == -1) { perror ("close"); return 0; /* テキストファイル全部表示 */ #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> int main (int argc, char * argv []) { int fd, n; char c; if (argc!=2) { fprintf (stderr, "Usage: %s filename\n", argv[0]); exit(1); }

複数バイトずつ読み込む readシステムコールで、複数バイト単位で読み込むこともできる。 readシステムコールの返り値は、 (1) 正の場合、読み込んだバイト数を表す。 (2) 0 の場合、ファイルの内容を既に全部読み終わっていたことを表す。 (3) -1の場合、システムコールが何らかの理由で正常終了しなかったことを表す。この場合はライブラリ関数perrorでエラー内容を表示するべき。 例えば、ファイルサイズ260バイトのファイルを100バイト単位で読み込むと、最後の回は60バイト(返り値も60)になり、その後は返り値は0となる。

例3 /* 続き */ if ((fd = open (argv[1], O_RDONLY)) /* テキストファイル全部表示 */ == -1) { perror ("open"); exit(1); } while ((n = read (fd, c, 100) ) > 0) if (write (1, c, n) != n) { perror ("write"); exit(1); }; if (n == -1) { perror ("read"); if (close (fd) == -1) { perror ("close"); return 0; } /* テキストファイル全部表示 */ #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> int main (int argc, char * argv []) { int fd, n; char c[100]; if (argc!=2) { fprintf (stderr, "Usage: %s filename\n", argv[0]); exit(1); } 1は標準出力

例4 /* 標準入力を標準出力へ書きだす*/ #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> int main (int argc, char * argv []) { int fd, n; char c[100]; while ((n = read (0, c, 100) ) > 0) if (write (1, c, n) != n) { perror ("write"); exit(1); }; /* 続き */ if (n == -1) { perror ("read"); exit(1); } return 0; 0は標準入力 1は標準出力

新しいファイルの作成 新しいファイルの作成は、openシステムコールの第2引数のフラグにO_CREATを指定する。(ファイルが存在していたらそのファイルを使う。存在しなければファイルを新しく作る。) 他のフラグと組み合わせて指定できる。組み合わせるときはビットのor演算子|を用いる。 例えば、write onlyで開きたい場合は、openシステムコールの第2引数に O_WRONLY | O_CREAT を指定する。さらに、存在しているときに内容を消したいときは O_TRUNCをさらに追加で指定する。

例5 /* 続き */ if ((fd = open (argv[1], O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1) { perror ("open"); exit(1); } while ((n = read (0, c, 100) ) > 0) if (write (fd, c, n) != n) { perror ("write"); exit(1); }; if (n == -1) { perror ("read"); if (close (fd) == -1) { perror ("close"); return 0; } /* 入力をファイルへ書きだす*/ #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> int main (int argc, char * argv []) { int fd, n; char c[100]; if (argc!=2) { fprintf (stderr, "Usage: %s filename\n", argv[0]); exit(1); } 0は標準入力

演習課題3 実行ファイルの引数に2つのファイル名を受けとり、1つ目のファイル(存在するファイル)のコピーを2つ目のファイルに作成するプログラムを作成せよ。(コピーコマンド) コピー先ファイルのopen時の引数 第2引数 --- O_WRONLY | O_CREAT | O_TRUNC 第3引数 --- 0644(8進表記) とせよ。これにより、コピー先のファイル名が存在していたら、内容が消去されてから書き込まれる。

レポート課題3 catコマンドの以下の機能を、システムコール(open, close, read, write)を使って実装せよ。 引数無しの場合 --- 標準入力を標準出力へコピー 引数がある場合(1個以上のファイル名を引数にとる) --- それらのファイルの内容を結合したものを標準出力に書き出す。 catコマンドを使った場合と挙動を比較し、同じであることを確認したのち提出すること。

レポートの提出方法 □ 下記のファイルを作成し、提出 kadai3.c, kadai3.txt □ 提出方法 システムプログラミング講義用の課題提出用フォルダ内にあるkadai3というフォルダの中に自分の学籍番号を名前とするフォルダを作成し、その中に上記ファイルを置く。kadai3.txt内に学籍番号、氏名、日付、および作成したプログラムの簡単な説明を記載する。 □ 提出期限   12月8日の講義開始時間まで。締め切り後に提出した場合、成績への反映を保証しない。

参考: ライブラリ関数を使った場合 int main (int argc, char * argv []) { FILE *fp; if (argc==1) filecopy (stdin, stdout); else while (--argc > 0) if ((fp = fopen (*++argv, "r")) == NULL) { printf ("cat: can't open %s\n", *argv); return 1; } else { filecopy (fp, stdout); fclose (fp); } return 0; #include <stdio.h> void filecopy (FILE *fpin, FILE *fpout) { int c; while ((c = getc(fpin)) != EOF) putc (c, fpout); } この実装では1バイトずつコピーしている。複数バイトまとめて読み込んで書き込んだ方が速い。