V6 unix vol.2 in okinawa

Post on 31-May-2015

3.205 views 1 download

Transcript of V6 unix vol.2 in okinawa

Rev.1.0

2012/12/15 2012/3/24 1

厚い本出ます

2012/3/24 2

ファイルシステムとは何か

計算機の基本的な機能

処理対象→処理→処理結果

メインフレームはこの処理に特化

処理対象と処理出力は永続性が必要

電源を切っても、情報が保存され続ける事

古典的な記憶装置を利用する

DISK

○ 効果・高速・ランダムアクセス

TAPE

○ 安価・低速・シーケンシャルアクセス

2012/3/24 3

2012/3/24 4

磁気DISKの動作原理

円盤上の媒体に磁性体を塗布

DISKを回転させる

ヘッド(コイル)

電磁誘導で発生した電流を読む

電流を流して磁場を発生させて円盤の一部を磁化/

消磁する

2012/3/24 5

磁気DISKの特性

物理的なアドレス

トラック/セクタ

論理的なアドレス

ブロック番号

シーク待ち

トラック間のピックアップ(コイル)の移動待ち

回転待ち

ピックアップの下を指定ブロックが通過するまでの時間

2012/3/24 6

周辺機器との転送

完了イベントの検出方式

ポーリング

○ ステータスをCPUサイクルで検査(ルックイン)

割り込み

○ 完了時に周辺機器のコントローラが割り込みを発生

データの転送方式

プログラムIO

○ CPUサイクルでメモリを読み書き

Direct Memory Access

○ 周辺機器のコントローラがメモリを読み書き

2012/3/24 7

PDP-11の標準磁気DISK装置

2012/3/24 8

PDP-11の標準磁気DISK RK-11

一台のコントローラに複数のDISKがつながる

DISKはアドレスを持ちコントローラが指定

SCSIに似ているw

2012/3/24 9

RK11 の制御レジスタ

メモリ空間から制御レジスタを読み書き

2012/3/24 10

RK-11の仕様

512バイト/セクタ (1word = 2byte)

約2.5Mバイト/ドライブ

2012/3/24 11

RKDA – DISK ADDRESS REGISTER

2012/3/24 12

5420: rkaddr(bp) 5421: struct buf *bp; 5422: { 5423: register struct buf *p; 5424: register int b; 5425: int d, m; 5426: 5427: p = bp; 5428: b = p->b_blkno; 5431: d = p->b_dev.d_minor; 5436: return(d<<13 | (b/12)<<4 | b%12); 5437: }

RKCS – CONTROL STATUS REGISTER

5092: #define IENABLE 0100 IDE

5093: #define WCOM 02 FUNCTION

5094: #define RCOM 04 FUNCION

5095: #define GO 01 GO

2012/3/24 13

GO - RKCS

操作する人が書き込む

Function の3ビットの機能を制御する

指定した処理が開始されるまで値はそのまま

2012/3/24 14

IDE - RKCS

1をセットすると完了時に220ベクタの割り込みを発生する

2012/3/24 15

rk.c - definitions 5363: #define RKADDR 0177400 5364: #define NRK 4 5365: #define NRKBLK 4872 5366: 5367: #define RESET 0 5368: #define GO 01 5369: #define DRESET 014 5370: #define IENABLE 0100 5371: #define DRY 0200 5372: #define ARDY 0100 5373: #define WLO 020000 5374: #define CTLRDY 0200 5375: 5376: struct { 5377: int rkds; 5378: int rker; 5379: int rkcs; 5380: int rkwc; 5381: int rkba; 5382: int rkda; 5383: };

2012/3/24 16

rk.c - kstart

5440: rkstart()

5441: {

5442: register struct buf *bp;

5443:

5444: if ((bp = rktab.d_actf) == 0)

5445: return;

5446: rktab.d_active++;

5447: devstart(bp, &RKADDR->rkda, rkaddr(bp), 0);

5448: }

2012/3/24 17

bio.c - devstart

5096: devstart(bp, devloc, devblk, hbcom)

5097: struct buf *bp;

5098: int *devloc;

5099: {

5100: register int *dp;

5101: register struct buf *rbp;

5102: register int com;

5103:

5104: dp = devloc;

5105: rbp = bp;

5106: *dp = devblk; /* block address */

5107: *--dp = rbp->b_addr; /* buffer address */

5108: *--dp = rbp->b_wcount; /* word count */

5109: com = (hbcom<<8) | IENABLE | GO |

5110: ((rbp->b_xmem & 03) << 4);

5111: if (rbp->b_flags&B_READ) /* command + x-mem */

5112: com =| RCOM;

5113: else

5114: com =| WCOM;

5115: *--dp = com;

5116: } 2012/3/24 18

5092: #define IENABLE 0100 5093: #define WCOM 02 5094: #define RCOM 04 5095: #define GO 01

RKADDRの操作 5363: RKADDR 0177400

5100: register int *dp;

5447: devloc = &RKADDR->rkda

5104: dp = devloc;

5105: rbp = bp;

5106: *dp = devblk; /* block address */

5107: *--dp = rbp->b_addr; /* buffer address */

5108: *--dp = rbp->b_wcount; /* word count */

5109: com = (hbcom<<8) | IENABLE | GO | ((rbp->b_xmem & 03) << 4);

5112: com =| RCOM; // readの場合

5115: *--dp = com;

2012/3/24 19

0177400

rkwc

rkcs

rker

rkds

rkba

rkda 5106: *dp = devblk

5107: *--dp = rbp->b_addr; /* buffer address */

5108: *--dp = rbp->b_wcount; /* word count */

5115: *--dp = com;

割り込みベクタ

2012/3/24 20

525 low.s

0525: . = 60^.

0526: klin; br4

0527: klou; br4

0528:

0529: . = 70^.

0530: pcin; br4

0531: pcou; br4

0532:

0533: . = 100^.

0534: kwlp; br6

