'공부/운영체제&시스템프로그래밍'에 해당되는 글 4건

반응형

기존에는 멀티 스레드를 사용하지 않는 작업 하이퍼 스레딩이 필요하지 않음따라서 남는 레지스터를 활용하자는 생각을 .

 

Loop Splitting 사용하는 프로그램을 만들어, 병렬의 개수를 늘려가며 하이퍼 스레딩 사용 유무에 따라 비교를 해보았다.

#include<stdio.h>
#include<Windows.h>
#include<stdint.h> 
/*
vmware의 리눅스에서 하려고 하였다. 하지만 하이퍼 스레딩 유무에 따라 CPU정보 명령어( cat /proc/cpuinfo, grep -c processor /proc/cpuinfo, grep "physical id" /proc/cpuinfo | sort -u | wc -l, grep "cpu cores" /proc/cpuinfo | tail -1)를 사용하여 확인하였지만 차이가 없어 윈도우환경에서 하였다.
*/
//windows에는 gettimeofday함수가 없으므로 인터넷에서 참고하였다.
int gettimeofday(struct timeval* tp, int* tz)
{
 LARGE_INTEGER tickNow;
 static LARGE_INTEGER tickFrequency;
 static BOOL tickFrequencySet = FALSE;
 if (tickFrequencySet == FALSE) {
  QueryPerformanceFrequency(&tickFrequency);
  tickFrequencySet = TRUE;
 }
 QueryPerformanceCounter(&tickNow);
 tp->tv_sec = (long) (tickNow.QuadPart / tickFrequency.QuadPart);
 tp->tv_usec = (long) (((tickNow.QuadPart % tickFrequency.QuadPart) * 1000000L) / tickFrequency.QuadPart);
 
 return 0;
}

void main() {
	struct timeval startTime, endTime;

	double diffTime;

	int limit = 100000;
	int i;
    int loop = 1;
	int data[100000];
	int a;
	for (a = 0; a < limit; a++) {
		data[a] = 1;
	}
	
	int x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19;
	x0 = 1;
	x1 = 1;
	x2 = 1;
	x3 = 1;
	x4 = 1;
	x5 = 1;
	x6 = 1;
	x7 = 1;
	x8 = 1;
	x9 = 1;
	x10 = 1;
	x11 = 1;
	x12 = 1;
	x13 = 1;
	x14 = 1;
	x15 = 1;
	x16 = 1;
	x17 = 1;
	x18 = 1;
	x19 = 1;
    printf("loop %d,  %d loop splitting\n", limit, loop);
    gettimeofday(&startTime, NULL);
    printf("starttime %d.%d s\n",startTime.tv_sec, startTime.tv_usec);
	for (i = 0; i < limit; i += loop) {
		x0 = x0 * data[i];
		/*x1 = x1 * data[i + 1];
		x2 = x2 * data[i + 2];
		x3 = x3 * data[i + 3];
		x4 = x4 * data[i + 4];
		x5 = x5 * data[i + 5];
		x6 = x6 * data[i + 6];
		x7 = x7 * data[i + 7];
		x8 = x8 * data[i + 8];
		x9 = x9 * data[i + 9];
		x10 = x10 * data[i + 10];
		x11 = x11 * data[i + 11];
		x12 = x12 * data[i + 12];
		x13 = x13 * data[i + 13];
		x14 = x14 * data[i + 14];
		x15 = x15 * data[i + 15];
		x16 = x16 * data[i + 16];
		x17 = x17 * data[i + 17];
		x18 = x18 * data[i + 18];
		x19 = x19 * data[i + 19];*/
	}

	gettimeofday(&endTime, NULL);
    printf("endtime %d.%d s\n",endTime.tv_sec, endTime.tv_usec);
}

테스트를 해보기 하이퍼 스레딩 기능을 켰다.

 

다음은 하이퍼 스레딩이 켜진 상태에서 실행한 결과이다.

 

<병렬 1>

