2008-04-22

C language

風邪が悪化orz orz
講義聴いてるだけなのに、
謎の全身筋肉痛w
でも、休むわけにはいかなんだ。



Eyebotは朝一で実験実にいき、
メニュー画面とかoption画面とか作成。
とりあえずはこれでプログラムは完成としよう。
さっさとレポートだ。

----- assignment -----
Operating System 2008/04/22

実践OS課題群
・プロセスのスケジューリングの中にある小さなプロセスにさらにスケジューリング機能を搭載?
・SH4aに移植(難易度:高)
・期限は最終講義日まで
・拡張機能も可
・スケジューリングのアルゴリズム変更(難易度:易)
・ある時間のときの設定を保存して、プログラムが動いたとき元に戻す。
→システムの復旧?
・メモリ内プロセスバック?
・使っていないprocessに対して、ある一定の時間がたったら勝手に圧縮するプログラム。
・終わったらレポート

----- note -----

システムコール = OSを呼び出すための関数
普通は、OSのデータ構造にはアクセスできない。

システムコールを介してのみ、アクセス可能。

Index
・カーネルの中身
・C言語の復習
-header, structについて

C言語とは
OSを作るのに適切な言語。
低水準programming

assembly言語はCPU毎にソースコードが違う
→移植するときは全部変更しなくてはいけない。

C言語の場合、大抵使いまわせる。
→移植するときの楽。

C言語には予約語が一杯ある。
→JAVAに似ているが、CLASSの概念はない。

C言語は分割しても一括してもどちらでも大丈夫。
→どの関数をどのファイルに置くかを考える必要がある。

Structure
-宣言部
-main関数
-そのほかの関数

C言語を使うときは、型のbyte数を把握する必要がある。
JAVAの"NEW"に近いallocateをするためには、
sizeof(型)をやって自分でbyte数を確保する必要がある。

・auto(自動変数)
関数内部の変数とか。
関数から出たら、解放する。

・static(静的変数)
呼び出すかどうかに関わらず、いつでも存在する。

EX:staticで大きい配列はダメ

・Register(レジスタ変数)
register上に置くので、早くなるかもしれない。
現在は、compilerが勝手にやってくれるので、
使っても無視されることがしばしばある。

・exterm(外部参照変数)
プログラムの外に変数を書く。
グローバル変数 = static変数

main()内はauto変数
関数内の変数をstaticにすると、以前使ったときの
結果が残っている。

int foo(void)
int main()
引数の数は自分で数える。

GNU gccは良いが、他のコンパイラには
引数をカウントしないものもある。
→clashしてdownする可能性がある。

・prototype宣言
int foo(int);
compilerがcheckしてくれる。

Ex:型のミス
void foo(void);
int x = foo;

---------------------------------

・C言語のsequence

C sourve(*.c)
↓ 
↓ preprocessor

preprocessor後のsource(*.i)

↓ C compiler

Object file
↓ linker
↓←←←←←←library

実行ファイル


・header
#include "queue.h"

preprocessorがlibraryの中にある"queue.h"を
ソースファイル内に展開する。

・マクロ展開
#define MAX 10
MAXを10に置き換える

#define putchar(x) fputc(x, stdout)
xは引数としてマクロ展開する。

用途:何行も使うものをまとめるときに使う。
「何故methodにしないのか」
methodの呼び出しのために、サイクルカウント値を消費してしまい、
動作が遅くなるから。

OSでは、致命的。C言語では重要な部分。
→overflowはなるべく少なくする。

・他の記号
#include"hoge.h"
#if DEBUG == TRUE
print("value = %d\n", val);

→hoge.hが
#define DEBUG TRUEならば
print文がマクロ展開される。

→#include"hoge.h"の文があるかどうかで
実行の有無がわかる。

debugに便利!

・gcc -DTEST ~~~
オプションの-DTESTがあれば
#ifdef TEST以下の文が展開
そうでなければ
#else以下の文が展開される。

