4-6 Process (과제-2)

do·2022년 5월 10일
0

API

목록 보기
31/42

1. 문제 :
a. 과제-1을 grep 명령어를 호출하는게 아니라 직접 멀티 프로세스로 구현하기
b. 부모 프로세스는 자식 프로세스를 n개를 생성하여, n개의 자식 프로세스가 파일에서 찾는 범위를 나눠서 파일에서 매칭되는 문자열을 찾고, 부모 프로세스는 자식 프로세스에서 찾은 결과를 취합해서 화면에 출력한다.
c. 자식 프로세스의 수는 대상이 되는 파일의 크기에 따라 가변이 되도록 한다. 파일 크기에 따라 몇 개의 프로세스를 실행할지는 구현하는 사람이 선택한다.
d. 자식 프로세스에서 찾은 결과는 임시 파일에 저장하고, 부모 프로세스는 자식 프로세스가 종료되면 임시 파일들을 이용하여 최종 결과를 화면에 출력하고 임시 파일들은 삭제한다.
2. 입력 : 프로그램 실행 시, 인자로 파일명과 찾을 문자열을 입력받는다. 파일명은 1개로 제한한다. (프로그램명 찾을문자열 파일명)
3. 출력 :
a. 정상적인 경우는 파일에서 찾은 문자열이 존재하는 line번호와 해당 라인 정보를 출력한다. (grep 출력 양식 그대로 사용)

입력) my_grep2 float dcl.c
출력)
 6:	float degrees= 0.0012f;
 7:	float radians;
 8:	float const pi = 3.14159;
 9:	float radians2;

b. 파일에 찾을 문자열이 존재하지 않는 경우, 문자열이 존재하지 않는다는 문구를 출력

입력) my_grep2 test dcl.c
출력) "test" not found in dcl.c

c. 파일이 존재하지 않는 경우, 파일이 없다는 문구를 출력

입력) my_grep2 float test.c
출력) test.c is not existed

my_grep2.c

#include <stdio.h>
#include <fcntl.h> //open()
#include <unistd.h> //access()
#include <string.h> //strstr()
#include <unistd.h> //fork() unlink()
#include <wait.h> //wait() waitpid()
#include <sys/stat.h> //stat()
#include <stdlib.h> //exit()

enum { LINES_PER_CHILD = 20, BUFSIZE = 255 };

int main(int argc, char *argv[])
{
	if (argc != 3) {
		printf("인자를 잘 못 입력하였습니다\n");
		return 0;
	}

	const char *search = argv[1];
	const char *path = argv[2];

	if (access(path, F_OK) == -1) {
		printf("%s is not existed\n", path);
		return 0;
	}

	/* 라인 갯수 및 자식 프로세스 갯수 확인 위해 파일 열기 */ 
	FILE* fp_init;
	fp_init = fopen(path, "r");
	if (fp_init == NULL) {
		perror("fopen()");
		exit(EXIT_FAILURE);
	}

	char buffer[BUFSIZE];
	memset(buffer, 0, sizeof(buffer));

	/* 라인 갯수 확인 */
	char c;
	int line = 0;
	while ((c = fgetc(fp_init)) != EOF) {
		if (c == '\n') {
			line++;
		}
	}
	printf("[%d 라인 갯수]\n", line);
	fseek(fp_init, 0, SEEK_SET);

	/* 자식 프로세스 갯수 */
	int nChild = 0;
	nChild = (line / LINES_PER_CHILD) + 1;
	printf("[%d 자식 프로세스 갯수]\n", nChild);

	int a = 0;
	int cnt = 0;
	int point[nChild];

	/* 파일포인터 위치 확인 */
	while ((fgets(buffer, sizeof(buffer), fp_init)) != NULL) {
		if (a == 0) { //0줄일때
			point[cnt] = 0;	
			printf("%d줄 파일포인터 %d\n", a, point[cnt]);
			cnt++;
		}
		else { //19, 39, 59
			if (a % LINES_PER_CHILD == LINES_PER_CHILD - 1) {
				point[cnt] = (int)ftell(fp_init);
				printf("%d줄 파일포인터 %d\n", a, point[cnt]);
				cnt++;
			}
		}
		a++;
	}

	/* 파일 닫기 */
	if (fclose(fp_init) != 0) {
		perror("fclose()");
		exit(EXIT_FAILURE);
	}
	
 	char filename[50];
	pid_t pid[nChild];

	int i = 0;
	for (i = 0; i < nChild; i++) {
		pid[i] = fork();

		if (pid[i] == 0) { /* 자식 프로세스 */
			printf("[%d 자식 프로세스]\n", getpid());
			
			int lineCheck = 1;
			
			FILE* fp;
			fp = fopen(path, "r");
			if (fp == NULL) {
				perror("fopen()");
				exit(EXIT_FAILURE);
			}

			/* 파일 포인터 위치 */
			fseek(fp, point[i], SEEK_SET);

			FILE* fp_temp;
			snprintf(filename, sizeof(filename), "./temp%d.txt", i);
			fp_temp = fopen(filename, "w+");
			if (fp_temp == NULL) {
				perror("fopen()");
				exit(EXIT_FAILURE);
			}

			while (fgets(buffer, sizeof(buffer), fp) != NULL) {
				/* 20줄 이상 읽으면 반복문 중지 */
				if (lineCheck > LINES_PER_CHILD) {
					break;
				}
				
				/* 문자열 검색 후 저장 */
				if (strstr(buffer, search) != NULL) {
					fprintf(fp_temp, "%d:%s", lineCheck + (i * LINES_PER_CHILD) , buffer);
				}

				lineCheck++;
			}

			if (fclose(fp) != 0) {
				perror("fclose()");
				exit(EXIT_FAILURE);
			}
			if (fclose(fp_temp) != 0) {
				perror("fclose()");
				exit(EXIT_FAILURE);
			}

			exit(0);
		}
		else if (pid[i] > 0) {
			
		}
		else if (pid[i] == -1) {
			perror("fork()");
			exit(EXIT_FAILURE);
		}
	}

	printf("[%d 프로세스]\n", getpid());

	/* 자식 프로세스 종료 회수 */
	int status = 0;
	for (i = 0; i < nChild; i++) {
		if (waitpid(pid[i], &status, 0) == -1) {
			perror("waitpid()");
			exit(EXIT_FAILURE);
		}
		if (WIFEXITED(status) != 0) {
			printf("[%d 자식 프로세스 정상 종료]\n", pid[i]);
		}
	}

	printf("\n");

	int size = 0;
	int total = 0;

	/* 임시 파일들 읽기 및 삭제 */
	for (i = 0; i < nChild; i++) {
		FILE* fp_final;
		snprintf(filename, sizeof(filename), "./temp%d.txt", i);
		fp_final = fopen(filename, "r");
		if (fp_final == NULL) {
			perror("fopen()");
			exit(EXIT_FAILURE);
		}

		struct stat s2;
		if (stat(filename, &s2) == -1) {
			perror("stat()");
			exit(EXIT_FAILURE);
		}
		
		size = (int)s2.st_size;
		printf("file size %d\n", size);
		
		total += size;

		while (fgets(buffer, sizeof(buffer), fp_final) != NULL) {
			printf("%s", buffer);	
		}

		if (fclose(fp_final) != 0) {
			perror("fclose()");
			exit(EXIT_FAILURE);
		}

		unlink(filename);
	}

	if (total == 0) {
		printf("\"%s\" not found in %s\n", search, path);
	}

	return 0;
}

0개의 댓글