<병렬 2>

<병렬 4>

<병렬 5>

<병렬 8>

<병렬 10 >

<병렬 20>



그리고 나서 하이퍼 스레딩을 끄고 테스트를 해보았다.

 

 

<병렬 1>

<병렬 2>

<병렬 4>

<병렬 5>

<병렬 8>

 

<병렬 10 >

<병렬 20>

 

테스트 결과들을 표로 정리하면 다음과 같다.

 

startT endT 시간() 평균 시간
1 병렬      
158.286745 158.286334 0.000411 0.000529
159.294495 159.293966 0.000529  
159.941791 159.941145 0.000646  
2 병렬      
205.491576 205.491193 0.000383 0.000429
206.256555 206.256076 0.000479  
206.781915 206.781489 0.000426  
4 병렬      
233.779762 233.779216 0.000546 0.000466
234.638762 234.638302 0.00046  
235.315725 235.315334 0.000391  
5 병렬      
276.227503 276.227081 0.000422 0.001615
277.362467 277.361994 0.000473  
278.18864 278.18469 0.00395  
8 병렬      
305.11175 305.10701 0.00474 0.003192
306.78751 306.78311 0.0044  
306.816079 306.815644 0.000435  
10 병렬      
373.782009 373.781564 0.000445 0.000421
374.588579 374.588149 0.00043  
375.25087 375.250482 0.000388  
20 병렬      
411.261493 411.261106 0.000387 0.000412
412.976789 412.976307 0.000482  
413.531929 413.531562 0.000367  
HTon      

<하이퍼 스레딩 켰을 >

 

 

startT endT 시간() 평균시간
1 병렬      
1193.879285 1193.878775 0.00051 0.001763
1195.55735 1195.55297 0.00438  
1195.954497 1195.954098 0.000399  
2 병렬      
1250.718352 1250.718071 0.000281 0.000349
1251.968818 1251.968417 0.000401  
1252.790355 1252.789991 0.000364  
4 병렬      
1333.682861 1333.682653 0.000208 0.000284
1336.171769 1336.171549 0.00022  
1337.950726 1337.950303 0.000423  
5 병렬      
1449.503198 1449.502993 0.000205 0.000939
1452.7616 1452.75931 0.00229  
1452.823454 1452.823132 0.000322  
8 병렬      
1589.8527 1589.852293 0.000407 0.00044
1590.653918 1590.653423 0.000495  
1591.37499 1591.374572 0.000418  
10 병렬      
1652.622676 1652.622495 0.000181 0.001527
1653.424747 1653.424336 0.000411  
1654.68126 1654.67727 0.00399  
20 병렬      
1875.417252 1875.416802 0.00045 0.001983
1876.366084 1876.365556 0.000528  
1877.5143 1877.50933 0.00497  
HToff      

<하이퍼 스레딩을 껐을 >

 

하이퍼 스레딩을 켰을 경우와 껐을 경우의 컴퓨터 환경을 최대한 동일하게 하기 위해 네트워크를 차단하고 켜진 프로그램도 최대한 동일하게 유지하였다. (따라서, 환경이 동일한 환경이라고 가정하고 차이를 보았다.)

병렬개수별 시간을 여러 측정하여 평균치를 사용하였다. 병렬개수별 시간 차이는 다음과 같다

 

 

차이를 보기 쉽게 시간에 10^5만큼 곱하였다.

병렬 차이(HTon - HToff)
1 52.86490367
2 8.066666663
4 18.2
5 67.59999999
8 275.1666667
10 -110.6333333
20 -157.0666667

병렬의 개수를 많이 늘렸을 하이퍼 스레딩을 껐을 경우가 시간이 오래 걸리는 것으로 보아, 하이퍼 스레딩을 껐을 , 남은 Architectural state(레지스터) 활용하지 못하는 것으로 판단하였다.

 따라서 이러한 단일 프로세스만 수행해야하는 상황에서 어떻게 하면 효율적으로 수행할 있을까 생각해보게 되었고, 결국 레지스터를 어떻게 하면 최대한 많이 넣고 많이 사용할 잇을까에 대해 생각해보게 되었다.

 

