처음부터 차근차근

Unix 기본 시스템 함수 - getopt(), time(), localtime(), localtime_r(), ftime(), gettimeofday(), mktime(), 파일 기술자, bcopy() 본문

Linux & Unix

Unix 기본 시스템 함수 - getopt(), time(), localtime(), localtime_r(), ftime(), gettimeofday(), mktime(), 파일 기술자, bcopy()

_soyoung 2022. 4. 15. 17:18
반응형

getopt()

#include <stdio.h> // c 언어 파일 작성할 때 필요한 헤더
#include <stdlib.h>
#include <string.h> // string 헤더
#include <unistd.h> // unix 계열 헤더

// argc : 명령 파라미터의 개수(자기 자신까지 1개로 침)
// argv[] : 각각의 아규멘트의 값들(argv[0]는 자기자신)
int main(int argc, char* argv[]) {

	// 옵션 넣을 변수 생성
	int nOpt;

	printf("Original\n");

	// 파일 실행할 때 입력한 매개변수들 모두 출력
	for (int i = 0; i < argc; i++) {
		printf("value[%d] : %s\n", i, argv[i]);
	}

	printf("--------Options-------\n");

	// getopt() : 옵션을 찾아내는 함수
	while ((nOpt = getopt(argc, argv, "abc")) != -1) {
		// 옵션을 찾아내서 출력한다.
		printf("Option : %c\n", nOpt);
	}

	return 0;
}

실행결과

명령어, 파라미터, 사용된 옵션들이 출력되었다.

 

 

 

#include <stdio.h> // c 언어 파일 작성할 때 필요한 헤더
#include <stdlib.h>
#include <string.h> // string 헤더
#include <unistd.h> // unix 계열 헤더

// argc : 명령 파라미터의 개수(자기 자신까지 1개로 침)
// argv[] : 각각의 아규멘트의 값들(argv[0]는 자기자신)
int main(int argc, char* argv[]) {

	// 옵션 넣을 변수 생성
	int nOpt;

	// 옵션과 다음에 넣은 값을 출력한다.
	// optarg : 옵션 다음에 입력한 값
	while ((nOpt = getopt(argc, argv, "s:d:h")) != -1) {
		switch (nOpt) {
		// 옵션이 s면
		case 's' :
			printf("s : %s\n", optarg);
			break;
		// 옵션이 d면
		case 'd':
			printf("d : %s\n", optarg);
			break;
		// 옵션이 h나 다른 옵션을 넣으면
		case 'h':
		default:
			printf("Usage : %s [-s value] [-d value] value\n",
				argv[0]);
			// 종료
			return -1;
		}
	}

	// 옵션 값에 해당되지 않는 파라미터 값을 출력
	// optind : 옵션의 인덱스
	// 옵션 값 아닌 파라미터 값을 뒤가 아닌 앞에 붙여도 상관없다. getopt() 함수가 다시 정렬해주기 때문
	for (; optind < argc; optind++) {
		// 인덱스는 5부터 시작함
		printf("value[%d] : %s\n", optind, argv[optind]);
	}
	return 0;
}

실행결과

s 옵션 값으로 aa가 입력되었고, d옵션 값으로 bb가 입력되었다는 것이 출력되었다.

그리고 옵션 값에 해당하지 않는 파라미터 cc, dd가 출력되었다.

 

 

 

#include <stdio.h> // c 언어 파일 작성할 때 필요한 헤더
#include <time.h> // time() 함수 헤더
#include <unistd.h> // unix 계열 헤더

int main(void) {
	// time 변수
	time_t timeCurrent = 0;

	// 10번 반복
	// 현재의 시간을 출력한다.
	for (int i = 0; i < 10; i++) {
		// time() : 현재 시각을 1970년 1월 1일을 기준으로 초 단위 값 추출
		timeCurrent = time(NULL);
		printf("Current time is %d\n", timeCurrent);
		sleep(1);
	}

	return 0;
}

실행결과

현재 시간이 1초 간격으로 10번 출력되었다.

 

 

 

localtime()

#include <stdio.h> // c 언어 파일 작성할 때 필요한 헤더
#include <time.h> // time() 함수 헤더
#include <unistd.h> // unix 계열 헤더
#include "print_localtime.h" // print_localtime 헤더 include

int main(void) {
	// time 변수
	time_t timeCurrent;

	// 연월일 넣을 변수
	struct tm* tmCurrent;

	// 현재 시간 뽑기
	time(&timeCurrent); 

	// 뽑은 현재 시간 출력
	printf("Current Time : %d\n", timeCurrent);

	// 우리가 알아볼 수 있게 변환(연 월 일)
	tmCurrent = localtime(&timeCurrent);
	print_localtime(*tmCurrent);

	return 0;
}

실행결과

현재 시간이 초 단위로 출력되었고,

초 단위로 출력된 시간이 다시 연,,일로 변환되어 출력되었다.

 

 

 

#include <stdio.h> // c 언어 파일 작성할 때 필요한 헤더
#include <time.h> // time() 함수 헤더
#include <unistd.h> // unix 계열 헤더
#include "print_localtime.h" // print_localtime 헤더 include

int main(void) {
	// time 변수
	time_t timeCurrent;

	// 연월일 넣을 변수
	struct tm* tm1;
	struct tm* tm2;

	// 현재 시간 뽑기
	time(&timeCurrent);

	// 연 월 일로 변환
	tm1 = localtime(&timeCurrent);

	// 1초 쉬기
	sleep(1);

	// 현재 시간 뽑기
	time(&timeCurrent);

	// 연 월 일로 변환
	tm2 = localtime(&timeCurrent);

	// 출력
	print_localtime(*tm1);
	print_localtime(*tm1);

	return 0;
}

실행결과

localtime() 함수는 static처럼 정적으로 선언되어 있어서 원래 1초 뒤의 시간을 출력해야 되는데 그렇지 않은 게 결과로 보인다.

 

 

 

localtime_r()

#include <stdio.h> // c 언어 파일 작성할 때 필요한 헤더
#include <time.h> // time() 함수 헤더
#include <unistd.h> // unix 계열 헤더
#include "print_localtime.h" // print_localtime 헤더 include

int main(void) {
	// time 변수
	time_t timeCurrent;
	struct tm tm1;
	struct tm tm2;

	// 현재 시간 뽑기
	time(&timeCurrent);

	// 연 월 일로 변환
	localtime_r(&timeCurrent, &tm1);

	// 1초 쉬기
	sleep(1);

	// 현재 시간 뽑기
	time(&timeCurrent);

	// 연 월 일로 변환
	localtime_r(&timeCurrent, &tm2);

	// 출력
	print_localtime(tm1);
	print_localtime(tm2);

	return 0;
}

실행결과

Localtime() 함수와 다르게 1초가 지나면 1초 지난 시간으로 출력된다.

두번째 인자에 변환 결과를 기록하기 때문에 값이 변한 상태로 출력되는 것이다.

 

 

 

ftime()

#include <stdio.h> // c 언어 파일 작성할 때 필요한 헤더
#include <time.h> // time() 함수 헤더
#include <sys/timeb.h> // timeb 사용할 때 필요한 함수
#include <unistd.h> // unix 계열 헤더

int main(void) {
	// time 변수
	struct tm tmCurrent;
	struct timeb tmb;

	// 현재 시간 뽑기
	time(&tmb);

	// 연 월 일로 변환
	localtime_r(&(tmb.time), &tmCurrent);

	// 현재 time 출력
	printf("Current : %04d/%02d/%02d %02d:%02d:%02d\n",
		tmCurrent.tm_year + 1900,
		tmCurrent.tm_mon + 1,
		tmCurrent.tm_mday,
		tmCurrent.tm_hour,
		tmCurrent.tm_min,
		tmCurrent.tm_sec,
		tmb.millitm
	);

	return 0;
}

실행결과

초가 지날 때마다 시간이 변하는 것을 볼 수 있다.

 

 

 

gettimeofday()

#include <stdio.h> // c 언어 파일 작성할 때 필요한 헤더
#include <time.h> // time() 함수 헤더
#include <sys/time.h> 
#include <unistd.h> // unix 계열 헤더

int main(void) {
	struct timeval tv;
	struct tm tmCurrent;

	// gettimeofday() : 현재 시각을 마이크로초 단위의 값으로 추출하는 함수
	gettimeofday(&tv, NULL);

	// 연 월 일로 변환
	localtime_r(&(tv.tv_sec), &tmCurrent);

	// 현재 time 출력
	printf("Current : %04d/%02d/%02d %02d:%02d:%02d.%06d\n",
		tmCurrent.tm_year + 1900,
		tmCurrent.tm_mon + 1,
		tmCurrent.tm_mday,
		tmCurrent.tm_hour,
		tmCurrent.tm_min,
		tmCurrent.tm_sec,
		tv.tv_usec
	);

	return 0;
}

실행결과

gettimeofday() 함수에 의하여 시간이 초까지 더 세밀하게 출력된 것을 볼 수 있다.

 

 

 

mktime()

#include <stdio.h> // c 언어 파일 작성할 때 필요한 헤더
#include <time.h> // time() 함수 헤더
#include <sys/time.h> 
#include <unistd.h> // unix 계열 헤더

int main(void) {
	// time 구조체와 변수
	struct tm tm1;
	time_t timeCurrent = 0;

	// 값 설정
	tm1.tm_year = 2021 - 1900;
	tm1.tm_mon = 4 - 1;
	tm1.tm_mday = 14;
	tm1.tm_hour = 20;
	tm1.tm_min = 30;
	tm1.tm_sec = 5;
	tm1.tm_isdst = -1;
	
	// mktime() : struct tm 형태의 시각정보를 초 단위의 UNIX 시간 정보로 변환하는 함수
	timeCurrent = mktime(&tm1);

	// mktime() 함수 결과 값이 실패이면
	if (timeCurrent == -1) {
		printf("-unknown-\n");
	}
	// 성공하면
	else {
		printf("Seconds: %ld\n", timeCurrent);
	}

	return 0;
}