0535: kwlp; br6

0539:

0540: . = 200^.

0541: lpou; br4

0542:

0543: . = 220^.

0544: rkio; br5

Vector device entry

060 Teletype input klin

064 Teletype output klou

070 Paper tape input pcin

074 Paper tape output pcou

100 Line clock kwlp

104 Programmable clock kwlp

200 Line printer lpou

220 RK disk driver rkio

2012/3/24 21

0576: .globl _rkintr 0577: rkio: jsr r0,call; _rkintr

rk.c - rkintr

5451: rkintr()

5452: {

5453: register struct buf *bp;

5454:

5455: if (rktab.d_active == 0)

5456: return;

5457: bp = rktab.d_actf;

5458: rktab.d_active = 0;

5469: rktab.d_errcnt = 0;

5470: rktab.d_actf = bp->av_forw;

5471: iodone(bp);

5472: rkstart();

5473: }

2012/3/24 22

ファイルシステムなしでDISKを使うと

情報を格納したブロックアドレスをメモ

ブロックアドレスを書き留める

複数のブロックの集合を書き留めてグループ化

ブロックの途中まで書き込んでいたら、位置をメモ

利用状況/の管理

複数の利用者がいたら?

○ ブロックはフラットな1次元配列

○ 上書きの危険

何時データを保存したのかなど属性はすべてメモ書き

2012/3/24 23

ソースを読む前に仕様を理解

2012/3/24 24

open(2)

open(name, mode)

char *name;

ファイルのopen

name はNULLで終端したpath name

ファイルディスクリプタを返す

modeは0:read, 1:write, 2:read and write

2012/3/24 25

write(2)

write(fildes, buffer, nbytes)

char *buffer

fildesはopen,creat,dup,pipeで生成したファイルディスクリプタ

プログラムのアドレスbufferからnbyteを書き込む

復帰値は書き込まれたバイト数

ファイルの512バイト境界に512xNバイトをかくと性能が良い

2012/3/24 26

read(2)

read(fildes, buffer, nbytes)

char *buffer;

Fildesからプログラムアドレスbufferへnbyte

読み込む

復帰値が0の場合はend-of-file

2012/3/24 27

seek(2)

seek(fildes, offset, ptrname)

Fildesのファイルポインタをoffsetにセットする

Ptrnameの値と設定するファイルポインタの関係は以下

0: offsetを指定 (絶対位置指定)

1: 現在のファイルポインタ+offsetに (相対位置指定)

2: ファイルの最後+offsetに

3,4,5 は1,2,3の0,1,2のoffsetの単位を512に

2012/3/24 28

fork(2)

fork()

プロセスを生成する唯一のもの

呼び出たプロセスと、生成されたプロセスにそれぞれ復帰する

2012/3/24 29

暗示的な仕様が多数

・プロセス空間を複写

・異なるのはpipとppid

・Open中ファイルの引継ぎ

親がopenしたファイルディスクリプタは子も利用できる

この仕様に依存した機能が多数ある

exec(2)

execl(name, arg0, arg1, ..., argn, 0)

char *name, *arg0, *arg1, ..., *argn;

プロセス空間をnameで指定したa.outで上書き

成功したexecを発行したプロセスには復帰しない

プロセスのIDが変更になる場合がある

SUID/SGID

2012/3/24 30

pipe(2)

pipe(fildes)

int fildes[2];

2つのファイルディスクリプタを返す

fildes[1]の先には4096バイトのバッファがあり、バッファがフルにならない範囲で書き込む事ができる

fildes[0]の先に同じバッファがあり、ここから読む事ができる

バッファの読み書きはブロッキングによるフロー制御が行われる

2012/3/24 31

dup(2)

dup(fildes)

int fildes;

ファイルディスクリプタを複写して、新しいディスクリプタを返す

複写先のディスクリプタは0から順に空き

ディスクリプタを探して最初に見つかったものを選択

2012/3/24 32

chdir(2)

chdir(dirname)

char *dirname;

current working directoryを変更する

2012/3/24 33

mknod(2)

mknod(name, mode, addr)

char *name;

Nemaで指定された新しいディレクトリまたは特殊ファイルを作成する

作られるファイルのmodeがファイルのモードとして指定される

Addrは特殊ファイルでのみ使われる

Rootのみが実行可能

2012/3/24 34

link(2)

link(name1, name2)

char *name1, *name2;

name1にname2をリンクする

リンクカウントは1増える

2012/3/24 35

unlink(2)

unlink(name)

char *name;

Nameで指定したファイルをディレクトリから取り除いてリンクカウントを1つ減らす

取り除いたけっか0だったらファイルを破棄する

ただし、そのファイルをプロセスが利用していたら、破棄はプロセスが利用をやめるまで待って、遅れて行われる

2012/3/24 36

確認 思い出してね

current working directory

SUID/SGID

一般ファイル、ディレクトファイル、特殊ファイル

shell (資料では触れていない)

パイプ・リダイレクト

標準入力、標準出力、エラー出力

cd, cwd

相対パス、絶対パス

2012/3/24 37

ソースを読む前に仕様を理解

2012/3/24 38

Path name - パス名

パス名はカーネル・システムコールが理解するファイルシステム上の名前空間

ファイル名を’/’で連結

ファイル名は最大14文字

一番右側にのみ一般ファイル、特殊ファイルを指定できる。ディレクトリファイルはどこにでも指定できる

パス名が’/’で始まると絶対パス、それ以外は相対パス

相対パスの起点がcurrent working directory

2012/3/24 39

ファイルディスクリプタ

open, creat, dup, pipeで獲得

Closeで解放

小さな整数

標準の環境でログインすると

0: 標準入力

1: 標準出力

2: 標準エラー出力

0-14の最大15個を獲得可能

fork/execで子に引き継ぐ

2012/3/24 40

一般ファイルのread/write/seek

バイト単位で操作可能

writeで必要な媒体を自動割り当て

操作毎にファイルポインタを更新

操作開始位置を毎回指定する必要なし

2012/3/24 41

処理を読む前にデータ構造を理解する

2012/3/24 42

Inode – ino.h (DISK inode)

5605: struct inode

5606: {

5607: int i_mode;

5608: char i_nlink;

5609: char i_uid;

5610: char i_gid;

5611: char i_size0;

5612: char *i_size1;

5613: int i_addr[8];

5614: int i_atime[2];

5615: int i_mtime[2];

5616: };

5617: /* --------------------------- */

5619: /* modes */

5620: #define IALLOC 0100000

5621: #define IFMT 060000

5622: #define IFDIR 040000

5623: #define IFCHR 020000

5624: #define IFBLK 060000

5625: #define ILARG 010000

5626: #define ISUID 04000

5627: #define ISGID 02000

5628: #define ISVTX 01000

5629: #define IREAD 0400

5630: #define IWRITE 0200

5631: #define IEXEC 0100

2012/3/24 43

ファイルの実態 DISK上では配列として格納しインデックがi番号

filsys - filsys.h

5561: struct filsys

5562: {

5563: int s_isize; /* size in blocks of I list */

5564: int s_fsize; /* size in blocks of entire volume */

5565: int s_nfree; /* number of in core free blocks (0-100) */

5567: int s_free[100]; /* in core free blocks */

5568: int s_ninode; /* number of in core I nodes (0-100) */

5569: int s_inode[100]; /* in core free I nodes */

5570: char s_flock; /* lock during free list manipulation */

5571: char s_ilock; /* lock during I list manipulation */

5572: char s_fmod; /* super block modified flag */

5573: char s_ronly; /* mounted read-only flag */

5574: int s_time[2]; /* current date of last update */

5575: int pad[50];

5576: };

2012/3/24 44

dir – param.h user.h

param.h

0106: #define ROOTINO 1 /* i number of all roots */

0107: #define DIRSIZ 14 /* max characters per directory */

user.h

0431: struct { /* current directory entry */

0432: int u_ino;

0433: char u_name[DIRSIZ];

0434: } u_dent

2012/3/24 45

u_ino 14文字固定長

data blocks

Inode blocks

Struct inode[]

媒体上のレイアウト

mkfs(1)でフォーマット

先頭にbook block

Boot device以外は空

Super block

媒体全体を管理する構造

Inode blocks

Inodeの配列を格納

インデックをi番号(i-no)と呼ぶ

2012/3/24 46

Super block

struct file

Boot block

データブロックの利用

一般ファイルのデータ部分

メタデータはinodeが管理

ディレクトリファイル

一般ファイルのモードがIFDIR (040000)

i番号とファイル名の構造が配列として格納

間接ブロック

Inodeのiaddrから直接参照できないブロックを関節参照する

2012/3/24 47

処理を読む前にデータ構造を理解する

2012/3/24 48

Inode inode.c (incore inode) 1/2

5659: struct inode

5660: {

5661: char i_flag;

5662: char i_count; /* reference count */

5663: int i_dev; /* device where inode resides */

5664: int i_number; /* i number, 1-to-1 with device address */

5665:

5666: int i_mode;

5667: char i_nlink; /* directory entries */

5668: char i_uid; /* owner */

5669: char i_gid; /* group of owner */

5670: char i_size0; /* most significant of size */

5671: char *i_size1; /* least sig */

5672: int i_addr[8]; /* device addresses constituting file */

5673: int i_lastr; /* last logical block read (for read-ahead) */

5674:

5675: } inode[NINODE];

0131: #define NINODE 100 /* number of in core inodes */

2012/3/24 49

Inode inode.c (incore inode) 2/2 5678: /* flags */

5679: #define ILOCK 01 /* inode is locked */

5680: #define IUPD 02 /* inode has been modified */

5681: #define IACC 04 /* inode access time to be updated */

5682: #define IMOUNT 010 /* inode is mounted on */

5683: #define IWANT 020 /* some process waiting on lock */

5684: #define ITEXT 040 /* inode is pure text prototype */

5685:

5686: /* modes */

5687: #define IALLOC 0100000 /* file is used */

5688: #define IFMT 060000 /* type of file */

5689: #define IFDIR 040000 /* directory */

5690: #define IFCHR 020000 /* character special */

5691: #define IFBLK 060000 /* block special, 0 is regular */

5692: #define ILARG 010000 /* large addressing algorithm */

5693: #define ISUID 04000 /* set user id on execution */

5694: #define ISGID 02000 /* set group id on execution */

5695: #define ISVTX 01000 /* save swapped text even after use */

5696: #define IREAD 0400 /* read, write, execute permissions */

5697: #define IWRITE 0200

5698: #define IEXEC 0100

2012/3/24 50

file – file.h

5507: struct file

5508: {

5509: char f_flag;

5510: char f_count; /* reference count */

5511: int f_inode; /* pointer to inode structure */

5512: char *f_offset[2]; /* read/write character pointer */

5513: } file[NFILE];

5514: /* --------------------------- */

5515:

5516: /* flags */

5517: #define FREAD 01

5518: #define FWRITE 02

5519: #define FPIPE 04

0132: #define NFILE 100 /* number of in core file structures */

2012/3/24 51

処理を読む前にデータ構造を理解する

2012/3/24 52

proc – proc.h 0358: struct proc 0359: { 0360: char p_stat; 0361: char p_flag; 0362: char p_pri; /* priority, negative is high */ 0363: char p_sig; /* signal number sent to this process */ 0364: char p_uid; /* user id, used to direct tty signals */ 0365: char p_time; /* resident time for scheduling */ 0366: char p_cpu; /* cpu usage for scheduling */ 0367: char p_nice; /* nice for scheduling */ 0368: int p_ttyp; /* controlling tty */ 0369: int p_pid; /* unique process id */ 0370: int p_ppid; /* process id of parent */ 0371: int p_addr; /* address of swappable image */ 0372: int p_size; /* size of swappable image (*64 bytes) */ 0373: int p_wchan; /* event process is awaiting */ 0374: int *p_textp; /* pointer to text structure */ 0375: 0376: } proc[NPROC];