문제 인식 무어의 법칙을 근거로 다양한 기능 시도

1. 병렬적 작업을 하는 단일 프로세스만 수행할 , 하이퍼 스레딩기능을 끄고 하이퍼 스레딩을 위한 레지스터를 활용하면 많은 레지스터를 있지 않을까?

 


PROPOSAL

             <기존의 멀티코어 시스템>

 


예전 Pentium D processor 듀얼 코어와 달리 캐시와 버스 인터페이스를 cpu간에 공유하기 시작하면서 본격적으로 멀티코어 기술에 대한 관심이 많아졌고, 중에 Architectural State부분에서 아래와 같이 cpu내부에 스레드를 여러 두어 문맥 교환을 os 아닌 cpu에서 처리하도록 Hyper threading 기술이 있고 더욱 효율적인 Architectural state 가지로 제안을 하게 되었다

 

1.   기존의 cpu 번째 제안

 

1-1            기존의
 cpu 번째 제안

 

1- 2 제안

           

728x90
반응형

'공부 > 운영체제&시스템프로그래밍' 카테고리의 다른 글

myshell  (0) 2020.07.16
mycp  (0) 2020.07.16
EXT2 file system 실습 (6번 디렉토리안의 82번 파일 찾기)  (0) 2020.07.16
블로그 이미지

아상관없어

,
반응형

mysh.h

//header for myshell by 이창민, ckdals0115@naver.com

//mysh.h

#include<unistd.h>

#include<stdio.h>

#include<string.h>

#include<stdlib.h>

#include<wait.h>

#include<sys/stat.h>

#include<sys/types.h>

#include<fcntl.h>

#include<signal.h>

#include<errno.h>

#define MAX 100

//static int child_pid = 0;

//static int COUNT = 0;

//static char* COMMAND_PATH = "Desktop/Sys/mysh/";

void redirection_com(char** commands, int i);

void background_com(char** commands, int i);

char** get_tokens(char* CommandLine);

void execute_com(char** command);

 

mysh.c

//myshell by 이창민, ckdals0115@naver.com
//mysh.c 
#include"mysh.h"
void main(){
	write(STDOUT_FILENO,"+------------------------------------------------------------------------------------+\n",88);
	write(STDOUT_FILENO,"|MYSHELL                                                                             |\n",88);
	write(STDOUT_FILENO,"|------------------------------------------------------------------------------------|\n",88);
	write(STDOUT_FILENO,"|QUIT : quit                                                                         |\n",88);
	write(STDOUT_FILENO,"+------------------------------------------------------------------------------------+\n",88);

	while(1){
		//write시 쓰레기값 없게 초기화
		char CommandLine[MAX]={0};
		char PWD[MAX]={0};
		char** command;
		int read_size;
		int errno;
		/*char *getcwd(char *buf, int maxlen); => get pwd "unistd.h*/
		getcwd(PWD,MAX);
 	/////////////////////////////////////////////////////////////////
	//화면에 출력, write가 printf보다 빠르므로 write를 써봣음..
		write(STDOUT_FILENO, "@myshell:~", 20);
		write(STDOUT_FILENO, PWD, MAX);
		write(STDOUT_FILENO, "$ ",3);
	/////////////////////////////////////////////////////////////////
	//읽기
		/*입력받은 커맨드 command로 읽음*/
		read_size = read(STDIN_FILENO, CommandLine, MAX);
		//input enter
		if(read_size == 1){
			continue;}
	////////////////////////////////////////////////////////////////
	//명령어 구분하고 실행
		command = get_tokens(CommandLine);
		if(!strcmp(command[0],"quit")){
			printf("+------------------------------------------------------------------------------------+\n");
			printf("|BASH                                                                                |\n");
			printf("+------------------------------------------------------------------------------------+\n");
			exit(1);}
		else{
			execute_com(command);
		}
		
	}
}

mysh_funcs.c

//functions for myshell by 이창민, ckdals0115@naver.com
//mysh_funcs.c
/*
token구하기
명령수행
-shell bulitin
-/bin
-redirection
-background
 */
#include"mysh.h"
/////////////////////////////////////////////////////////////////////////////////////
////////CommandLine 쪼갬
char** get_tokens(char* CommandLine) {
	char **tokens;//토큰들을 저장할 배열
	char *token;
	int COUNT=0;
	//\n 대신 \0넣음
	CommandLine[strlen(CommandLine) - 1] = '\0';
	//토큰 저장할 배열 크기
	tokens = malloc((sizeof(char*))*MAX);
	//" "을 구분자로 자름
	token = strtok(CommandLine, " ");
	while(token != NULL){
		//\0포함해야하므로 +1
		tokens[COUNT] =malloc(strlen(token)+1);
		//동적할당 후 내용복사 
		strncpy(tokens[COUNT], token, strlen(token)+1);
		token = strtok(NULL, " ");
		COUNT++;
	}
	//토큰들 입력 끝나면 null
	tokens[COUNT] = NULL;
	return tokens;
}
//////////////////////////////////////////////////////////////////////////////////////
/////명령을 받으면 수행 
void execute_com(char **commands){
	int fork_process;
	int status;
	int i=0;
	char *dir;
	///////////////////////////////////////////////
	/////////shell builtin command  
	if(!strcmp(commands[0], "cd")){
		if(commands[1] == NULL){
			printf("USEAGE : cd directory\n");
			}
		chdir(commands[1]);
	}
	else if(!strcmp(commands[0], "pwd")){
		printf("Present Working Directory: %s\n",getcwd(dir, MAX));
	}
	///////////////////////////////////////////////
	///////////저장되어있는 명령어(/bin안에 존재)
	else {
		if((fork_process = fork())==0){
		//execv'P' 는 PATH에 등록된 모든 디렉토리에 있는 프로그램을 실행
			//명령어 끝까지 읽어서 각각 상황에 따라 실행
			while(commands[i]){
				if(!strcmp(commands[i],">")){
					redirection_com(commands, i);
				}
				else if(!strcmp(commands[i],"&")){
					background_com(commands, i);
				}
				i++;
			}
			//잘못된 commands[0]가 들어오면 -1 반환함
			if(execvp(commands[0],commands)==-1){
				printf("%s : command not found\n",commands[0]);
				exit(1);
			}
		}
		else if(fork_process < 0){
			printf("fork error\n");
			exit(1);
		}
		else
			wait(&status);
	}
}

//////////////////////////////////////////////////////////////////////
///////////명령어에 리다이렉션이 있을경우 수행
//ex) cat a.txt > b.txt
void redirection_com(char** commands, int i){
	char* to = commands[i+1];
	char* from = commands[i-1];
	int to_fd;

	to_fd = open(to, O_WRONLY | O_CREAT, 0641);
	if(to_fd < 0){
		printf("open error\n");
		exit(1);
	}
	//STDOUT_FILENO이 to_fd를 가리키게함
	dup2(to_fd, STDOUT_FILENO);
	//>자리를 NULL로
	commands[i] = NULL;
	//명령어 수행
	if(execvp(commands[0], commands)==-1){
		printf("No such command : %s\n",commands[0]);
                exit(1);
	}
}
/////////////////////////////////////////////////////////////////////////
////////명령어에 &이 있을경우 background processing 수행
void background_com(char** commands, int i){
	commands[i]=NULL;
	int fork_process;
	if((fork_process = fork())==0){
		if(execvp(commands[0], commands)==-1){
                printf("No such command : %s\n",commands[0]);
                exit(1);
		}
	}
	else if(fork_process<0){
		printf("fork error\n");
		exit(1);
	}
	//기다리지 않음
	else{
		exit(1);
	}
};