用途:
#ifdef LINUX #else WINDOWS
Linux用とwindows用にわけてマクロ展開させることが可能。

・#incledeファイルの場所
→/usr/include/
or
/usr/include/sys/
and
/usr/include/linux/

・include fileのpathを指定したいとき
gcc -I/usr/local/hoge.h


・ifdef~else~endif
#ifdef MAIN
/* MAIN が #define してあったらここの部分がコンパイルされる。#define されていなかったらここの部分は無視される */
#else
/* MAIN が #define されていなかったらここの部分がコンパイルされる。#define してあったらここの部分は無視される */
#endif


・Compilerとlink
実行ファイルの中身
hm -g a.out | grep't'
00001c64 T __darmin_~~~
00001d44 T _main
0000166c T start 
プログラムが実行させるときは、まず最初にstartを探す!
startの位置をprogram counterに設定する。

※start -> _mainまでに
色々と初期化している。
mainかんすを呼ぶためにlibraryの中で、
色々と初期化されている。

・動的リンク
必要になったときにlibraryを呼ぶ
複数のプログラムから同じlibraryを使う場合、
共有ライブラリにする

*.so (shared object)

・コンパイラの最適化
program -> binaryにする場合
defaultで -O2 optionが入る。
→-O3以上にしても、あまり結果は変わらない。

・library
-lnew 自分が定義したもの?

-L/usr/local/mylibs
↑このdirectoryの中から優先的に探しだしてlinkする。

・libraryを作る場合
gcc -c newlib.c
ar rcs libnew.a newlib.o
で"new"ライブラリにnewlibを追加
nm/usr/lib/libc

・静的リンク
全部取り込む
→programが大きくなりやすい!注意!

・構造体
データ構造のみを定義。

struct tag名{
type member1;
type member2;
};

struct log{
char time[10];
long ch0;
long ch1;
};
↑この場合
1 structure = 10B+4B+4B = 18B

struct log logger1, logger2;
typedef struct{
~~
~~
~~
}LOG;

LOG logger1;
LOG logger2;
→structを宣言しないで済む。
typedefが主流。

・Pointer
※2000番地に10が入っているものとする。
int a;
int *p;
p=2000;
p=&a;

int *p;
int c = *p;
→integer型のpointerに10が入る。

func(&val);

→OSがCで書かれている理由の一つ
→pointer

予断:javaの場合classはcall-by-referenceになる

☆文字列の最後は必ず'0'が入っている。
"abcd"

'a'+'b'+'c'+'d'+'0'

while(*str) str++;
→文字列を読み終わったら0が入る
→偽になる→while文終了

予断:NULL = 0


・配列とポインタ
&array[0] と arrayは同じ意味
++arrayとすると
array[1]から読み込まれる。

データ構造の文だけincrementされるから。
→箱のサイズは気にしなくてもよい。


・character型の場合
char str[] ⇔ char *str
同じ

一般的に、*pには乗算や除算は使わない
structureをコピーするかpointerで指定するかで、
作業効率が大幅に変わってくる。

struct hm_time{
int hour;
int minute;
};

アクセスするには2つの方法がある。
①time.hour or time.minute

②void addtime(struct hm_time *t1, struct hm_time *t2){
t1->hour += t2->hour; ←メンバーアクセスと呼ぶ
t1->minute += t2->minute;
}

・command line
javaとはちょっと違う。
main(int argc, char argc[]){~~~

argc = コマンド(1)+引数の数
argv[] = コマンド及び引数へのポインタ

・pointerの危険性
異常終了or迷子のポインタ
エラーのとき
int *p;
int c = *p;
malloc <- 動的に領域を割り当てる。
malloc(10) = 10byte確保する
↑うまく確保できない場合は0を返すので
if文を使ってエラー処理することも可能!

☆確保したものはfree()で解放すること!
解放し忘れると、メモリがドンドン減ってくる!

0 件のコメント: