4-7 Thread (과제)

do·2022년 5월 13일
0

API

목록 보기
33/42
  1. 4-6 Process의 과제-2를 멀티 쓰레드로 변경하여 프로그램을 작성하시오.
  2. 입력 및 출력 조건은 동일함

thread.c

#include <stdio.h>
#include <unistd.h> //access()
#include <pthread.h> //pthread_create(), pthread_join()
#include <stdlib.h> //exit()
#include <sys/stat.h> //stat()
#include <string.h> //strstr()
#include <errno.h>

enum { LINES_PER_CHILD = 20, BUFSIZE = 500 };

char* search;
char* path;

typedef struct Info
{
	int cnt;
	int ptr;
} Info;

void *t_function(void *data)
{
	Info *temp = (Info *)data;

	char filename[50];
	snprintf(filename, sizeof(filename), "./temp%d.txt", temp->cnt);

	printf("Thread #%d\n", temp->cnt);
	printf("Searching %s in %s [%d~]\n", search, path, temp->ptr);
	printf("Saving in %s..\n", filename);
	printf("=============================\n");

	FILE* fp;
	fp = fopen(path, "r");
	if (fp == NULL) {
		perror("fopen()");
		return NULL;
	}
	fseek(fp, temp->ptr, SEEK_SET);

	FILE* fp_temp;
	fp_temp = fopen(filename, "w+");
	if (fp_temp == NULL) {
		perror("fopen()");
		if (fclose(fp) != 0) {
			perror("fclose()");
			return NULL;
		}
		return NULL;
	}

	char buf[BUFSIZE];
	int lineCheck = 1;
	while (fgets(buf, sizeof(buf), fp) != NULL) {
		if (lineCheck > LINES_PER_CHILD) {
			break;
		}
		if (strstr(buf, search) != NULL) {
			fprintf(fp_temp, "%d:%s", lineCheck + (temp->cnt * LINES_PER_CHILD), buf);
		}
		lineCheck++;
	}

	if (fclose(fp) != 0) {
		perror("fclose()");
		return NULL;
	}
	if (fclose(fp_temp) != 0) {
		perror("fclose()");
		return NULL;
	}

	return NULL;
}

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

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

	/* 인자로 받은 문자열 & 파일 */
	search = argv[1];
	path = argv[2];

	/* 라인 갯수, 스레드 갯수, 파일의 포인터 위치 확인 위해 파일 열기 */
	FILE* fp_init;
	fp_init = fopen(argv[2], "r");
	if (fp_init == NULL) {
		perror("fopen()");
		exit(EXIT_FAILURE);
	}

	/* 라인 갯수 */
	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 nThread = 0;
	nThread = (line / LINES_PER_CHILD) + 1;
	//printf("[%d 스레드 갯수]\n", nThread);

	int i = 0;
	int a = 0;
	int b = 0;
	int point[nThread]; //포인터 위치

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

	/* 라인 n줄(LINES_PER_CHILD)마다 포인터 위치 확인, point[]에 저장 */
	while (fgets(buffer, sizeof(buffer), fp_init) != NULL) {
		if (a == 0) {
			point[b] = 0;
			//printf("%d줄 파일포인터 %d\n", a, point[b]);
			b++;
		}
		else {
			if (a % LINES_PER_CHILD == LINES_PER_CHILD - 1) {
				point[b] = (int)ftell(fp_init) ;
				//printf("%d줄 파일포인터 %d\n", a, point[b]);
				b++;
			}
		}
		a++;
	}

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

	/* 스레드 */
	pthread_t p_thread[nThread];

	/* 몇번째 스레드인지, 스레드 내 파일 위치 정보 */
	Info info[nThread];

	/* 스레드 nThread개 생성 */
	for (i = 0; i < nThread; i++) {
		info[i].cnt = i;
		info[i].ptr = point[i];

		if (pthread_create(&p_thread[i], NULL, t_function, (void *)&info[i]) != 0) {
			perror("pthread_create()");
			exit(EXIT_FAILURE);
		}
	}

//	void *status;
	/* 각 스레드 종료를 기다림 */
	for (i = 0; i < nThread; i++) {
		if (pthread_join(p_thread[i], (void *)NULL) != 0) {
			perror("pthread_join()");
			exit(EXIT_FAILURE);
		}

//		printf("Thread #%d [%p]\n", i, status);
	}
	
	char name[50];
	int size = 0;
	int total = 0;

	/* 최종 결과 화면 출력 및 임시 파일들 삭제 */
	for (i = 0; i < nThread; i++) {
		snprintf(name, sizeof(name), "./temp%d.txt", i);
		
		FILE* fp_final;
		fp_final = fopen(name, "r");
		if (fp_final == NULL) {
			perror("fopen()");
			exit(EXIT_FAILURE);
		}

		struct stat s2;
		if (stat(name, &s2) == -1) {
			perror("stat()");
			exit(EXIT_FAILURE);
		}
		
		size = (int)s2.st_size;
		printf("\n[ 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(name);
	}

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

	return 0; 
}

0개의 댓글