while1.c (단순 무한 루프)

#include<stdio.h>
int main(){
	while(1){
	}
	return 0;
}

Makefile

mysh: mysh.o mysh_funcs.o
gcc -o mysh mysh.o mysh_funcs.o

mysh.o: mysh.h mysh.c
gcc -c mysh.c

mysh_funcs.o: mysh.h mysh_funcs.c
gcc -c mysh_funcs.c

 

현재 ~디렉토리 $를 해주기 위해 getcwd를 사용하여 현재 디렉토리를 가져와 터미널에 출력하였다.

read systemcall을 사용하여 STDIN을 읽었다. 그리고 만약 엔터 \n만 치게된다면 다시 커맨드를 입력받을 수 있게 하였다.

명령어가 들어오면 execute_com를 실행하여 명령어를 실행하게 하였고, quit를 입력하면 myshell이 종료되게 하였다.

 

execute_com을 하려면 일단 입력받은 커맨드를 쪼개서 구분을 하여 명령을 처리해야한다. 따라서 get_tokens라는 토큰을 얻는 함수를 생성하였다. strtok함수를 이용하여 “ ”을 구분자로 하여 token화 하였다.

 

커멘드를 token으로 쪼개어 명령을 수행하는데, shell builtin 명령어들은 /bin에 저장되어있는 것이 아니라 bash가 동작할 때 수행하므로 각 명령어에 맞는 함수들을 사용하여 구현하였다.

shell builtin명령어들은 종류가 많이 있지만 각각 경우들을 비교하려면 수행시간이 길어지므로 cdpwd만 구현을 하였다.

 

따라서, strcmp함수를 사용하여 shell builtin명령어가 들어오면 builtin명령어인지 구분하여 실행을 한다.

 

그 외의 명령어들은 /bin에 있으므로 execvp를 사용하여 명령어를 실행한다. 환경변수 path에 디렉토리가 있으면 파일명만 입력하면 되므로 commands[0]을 인자로 넘겨준다.

 

리다이렉션의 경우, “from_file > to_file”의 형태이므로 STDOUT_FILENOto_file fd를 가리키게 한다.

그리고 “>” 앞의 명령어들을 실행하여 to_file에 그 결과들이 수행되게 한다.

 

백그라운드의 경우, fork를 한 후 부모프로세스는 자식프로세스를 wait하지 않게 하여 자식 프로세스가 백그라운드 프로세스로 돌아가도록 한다.

 

나머지 잘못된 사용을 하였을 시 잘못되었다고 예외처리들을 해주었다.

 

bashbuiltin 명령어들을 모두 구현하기 위해선 모든 builtin 명령어에 해당하는지 검사를 하고, 또 그에 따른 적절한 함수들을 사용해야하므로 코드가 길어지고 명령어 수행시간이 길어질 것 같았다.

따라서 cd, pwd와 같은 간단한 명령어만 수행하였다.

여기서 굳이 shell에서 builtin 명령어, 그 외 명령어로 구분지어 하나는 파일로 저장을 하고 하나는 쉘 내부에서 작동하게 하였는지 궁금하여 찾아보니, builtin 명령어들은 자주 사용되어 파일로 디스크에 저장해두면 매번 디스크에서 불러와야하므로 효율을 높이기 위해 램에 상주시키는 것을 알게 되었다.

728x90
반응형
블로그 이미지

아상관없어

,
반응형

 

//mycp app by changmin, ckdals0115@naver.com

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#define MAX 64