2012/3/24 53

user – user.h 0413: struct user

0414: {

0418: char u_segflg; /* flag for IO; user or kernel space */

0419: char u_error; /* return error code */

0420: char u_uid; /* effective user id */

0421: char u_gid; /* effective group id */

0422: char u_ruid; /* real user id */

0423: char u_rgid; /* real group id */

0424: int u_procp; /* pointer to proc structure */

0425: char *u_base; /* base address for IO */

0426: char *u_count; /* bytes remaining for IO */

0427: char *u_offset[2]; /* offset in file for IO */

0428: int *u_cdir; /* pointer to inode of current directory */

0429: char u_dbuf[DIRSIZ]; /* current pathname component */

0430: char *u_dirp; /* current pointer to inode */

0431: struct { /* current directory entry */

0432: int u_ino;

0433: char u_name[DIRSIZ];

0434: } u_dent;

0435: int *u_pdir; /* inode of parent directory of dirp */

0438: int u_ofile[NOFILE]; /* pointers to file structures of open files */

0139: #define NOFILE 15 /* max open files per process */

2012/3/24 54

空間構造

text

data

bss

stack

text

data

bss

user

IOレジスタ

text

data

bss

stack

user

text

data

bss

stack

user

text

data

bss

stack

user

PSW PC

kstack kstack kstack kstack

2012/3/24 55

ここまで理解すれば、処理はスルスル読める かな?

2012/3/24 56

ファイルシステムの構造 fd視点

2012/3/24 57

fd = open()

プロセス proc

user

15個

file[NFILE]

u_ofile[NOFILE]

inode[NINODE]

i_number

data blocks

Inode blocks

Struct inode[]

Super block

Boot block

i_number

キャッシュバッファ

ファイルシステムの構造 fd視点

fdはu_ofile[]のインデックス

u_ofile[fd]はfileをポイントする

fileは複数のu_ofile[]から参照可能で参照カウンタ(f_count)をもつ

媒体上のinodeは媒体上のインデックスをi番号とする

メモリ上にinodeを展開する場合にはインコアinodeのi_numberにi番号を格納する

2012/3/24 58

ファイルシステムの構造 プロセス視点

2012/3/24 59

プロセス p_textp

proc

user

inode[NINODE]

i_number

data blocks

Inode blocks

Struct inode[]

Super block

Boot block

キャッシュバッファ

u_cdir

x_iptr

rootdev

u_dirp

u_pdir

ファイルシステムの構造 プロセス視点

procはtextセグメントを共用する場合にx_iprt

でtext構造をポイント

text構造は共用するa.outファイルのinodeをポイント

userはu_cdirでcurrent working directoryを管理

Userはu_dirpで作業用のinodeを管理

Userはu_pdirで親ディレクトのinodeを管理

2012/3/24 60

ファイルシステムの構造 ファイル視点

2012/3/24 61

data blocks

Inode blocks

Struct inode[]

Super block

Boot block u_cdir

rootdev

u_dirp

u_pdir

x_iptr

5659: struct inode 5660: { 5661: char i_flag; 5662: char i_count; 5663: int i_dev; 5664: int i_number; 5665: 5666: int i_mode; 5667: char i_nlink; 5668: char i_uid; 5669: char i_gid; 5670: char i_size0; 5671: char *i_size1; 5672: int i_addr[0]; [1] [2] [3] [4] [5] : : 5673: int i_lastr; 5674: 5675: }

f_inode

i_size

ファイルシステムの構造 ファイル視点

procはtextセグメントを共用する場合にx_iprt

でtext構造をポイント

text構造は共用するa.outファイルのinodeをポイント

userはu_cdirでcurrent working directoryを管理

Userはu_dirpで作業用のinodeを管理

Userはu_pdirで親ディレクトのinodeを管理

2012/3/24 62

ファイルシステムの処理

2012/3/24 63

名前空間 – 処理概要

絶対パスの場合

/のi番号は固定1、rootディバスは変数rootdev

パス名を順にi番号に変換

相対パスの場合

userのu_cdirから順にi番号に変換

/名前/の検索

ディレクトファイルを名前で検索

ヒットしたらその名前の左隣2バイトがi番号

2012/3/24 64

名前空間 – namei namei.c

7507: /*

7508: * Convert a pathname into a pointer to

7509: * an inode. Note that the inode is locked.

7510: *

7511: * func = function called to get next char of

name

7512: * &uchar if name is in user space

7513: * &schar if name is in system space

7514: * flag = 0 if name is sought

7515: * 1 if name is to be created

7516: * 2 if name is to be deleted

7517: */

7518: namei(func, flag)

7519: int (*func)();

7520: {

7521: register struct inode *dp;

7522: register c;

7523: register char *cp;

7524: int eo, *bp;

7525:

7526: /*

7527: * If name starts with '/' start from

7528: * root; otherwise start from current dir.

7529: */

7530:

7531: dp = u.u_cdir;

7532: if((c=(*func)()) == '/')

7533: dp = rootdir;

7534: iget(dp->i_dev, dp->i_number);

7535: while(c == '/')

7536: c = (*func)();

7537: if(c == '¥0' && flag != 0) {

7538: u.u_error = ENOENT;

7539: goto out;

7540: }

2012/3/24 65

名前空間 – namei namei.c

7542: cloop:

7548: if(u.u_error)

7549: goto out;

7550: if(c == '¥0')

7551: return(dp);

7558:

7559: if((dp->i_mode&IFMT) != IFDIR) {

7560: u.u_error = ENOTDIR;

7561: goto out;

7562: }

7563: if(access(dp, IEXEC))

7564: goto out;

7565:

7570: cp = &u.u_dbuf[0];

7571: while(c!='/' && c!='¥0' && u.u_error==0) {

7572: if(cp < &u.u_dbuf[DIRSIZ])

7573: *cp++ = c;

7574: c = (*func)();

7575: }

7576: while(cp < &u.u_dbuf[DIRSIZ])

7577: *cp++ = '¥0';

7578: while(c == '/')

7579: c = (*func)();

7580: if(u.u_error)

7581: goto out;

7585: u.u_offset[1] = 0;

7586: u.u_offset[0] = 0;

7587: u.u_segflg = 1;

7588: eo = 0;

7589: u.u_count = ldiv(dp->i_size1, DIRSIZ+2);

7590: bp = NULL;

2012/3/24 66

名前空間 – namei namei.c

7638: u.u_offset[1] =+ DIRSIZ+2;

7639: u.u_count--;

7640: if(u.u_dent.u_ino == 0) {

7641: if(eo == 0)

7642: eo = u.u_offset[1];

7643: goto eloop;

7644: }

7645: for(cp = &u.u_dbuf[0]; cp <

&u.u_dbuf[DIRSIZ]; cp++)

7646: if(*cp != cp[u.u_dent.u_name -

u.u_dbuf])

7647: goto eloop;

7648:

7655: if(bp != NULL)

7656: brelse(bp);

7657: if(flag==2 && c=='¥0') {

7658: if(access(dp, IWRITE))

7659: goto out;

7660: return(dp);

7661: }

7662: bp = dp->i_dev;

7663: iput(dp);

7664: dp = iget(bp, u.u_dent.u_ino);

7665: if(dp == NULL)

7666: return(NULL);

7667: goto cloop;

7668:

7669: out:

7670: iput(dp);

7671: return(NULL);

7672: }

2012/3/24 67

名前空間 – namei namei.c

7592: eloop:

7600: if(u.u_count == 0) {

7601: if(bp != NULL)

7602: brelse(bp);

7603: if(flag==1 && c=='¥0') {

7604: if(access(dp, IWRITE))

7605: goto out;

7606: u.u_pdir = dp;

7607: if(eo)

7608: u.u_offset[1] = eo-DIRSIZ-2;

else

7609: dp->i_flag =| IUPD;

7610: return(NULL);

7611: }

7612: u.u_error = ENOENT;

7613: goto out;

7614: }

7622: if((u.u_offset[1]&0777) == 0) {

7623: if(bp != NULL)

7624: brelse(bp);

7625: bp = bread(dp->i_dev,

7626: bmap(dp, ldiv(u.u_offset[1],

512)));

7627: }

7636: bcopy(bp->b_addr+(u.u_offset[1]&0777),

&u.u_dent, (DIRSIZ+2)/2);

7637:

2012/3/24 68

検索論理

/fileA/fileB/fileC

2012/3/24 69

data blocks

Inode blocks

Struct inode[]

Super block

Boot block

名前空間

UNIXのファイル識別は内部的にはi番号

i番号は1DISK装置内でユニーク

mountで複数のDISKを使うのでdev+i番号で1システム中のファイルは完全にユニーク

2012/3/24 70

Inodeとfdを関連付ける

2012/3/24 71

open – sys2.c

5765: open()

5766: {

5767: register *ip;

5768: extern uchar;

5769:

5770: ip = namei(&uchar, 0);

5771: if(ip == NULL)

5772: return;

5773: u.u_arg[1]++;

5774: open1(ip, u.u_arg[1], 0);

5775: }

2012/3/24 72

open1 – open.c

5804: open1(ip, mode, trf)

5805: int *ip;

5806: {

5807: register struct file *fp;

5808: register *rip, m;

5809: int i;

5810:

5811: rip = ip;

5812: m = mode;

5813: if(trf != 2) {

5814: if(m&FREAD)

5815: access(rip, IREAD);

5816: if(m&FWRITE) {

5817: access(rip, IWRITE);

5818: if((rip->i_mode&IFMT) == IFDIR)

5819: u.u_error = EISDIR;

5820: }

5821: }

5822: if(u.u_error)

5823: goto out;

5824: if(trf)

5825: itrunc(rip);

5826: prele(rip);

5827: if ((fp = falloc()) == NULL)

5828: goto out;

5829: fp->f_flag = m&(FREAD|FWRITE);

5830: fp->f_inode = rip;

5831: i = u.u_ar0[R0];

5832: openi(rip, m&FWRITE);

5833: if(u.u_error == 0)

5834: return;

5835: u.u_ofile[i] = NULL;

5836: fp->f_count--;

5837:

5838: out:

5839: iput(rip);

5840: } 2012/3/24 73

falloc – fio.c 6847: falloc() 6848: { 6849: register struct file *fp; 6850: register i; 6851: 6852: if ((i = ufalloc()) < 0) 6853: return(NULL); 6854: for (fp = &file[0]; fp < &file[NFILE]; fp++) 6855: if (fp->f_count==0) { 6856: u.u_ofile[i] = fp; 6857: fp->f_count++; 6858: fp->f_offset[0] = 0; 6859: fp->f_offset[1] = 0; 6860: return(fp); 6861: } 6862: printf("no file¥n"); 6863: u.u_error = ENFILE; 6864: return(NULL);

2012/3/24 74

fd->file->inode->baddrの流れ

2012/3/24 75

read, write – sys2.c 5708: /*

5709: * read system call

5710: */

5711: read()

5712: {

5713: rdwr(FREAD);

5714: }

5715: /* --------------------------- */

5716:

5717: /*

5718: * write system call

5719: */

5720: write()

5721: {

5722: rdwr(FWRITE);

5723: }

2012/3/24 76

rdwr – sys2.c

5731: rdwr(mode)

5732: {

5733: register *fp, m;

5734:

5735: m = mode;

5736: fp = getf(u.u_ar0[R0]);

5737: if(fp == NULL)

5738: return;

5739: if((fp->f_flag&m) == 0) {

5740: u.u_error = EBADF;

5741: return;

5742: }

5743: u.u_base = u.u_arg[0];

5744: u.u_count = u.u_arg[1];

5745: u.u_segflg = 0;

5746: if(fp->f_flag&FPIPE) {

2012/3/24 77

rdwr – sys2.c

5746: if(fp->f_flag&FPIPE) {

5747: if(m==FREAD)

5748: readp(fp); else

5749: writep(fp);

5750: } else {

5751: u.u_offset[1] = fp->f_offset[1];

5752: u.u_offset[0] = fp->f_offset[0];

5753: if(m==FREAD)

5754: readi(fp->f_inode); else

5755: writei(fp->f_inode);

5756: dpadd(fp->f_offset, u.u_arg[1]-u.u_count);

5757: }

5758: u.u_ar0[R0] = u.u_arg[1]-u.u_count;

5759: }

2012/3/24 78

readi – sys2.c

6216: * u_base core address for destination

6217: * u_offset byte offset in file

6218: * u_count number of bytes to read

6219: * u_segflg read to kernel/user

6220: */

6221: readi(aip)

6222: struct inode *aip;

6223: {

6224: int *bp;

6225: int lbn, bn, on;

6226: register dn, n;

6227: register struct inode *ip;

6228:

6229: ip = aip;

6230: if(u.u_count == 0)

6231: return;

2012/3/24 79

readi – sys2.c

6232: ip->i_flag =| IACC;

6238: do {

6239: lbn = bn = lshift(u.u_offset, -9);

6240: on = u.u_offset[1] & 0777;

6241: n = min(512-on, u.u_count);

6242: if((ip->i_mode&IFMT) != IFBLK) {

6243: dn = dpcmp(ip->i_size0&0377, ip->i_size1,

6244: u.u_offset[0], u.u_offset[1]);

6245: if(dn <= 0)

6246: return;

6247: n = min(n, dn);

6248: if ((bn = bmap(ip, lbn)) == 0)

6249: return;

6250: dn = ip->i_dev;

6251: } else {

6252: dn = ip->i_addr[0];

6253: rablock = bn+1;

6254: } 2012/3/24 80

readi – sys2.c

6255: if (ip->i_lastr+1 == lbn)

6256: bp = breada(dn, bn, rablock);

6257: else

6258: bp = bread(dn, bn);

6259: ip->i_lastr = lbn;

6260: iomove(bp, on, n, B_READ);

6261: brelse(bp);

6262: } while(u.u_error==0 && u.u_count!=0);

6263: }

2012/3/24 81

writei – rdwri.c 6271: * u_base core address for source

6272: * u_offset byte offset in file

6273: * u_count number of bytes to write

6274: * u_segflg write to kernel/user

6275: */

6276: writei(aip)

6277: struct inode *aip;

6278: {

6279: int *bp;

6280: int n, on;

6281: register dn, bn;

6282: register struct inode *ip;

6283:

6284: ip = aip;

6285: ip->i_flag =| IACC|IUPD;

6286: if((ip->i_mode&IFMT) == IFCHR) {

6287: (*cdevsw[ip->i_addr[0].d_major].d_write)(ip->i_addr[0]);

6288: return;

6289: }

2012/3/24 82

writei – rdwri.c 6290: if (u.u_count == 0)

6291: return;

6292:

6293: do {

6294: bn = lshift(u.u_offset, -9);

6295: on = u.u_offset[1] & 0777;

6296: n = min(512-on, u.u_count);

6297: if((ip->i_mode&IFMT) != IFBLK) {

6298: if ((bn = bmap(ip, bn)) == 0)

6299: return;

6300: dn = ip->i_dev;

6301: } else

6302: dn = ip->i_addr[0];

6303: if(n == 512)

6304: bp = getblk(dn, bn); else

6305: bp = bread(dn, bn);

6306: iomove(bp, on, n, B_WRITE);

2012/3/24 83

writei – rdwri.c 6307: if(u.u_error != 0)

6308: brelse(bp); else

6309: if ((u.u_offset[1]&0777)==0)

6310: bawrite(bp); else

6311: bdwrite(bp);

6312: if(dpcmp(ip->i_size0&0377, ip->i_size1,

6313: u.u_offset[0], u.u_offset[1]) < 0 &&

6314: (ip->i_mode&(IFBLK&IFCHR)) == 0) {

6315: ip->i_size0 = u.u_offset[0];

6316: ip->i_size1 = u.u_offset[1];

6317: }

6318: ip->i_flag =| IUPD;

6319: } while(u.u_error==0 && u.u_count!=0);

6320: }

2012/3/24 84

UNIXの最大の発明

2012/3/24 85

pipe – pipe.c

7723: pipe()

7724: {

7725: register *ip, *rf, *wf;

7726: int r;

7727:

7728: ip = ialloc(rootdev);

7729: if(ip == NULL)

7730: return;

7731: rf = falloc();

7732: if(rf == NULL) {

7733: iput(ip);

7734: return;

7735: }

7736: r = u.u_ar0[R0];

7737: wf = falloc();

7738: if(wf == NULL) {

7739: rf->f_count = 0;

7740: u.u_ofile[r] = NULL;

7741: iput(ip);

7742: return;

7743: }

7744: u.u_ar0[R1] = u.u_ar0[R0];

7745: u.u_ar0[R0] = r;

7746: wf->f_flag = FWRITE|FPIPE;

7747: wf->f_inode = ip;

7748: rf->f_flag = FREAD|FPIPE;

7749: rf->f_inode = ip;

7750: ip->i_count = 2;

7751: ip->i_flag = IACC|IUPD;

7752: ip->i_mode = IALLOC;

7753: }

2012/3/24 86

実は強力な

2012/3/24 87

dup – sys3.c

6069: dup()

6070: {

6071: register i, *fp;

6072:

6073: fp = getf(u.u_ar0[R0]);

6074: if(fp == NULL)

6075: return;

6076: if ((i = ufalloc()) < 0)

6077: return;

6078: u.u_ofile[i] = fp;

6079: fp->f_count++;

6080: }

2012/3/24 88

パイプとリダイレクト

2012/3/24 89

リダイレクト

1 “> out”でoutをopen fd:3

2 標準出力fd:1をclose

3 “out”のfd:3をdup →fd:1

5 “out”のfdをclose

2012/3/24 90

“out”

“out”

“out”

“out”

パイプ

1 pipeを呼ぶ

2 forkする

3 親のread fdをclose

4 子のwrite fdをclose

5 必要ならcloseとdupで0,1に繋ぎかえ

2012/3/24 91

DISKとメモリを繋ぐ

2012/3/24 92

buf - buf.h

4520: struct buf

4521: {

4522: int b_flags; /* see defines below */

4523: struct buf *b_forw; /* headed by devtab of b_dev */

4524: struct buf *b_back; /* " */

4525: struct buf *av_forw; /* position on free list, */

4526: struct buf *av_back; /* if not BUSY*/

4527: int b_dev; /* major+minor device name */

4528: int b_wcount; /* transfer count (usu. words) */

4529: char *b_addr; /* low order core address */

4530: char *b_xmem; /* high order core address */

4531: char *b_blkno; /* block # on device */

4532: char b_error; /* returned after I/O */

4533: char *b_resid; /* words not transferred after error */

4534:

4535: } buf[NBUF];

0130: #define NBUF 15 /* size of buffer cache */

2012/3/24 93

buf - buf.h

4566: struct buf bfreelist;

4567:

4571: #define B_WRITE 0 /* non-read pseudo-flag */

4572: #define B_READ 01 /* read when I/O occurs */

4573: #define B_DONE 02 /* transaction finished */

4574: #define B_ERROR 04 /* transaction aborted */

4575: #define B_BUSY 010 /* not on av_forw/back list */

4576: #define B_PHYS 020 /* Physical IO potentially using UNIBUS map */

4577:

4578: #define B_MAP 040 /* This block has the UNIBUS map allocated */

4579:

4580: #define B_WANTED 0100 /* issue wakeup when BUSY goes off */

4581:

4582: #define B_RELOC 0200 /* no longer used */

4583: #define B_ASYNC 0400 /* don't wait for I/O completion */

4584:

4585: #define B_DELWRI 01000 /* don't write till block leaves available list */

2012/3/24 94

devtab – buf.h

4551: struct devtab

4552: {

4553: char d_active; /* busy flag */

4554: char d_errcnt; /* error count (for recovery) */

4555: struct buf *b_forw; /* first buffer for this dev */

4556: struct buf *b_back; /* last buffer for this dev */

4557: struct buf *d_actf; /* head of I/O queue */

4558: struct buf *d_actl; /* tail of I/O queue */

4559: };

2012/3/24 95

buf - buf.h

2012/3/24 96

b_forw

b_back

av_forw

av_back

devtab

b_forw

b_back

d_actf

d_actl

512byte

buf - buf.h

2012/3/24 97

b_dev

b_blkno

b_addr

514byte

512byte

b_blkno

bufの役割

1つのbuf構造が512バイトのキャッシュを管理

DISKドライバの非同期処理の管理を兼ねる

キャッシュの識別はb_dev(maj:min)とb_blkno

512バイト単位のDISKアクセスとバイト単位のメモリアクセスの緩衝器の役割も兼ねる

例:

○ inodeは16バイト、DISKから512バイト(inode

を32個)読みだしてbufで管理

○ ディレクトエントリは16バイト、DISKから32個読みだして、各エントリを操作

2012/3/24 98

bufの操作

獲得

getblk DISKから読まずにbufを獲得

bread DISKから読んでbufを獲得 - 同期

breada DISKから読んでbufを獲得 - 非同期

解放

Bwrite DISKへ書いてbufを解放

Bdwrite DISKへ書いてbufを解放

Bawrite DISKへか

Brelse DISKへ書かずにbufを解放

2012/3/24 99

binit – bio.c 5055: binit()

5056: {

5057: register struct buf *bp;

5058: register struct devtab *dp;

5059: register int i;

5060: struct bdevsw *bdp;

5061:

5062: bfreelist.b_forw = bfreelist.b_back =

5063: bfreelist.av_forw = bfreelist.av_back =

&bfreelist;

5064: for (i=0; i<NBUF; i++) {

5065: bp = &buf[i];

5066: bp->b_dev = -1;

5067: bp->b_addr = buffers[i];

5068: bp->b_back = &bfreelist;

5069: bp->b_forw = bfreelist.b_forw;

5070: bfreelist.b_forw->b_back = bp;

5071: bfreelist.b_forw = bp;

5072: bp->b_flags = B_BUSY;

5073: brelse(bp);

5074: }

5075: i = 0;

5076: for (bdp = bdevsw;

bdp->d_open; bdp++) {

5077: dp = bdp->d_tab;

5078: if(dp) {

5079: dp->b_forw = dp;

5080: dp->b_back = dp;

5081: }

5082: i++;

5083: }

5084: nblkdev = i;

5085: }

2012/3/24 100

getblk – bio.c 4921: getblk(dev, blkno)

4922: {

4923: register struct buf *bp;

4924: register struct devtab *dp;

4925: extern lbolt;

4930: loop:

4931: if (dev < 0)

4932: dp = &bfreelist;

4933: else {

4934: dp = bdevsw[dev.d_major].d_tab;

4935: if(dp == NULL)

4936: panic("devtab");

4937: for (bp=dp->b_forw; bp != dp; bp = bp->b_forw) {

4938: if (bp->b_blkno!=blkno || bp->b_dev!=dev)

4939: continue;

4940: spl6();

4941: if (bp->b_flags&B_BUSY) {

4942: bp->b_flags =| B_WANTED;

4943: sleep(bp, PRIBIO);

4944: spl0();

4945: goto loop;

4946: }

4947: spl0();

4948: notavail(bp);

4949: return(bp);

4950: }

4951: }

4952: spl6();

4953: if (bfreelist.av_forw == &bfreelist) {

4954: bfreelist.b_flags =| B_WANTED;

4955: sleep(&bfreelist, PRIBIO);

4956: spl0();

4957: goto loop;

4958: }

4959: spl0();

4960: notavail(bp = bfreelist.av_forw);

4961: if (bp->b_flags & B_DELWRI) {

4962: bp->b_flags =| B_ASYNC;

4963: bwrite(bp);

4964: goto loop;

4965: }

4966: bp->b_flags = B_BUSY | B_RELOC;

4967: bp->b_back->b_forw = bp->b_forw;

4968: bp->b_forw->b_back = bp->b_back;

4969: bp->b_forw = dp->b_forw;

4970: bp->b_back = dp;

4971: dp->b_forw->b_back = bp;

4972: dp->b_forw = bp;

4973: bp->b_dev = dev;

4974: bp->b_blkno = blkno;

4975: return(bp);

4976: } 2012/3/24 101

incore – bio.c

4896: /* See if the block is associated with some buffer

4897: * (mainly to avoid getting hung up on a wait in breada)

4898: */

4899: incore(adev, blkno)

4900: {

4901: register int dev;

4902: register struct buf *bp;

4903: register struct devtab *dp;

4904:

4905: dev = adev;

4906: dp = bdevsw[adev.d_major].d_tab;

4907: for (bp=dp->b_forw; bp != dp; bp = bp->b_forw)

4908: if (bp->b_blkno==blkno && bp->b_dev==dev)

4909: return(bp);

4910: return(0);

4911: }

2012/3/24 102

bread – bio.c

4754: bread(dev, blkno) 4755: { 4756: register struct buf *rbp; 4757: 4758: rbp = getblk(dev, blkno); 4759: if (rbp->b_flags&B_DONE) 4760: return(rbp); 4761: rbp->b_flags =| B_READ; 4762: rbp->b_wcount = -256; 4763: (*bdevsw[dev.d_major].d_strategy)(rbp); 4764: iowait(rbp); 4765: return(rbp); 4766: }

2012/3/24 103

breada – bio.c 4773: breada(adev, blkno, rablkno)

4774: {

4775: register struct buf *rbp, *rabp;

4776: register int dev;

4777:

4778: dev = adev;

4779: rbp = 0;

4780: if (!incore(dev, blkno)) {

4781: rbp = getblk(dev, blkno);

4782: if ((rbp->b_flags&B_DONE) == 0) {

4783: rbp->b_flags =| B_READ;

4784: rbp->b_wcount = -256;

4785: (*bdevsw[adev.d_major].d_strategy)(rbp);

4786: }

4787: }

4788: if (rablkno && !incore(dev, rablkno)) {

4789: rabp = getblk(dev, rablkno);

4790: if (rabp->b_flags & B_DONE)

4791: brelse(rabp);

4792: else {

4793: rabp->b_flags =|

B_READ|B_ASYNC;

4794: rabp->b_wcount = -256;

4795:

(*bdevsw[adev.d_major].d_strategy)(rabp);

4796: }

4797: }

4798: if (rbp==0)

4799: return(bread(dev, blkno));

4800: iowait(rbp);

4801: return(rbp);

4802: }

2012/3/24 104

bwrite – bio.c 4809: bwrite(bp) 4810: struct buf *bp; 4811: { 4812: register struct buf *rbp; 4813: register flag; 4814: 4815: rbp = bp; 4816: flag = rbp->b_flags; 4817: rbp->b_flags =& ~(B_READ | B_DONE | B_ERROR | B_DELWRI); 4818: rbp->b_wcount = -256; 4819: (*bdevsw[rbp->b_dev.d_major].d_strategy)(rbp); 4820: if ((flag&B_ASYNC) == 0) { 4821: iowait(rbp); 4822: brelse(rbp); 4823: } else if ((flag&B_DELWRI)==0) 4824: geterror(rbp); 4825: }

2012/3/24 105

brelese – bio.c 4869: brelse(bp)

4870: struct buf *bp;

4871: {

4872: register struct buf *rbp, **backp;

4873: register int sps;

4874:

4875: rbp = bp;

4876: if (rbp->b_flags&B_WANTED)

4877: wakeup(rbp);

4878: if (bfreelist.b_flags&B_WANTED) {

4879: bfreelist.b_flags =& ~B_WANTED;

4880: wakeup(&bfreelist);

4881: }

4882: if (rbp->b_flags&B_ERROR)

4883: rbp->b_dev.d_minor = -1; /* no assoc. on error */

4884: backp = &bfreelist.av_back;

4885: sps = PS->integ;

4886: spl6();

4887: rbp->b_flags =& ~(B_WANTED|B_BUSY|B_ASYNC);

4888: (*backp)->av_forw = rbp;

4889: rbp->av_back = *backp;

4890: *backp = rbp;

4891: rbp->av_forw = &bfreelist;

4892: PS->integ = sps;

4893: } 2012/3/24 106

iowait – bio.c

4982: iowait(bp)

4983: struct buf *bp;

4984: {

4985: register struct buf *rbp;

4986:

4987: rbp = bp;

4988: spl6();

4989: while ((rbp->b_flags&B_DONE)==0)

4990: sleep(rbp, PRIBIO);

4991: spl0();

4992: geterror(rbp);

4993: }

2012/3/24 107

参考資料

RK11-D and RK11-E moving head disk drive

controller manual

UNIX v6 マニュアル

http://wwwlehre.dhbw-

stuttgart.de/~helbig/os/v6/doc/index.html

2012/3/24 108