C言語でrmdirコマンドを書きたい

■要求定義
– 空のフォルダを削除する

#include <stdio.h>
#include <sys/stat.h>

int main(){

	char *dir = "./newfolder";
	rmdir(dir);
		
	return 0;
}

$ ./dev

フォルダの中にファイルが入っているときは、rmdirでは削除されない。

linuxコマンドとcの標準ライブラリ関数がネーミングが同じ場合は面白みがないな。

C言語でtouchコマンドを書きたい

■要求定義
– ファイルを作成する

■検討
– touchはファイルの中身は書かないから、fopen, fcloseだけで良いか?

#include <stdio.h>

int main(){

	FILE *fp;
	fp = fopen("test.txt", "w");
	fclose(fp);
		
	return 0;
}

$ ./dev

■追加
– コマンドラインで入力した値のファイルを作成する

#include <stdio.h>

int main(){

	char ss[256];
    gets(ss);

	FILE *fp;
	fp = fopen(ss, "w");
	fclose(fp);
		
	return 0;
}

$ ./dev
hoge.txt

できました。

fopenの拡張子はテキストファイル(.dat, .txt, .c, .h)、バイナリファイル(.exe, .jpg, .gif, .mpeg)どちらも可

なるほど、C言語はバイナリの概念がかなり出てくるな。。

C言語でclearコマンドを書きたい

■要求定義
– 消さずに画面を綺麗にする

■検討
– windowsでsystem(“cls”); で消せると書いてある。嫌な予感がするが、bionicでも動く?

#include 
#include 

int main(){

	for(int idx=0; idx<10; idx++){
    	printf("%d\n", idx);
  	}

	system("clear");
		
	return 0;
}

0
1
2
3
4
5
6
7
8
9
sh: 1: cls: not found

やっぱり。DOS/Windowsコマンドらしく、linuxには無いとのこと。

int main(){

	for(int idx=0; idx<10; idx++){
    	printf("%d\n", idx);
  	}

	system("clear");
		
	return 0;
}

これなら動くけど意味ないね。

エスケープシーケンシーとはターミナルを制御する制御文字
printf("\033[2J") //画面クリア
などがある。

system("\033[2J");


う〜ん、clearコマンドとはちょっと違うな。

C言語でcpコマンドを書きたい

■要求定義
– ファイルやフォルダをコピーする
– cp (移動元ファイル名/フォルダ名) (移動先ファイル名/フォルダ名) 

#include <stdio.h>
#include <stdlib.h> //汎用ライブラリ
#include <string.h>

int main(){

	FILE *fpSrc, *fpDes, *fp;
	char ss[256], ch[50];

	fpSrc = fopen("test.txt", "r");
	fpDes = fopen("copy.txt", "w");

	while(fgets(&ss, 256, fpSrc) != NULL){
		printf("%s", ss);
		fwrite(ss, 1, 8, fpDes);
	}

	fclose(fpSrc);
	fclose(fpDes);

	printf("コピーしました。\n");
		
	return 0;
}

$ ./dev
asdf
1234コピーしました。

■考察
あれ、コピー先のデータはバイナリデータで入ってるな。
調べてみると、fwriteはバイナリデータの書き込みとのこと。
fwriteではなく、fputs()に変更します。

int main(){

	FILE *fpSrc, *fpDes;
	char ss[256];

	fpSrc = fopen("test.txt", "r");
	fpDes = fopen("copy.txt", "w");

	while(fgets(&ss, 256, fpSrc) != NULL){
		printf("%s", ss);
		fputs(ss, fpDes);
	}

	fclose(fpSrc);
	fclose(fpDes);

	printf("コピーしました。\n");
		
	return 0;
}

コピーできました。
バイナリとは2進数データのこと。

C言語でmvコマンドを書きたい

■要求定義
– ファイルを移動させる

■ステップ1
– 標準ライブラリ関数であるrename関数を使う

#include <stdio.h>

int main(){

	rename("./test.c", "./hoge/test.c");
	printf("移動しました。\n");
		
	return 0;
}

$ ./dev
移動しました。

移動できた事を確認。

■ステップ2
– ユーザ入力で$ mv ${FileName} ${MoveDir}となるので、コマンドラインからの入力を元に移動させたい
– 文字列の分割は”strtok”を使う。ポインタでファイル名s1, 異動先s2を指定する。

#include <stdio.h>
#include <string.h>

int main(){

	char ss[256] = "./test.c ./hoge/test.c";
	char *s1, *s2;
	s1 = strtok(ss, " ");
	s2 = strtok(NULL, " ");
	rename(s1, s2);	
	printf("移動しました。\n");
		
	return 0;
}

■ステップ3
– gets()でコマンドラインから入力した値を取得して移動させたい

int main(){

	// char ss[256] = "./test.c ./hoge/test.c";
	char ss[256];
	char *s1, *s2;
	
	gets(ss);
	s1 = strtok(ss, " ");
	s2 = strtok(NULL, " ");
	rename(s1, s2);	
	printf("移動しました。\n");
		
	return 0;
}

$ ./dev
./test.c ./hoge/test.c
移動しました。

ほう、面白い。コマンドラインからの入力は、strtokで分割して処理すれば良いですな。

C言語でcdコマンドを書きたい

■要求定義
– ユーザ名の入力に合わせてカレントディレクトリを移動する

■検討事項
ディレクトリ一覧を取得し、ユーザ入力と一致したら移動か
+ chdirでディレクトリを変更

#include <stdio.h>
#include <string.h> // 文字列操作
#include <unistd.h> // standard symbolic constants and types

int main(){

	char pathname[512];
	memset(pathname, '\0', 512); // memsetはバイトメモリブロックのセット

	char path[64] = "./hoge";
	chdir(path);
	getcwd(pathname, 512); // getcwdはカレントディレクトリ
	printf("%s\n",pathname);
		
	return 0;
}

$ pwd
/home/vagrant/dev
$ ./dev
/home/vagrant/dev/hoge

cだと、chdir(path)でディレクトリを変更できる

C言語でlsコマンドを書きたい

■要求定義
– まずはファイル名一覧表示
– オプションは後から考える

■検討した事
標準関数でファイル名一覧の取得関数はないらしい

#include <stdio.h>
#include <dirent.h> // format of directory entries

int main(){
	DIR *dir;
	struct dirent *dp; // 構造体
	char path[64] = "./";

	dir=opendir(path); // opendirはディレクトリオープン、 dirent.hが必要

	for(dp=readdir(dir);dp!=NULL;dp=readdir(dir)){ // readdirはディレクトリ読み込み
		printf("%s\n",dp->d_name);
	}
		
	return 0;
}

$ ./dev
.
dev
hello.c
..

forループでdp=readdir(dir);dp!=NULL;dp=readdir(dir)の書き方がよくわからんな。

C言語でログイン処理を書きたい

さて、C言語の基礎を写経したので、ここから少しずつC言語を使って緩くOSを学んでいきたい
まずmac, windowsにもあるログイン処理から

■要求定義
– ユーザ名に一致したパスワードを入力し、一致していたらログイン
– 不一致の場合は、パスワードを再入力してくださいと表示

#include <stdio.h>
#define User "hpscript"
#define Password "asdf"

int main(){
	char s[5];
	
	while(1){
		printf("%sさん、パスワードを入力してください。\n", User);
			gets(s);
		if(strcmp(s, Password)==0){
			printf("ログイン成功しました。\n");
			break;
		} else {
			printf("%sさん、パスワードを入力してください。\n", s);
		}
	}
	
	return 0;
}

$ ./dev
hpscriptさん、パスワードを入力してください。
aaaa
aaaaさん、パスワードを入力してください。
hpscriptさん、パスワードを入力してください。
asdf
ログイン成功しました。

文字列の比較は、strcmpを使用する
if(s == Password){} としても、trueにならない。
while(1)で無限ループにして、一致した場合はbreakでループから抜ける。

なるほど、型の宣言するところとか、色々頭使うなー

記憶装置の原理

PCが記憶装置を制御している
– データ授受の為の情報通路: データ線、データバスと呼ばれる
– 読み出し・書込みの制御信号: R/Wを通告する
– 記憶装置のどの位置を選択するかのアドレス線

基本記憶素子をメモリセルという
主記憶装置の構造は
1. アドレス選択部
2. 制御部
3. 記憶部: 一つのアドレスに1バイト

RAM
L SRAM: 高速アクセス、フリップフロップ、バイポーラ型、MOS型のトランジスタが用いられている
L DRAM: コンデンサに電荷を蓄える
フラッシュメモリ
 大容量で書き換え可能回数の多い
キャッシュメモリ
 主記憶装置とCPUの間に小容量の高速メモリを入れる