실행결과

초 단위의 UNIX 시간 정보로 변환해서 출력한 것을 볼 수 있다.

 

 

 

파일기술자

#include <stdio.h> // c 언어 파일 작성할 때 필요한 헤더
#include <unistd.h> // unix 계열 헤더
#include <sys/stat.h> // 파일 작업할 때 필요한 헤더
#include <sys/types.h> // 파일 작업할 때 필요한 헤더
#include <fcntl.h> // 파일 작업할 때 필요한 헤더
#include <string.h> // string 헤더
#include <stdlib.h> // random() 사용하기 위한 헤더
#include <time.h> // time() 사용하기 위한 헤더
#define MAX_FD 16 // 상수 정의

int main(void) {

	int fd[MAX_FD];
	int fdCnt;
	int i;
	int nRandom;
	char buffer[BUFSIZ]; // 버퍼
	time_t currentTime; // time 변수

	// 메모리 세팅 함수
	// fd : 세팅하고자하는 메모리의 시작주소
	// 0 : 메모리에 세팅할 값
	// sizeof(fd) : 세팅할 크기(byte 단위)
	memset(fd, 0, sizeof(fd));

	// 현재 시각 초 단위 값으로 추출(1970.01.01 기준)
	currentTime = time(NULL);

	// 난수를 발생시키는 seed 값을 재설정해주는 함수
	srandom((unsigned int)currentTime);

	// (난수 + 1) % 16
	nRandom = (random() + 1) % MAX_FD;
	
	for (fdCnt = 0; fdCnt < nRandom; fdCnt++) {
		// buffer : 출력값 저장할 버퍼, "./test%d.txt" : 서식 문자열, fdCnt : 서식 연산자에 치환할 값
		sprintf(buffer, "./test%d.txt", fdCnt);
		
		// 버퍼 안에 들어간 경로의 파일을 읽기 전용으로 열되, 없으면 새로만든다.(소유자 : 읽기/쓰기(6), 나머지 : 읽기(4) 권한으로)
		fd[fdCnt] = open(buffer, O_CREAT|O_RDONLY, 0644);
	}

	// 프로세스 아이디 구해서 출력
	printf("Process_Number : %d\n", getpid());

	printf("The number of FDs is %d\n", fdCnt);
	getchar(); // 키보드 한 개를 입력받음

	// 16번 반복하여 fd(open한 파일들)를 모두 close
	for (i = 0; i < MAX_FD; i++) {
		if (fd[i] > 0) {
			close(fd[i]);
		}
	}

	for (i = 0; i < fdCnt; i++) {
		// sprintf로 파일 경로 세팅
		sprintf(buffer, "./test%d.txt", i);

		// 파일 삭제
		unlink(buffer);
	}

	return 0;
}

 

실행결과

실행시켰더니 프로세스 아이디와 만들어진 파일의 개수가 출력되고,

현재 경로에 test~.txt 파일들이 생긴 것을 볼 수 있다.

그 다음 enter을 쳤더니(getchar()로 인해 키보드 한 개 입력받음) 만들어졌던 파일들이 다 삭제되었다.

 

 

 

bcopy()

바이트 배열 처리 함수

#include <stdio.h> // c 언어 파일 작성할 때 필요한 헤더
#include <string.h> // string 헤더
#include <strings.h> // strings 헤더

int main(void) {

	// 20 크기의 배열 정의(안의 값은 모두 0으로 초기화)
	char p_strText1[20] = { 0, };
	char p_strText2[20] = { 0, };
	for (int i = 0; i < 20; i++) {
		// p_strText1 배열 안에 'a' + i 값 넣음
		p_strText1[i] = 'a' + i; // abcde....
	}

	// 각각의 배열에 어떤 값이 들어가 있는지 출력
	printf("Text1 : %s\n", p_strText1); // 아까 넣은 abcd... 가 나옴
	printf("Text2 : %s\n", p_strText2); // 아직 아무 값도 없음
	printf("Calling bcopy().\n");

	// p_strText1를 p_strText2에다 복사(20 byte 복사)
	bcopy(p_strText1, p_strText2, 20); 

	// 각각의 배열에 어떤 값이 들어가 있는지 출력
	printf("Text1 : %s\n", p_strText1); // abcd...
	printf("Text2 : %s\n", p_strText2); // abcd...

	return 0;
}

실행결과

Text1 내용이 복사되어 Text2에도 똑같이 출력된다.

 

 

 

출처 : 네트워크개론(22-1학기)김병국교수 강의 내용 변형 및 요약

반응형
Comments