void main(int argc,char* argv[]){

	int original, copy, r_size;
	char buf[MAX];
	struct stat attribute;//stat 구조체선언  mode_t st_mode로 파일 권한을 가져오기위해 

	//쓰기잘못	
	if(argc != 3){
		printf("Wrong useage! USAGE : %s \"original_file\" \"copy_file\" \n",argv[0]);
		exit(-1);}
	//orignal 파일 열기
	original = open(argv[1],O_RDONLY);
	//파일 open 실패시
	if(original < 0){
		printf("can't open file\n");
		exit(-1);}
	
	if(stat(argv[1], &attribute)==-1){//original file 속성가져옴 실패시 에러
		printf("getting attribute error\n");
		exit(-1);}
	
	
	mode_t original_permisson = attribute.st_mode;//original의 st_mode를 가져옴
	



	copy = open(argv[2],O_WRONLY|O_CREAT|O_EXCL,original_permisson);//쓰기로 읽고 권한을 original파일의 권한을 줌
	//파일 open 실패시
	if(original < 0){
                printf("can't open file\n");
                exit(-1);}
	//파일끝까지 읽고 씀
	while((r_size = read(original,buf,MAX)) >0){
		write(copy,buf,r_size);
	}
}
728x90
반응형
블로그 이미지

아상관없어

,
반응형

Boot Sector의 크기는 2 Sector = 1KB(0x400)이므로 Super Block의 위치는 0x400부터 시작한다.

해당위치로 이동하면,

Log Block Size( 블록 크기 ) = 0x2000, Inode Per Group( 각 블록그룹에 속한 inode ) = 0xef53, Block Per Group( 각 블록 그룹에 속한 block ) = 0x8000을 얻을 수 있다.

Ext2에서 Root inode number2이다. 따라서 (inode number – 1)/block per group을 하면 Rootinode가 속한 그룹은 0번임을 알 수 있다. 그리고 (inode number -1)%block per group을 하여 Root index1임을 알 수 있다.

그리고 Root안의 데이터를 보기위해 Group Descriptor Table을 보아 Group 0 inode Table 시작위치를 얻는다.

 

첫 번째 Group Descriptor Tableramdisk1블록(4KB = 0x1000) 이후부터 시작하므로 해당 위치로 이동하면

각 그룹의 inode Table을 구하면

(단위 : block)

Group 0 = 0x23

Group 1 = 0x8023

Group 2 = 0x10002

Group 3 = 0x18023

이다.

 

Root가 속한 Group 0inode Table에서 1번째 inode를 찾는다. ( Inode의 크기는 0x100byte, index = 1 )

첫번째 블록 포인터인 0x223000을 찾아서 데이터 영역으로 이동을 한다.

Record len으로 디렉토리 엔트리의 크기를 알아내고, file type으로 디렉토리를 찾고, 이름을 얻는다. 그중 32153”6/82”에 해당하는 6번 디렉토리의 inode를 찾는다.

6번 디렉토리 inode number = 0x6066

속한 Block Group = (0x6066 – 1)/0x2000 = 3

Inode Table Index = (0x6066 – 1)%0x2000 = 101

 

6번 디렉토리가 Block Group 3 inode Table101번째에 있음을 알 수 있다.

 

Block Group 3inode Table에서 101번째 inode로 이동을 한다.

=>0x18029600

Block pointer 0번을 얻고 이동을 한다.

=>0x8458000

6번 디렉토리가 있음을 확인할 수 있다.

 

학번의 끝이 682이므로 0x18029600에서 82번 뒤로 이동을 한다.

=>0x1802e800

Block Pointer 0 = 0x84aa000

Block Pointer 1 = 0x107ba000

Block Pointer 2 = 0x107d2000

 

Indirect Block Pointer 0 = 0x10204000

을 얻을 수 있다.

 

해당 블록의 위치로 이동을 하면 다음의 그림과 같이 데이터를 찾을 수 잇다.

 

 

마지막 indirect block pointer13번째 blockinode를 찾아내고 이동하여 데이터를 찾았다.

728x90
반응형

'공부 > 운영체제&시스템프로그래밍' 카테고리의 다른 글

New Architectural state structure  (0) 2021.06.21
myshell  (0) 2020.07.16
mycp  (0) 2020.07.16
블로그 이미지

아상관없어

,