[Tasks] 운영체제 HW1
💼

[Tasks] 운영체제 HW1

카테고리
📒 Assignment
작성자
박용성박용성
작성일
2024년 06월 02일
태그
C
Slug
task-os-1
문제문제 해결0. 문제 해결을 위한 분석1. 리눅스 설치2. 마피아 문제 해결1. linuxtown_class1 파일을 실행하려고 했는데, 실행할 수 없다고 함2. C언어 상에서 어떻게 linuxtown_class1 을 실행해야 할까?3. 실행시킨 프로세스들의 PID를 어떻게 C언어로 불러올까?4. PID 목록을 파일로 저장 후, 시그널을 주는 방법?5. 이제 하나하나 PID를 순회하며 시그널을 전달 후 마피아를 찾는 법6. 그렇다면 마피아를 찾을 solution 함수는 어떻게 구현해야 할까?7. 총 마피아의 수는? (결과는?)번외 1. 파일 크기를 가져오는 함수는 어떻게 구현하나?번외 2. 왜 perror 와 exit(EXIT_FAILURE) 을 사용했나?실행 과정과 결과1. answer 실행파일 생성2. 실행파일 실행 (linuxtown_class1도 같이 실행되고, 10초 후 부모 프로세스 재실행)1-1. ver2 로 로직을 변경하고 터미널을 2개 사용해서 값이 같은지 확인할 수 있음 (물론 linuxtown_class1 이 재시작되면 PID도 달라짐)성공한 코드 전체ver1 : linuxtown_class1 을 내부에서 실행하는 버전ver2 : linuxtown_class1 을 외부에서 실행해야 하는 버전시행 착오번외. 처음 실행할 때 오류?1. PID를 배열로 먼저 전부 저장한 후, 이를 텍스트 파일과 비교하려고 시도2. fork를 사용해 linuxtown_class1 을 실행시킨 후 작성한 C언어 코드를 실행3. 텍스트 파일 변경 여부를 확인하지 않고 진행4. 한 프로그램에서 전부 실행되도록 변경소감참고문헌
 
학번 : 2020039069 이름 : 박용성

문제

리눅스 마을에 200개의 프로세스가 살고 있고, 그 중 시민으로 변장한 마피아 프로세스가 숨어 있다.
첩보에 따르면, 마피아 프로세스는 특정 시그널 SIGUSR1에 반응을 보인다고 한다.
 

문제 해결

0. 문제 해결을 위한 분석

아래와 같은 두 가지 버전을 만들 수 있다고 생각했습니다.
  • ver1
    • linuxtown_class1 파일을 C언어 내부에서 실행시킨 후, 마피아 찾기 프로세스 시작 → 수업시간에 배운 fork()exec() 을 통해 구현할 수 있었습니다.
  • ver2
    • linuxtown_class1 파일을 외부에서 실행시킨 후, 마피아 찾기 프로세스를 시작 → 터미널을 하나 더 열어 ./linuxtown_class1 실행 후 ./answer 실행하는 방식으로 구현했습니다.
 

1. 리눅스 설치

현재 맥북을 사용중이라 ARM 버전 Linux Server을 설치했는데, cannot execute binary file 오류가 발생했습니다.
→ 서칭을 하니 아키텍처가 달라 발생하는 오류라고 합니다.
 
이를 해결하고자 x86_64 Linux을 설치해 보거나, 윈도우를 설치해 그 안에서 WSL을 사용하는 방향을 생각해 모두 실행해보았지만 모두 오류가 발생했습니다.
 
→ 계속 찾아보다 보니, Orbstack 에서 amd64 버전 리눅스를 도커로 쓸 수 있다고 해서 시도해보았고, 성공했습니다.
💡
도커에서 docker run -it --name ubuntu --platform=linux/amd64 ubuntu:20.04 bash 명령어 수행
 

2. 마피아 문제 해결

과제를 수행하며 많은 난관에 부딪혔습니다. 문제를 해결하며 순서대로 로직을 구현했습니다.
 

1. linuxtown_class1 파일을 실행하려고 했는데, 실행할 수 없다고 함

chmod +x linuxtown_class1 명령어를 실행해서 실행 권한을 주어 해결
 

2. C언어 상에서 어떻게 linuxtown_class1 을 실행해야 할까?

execv 함수를 이용했습니다. exec 함수는 계속 오류가 나서 같은 계열의 함수인 execv 함수로 대체했습니다.
if ((pid_linuxtown = fork()) == 0) { char *args[] = {"linuxtown_class1", NULL}; execv(args[0], args); perror("exec"); // exec가 실패하면 에러 메시지 출력 } else { ...
  • ver2 에서는 이 과정이 생략되어 있습니다.
 

3. 실행시킨 프로세스들의 PID를 어떻게 C언어로 불러올까?

cmd 를 이용해 snprintf 로 PID를 불러왔습니다.
 
FILE *pid_fp; // 프로세스 PID를 가져오기 위한 파일 포인터 선언 char cmd[] = "linuxtown_class"; // 프로세스 CMD 이름 char pid_buffer[BUFFER_SIZE]; // PID 임시 버퍼 // pgrep 명령어를 통해 linuxtown_class 명령어를 실행 중인 프로세스 PID를 가져옴 snprintf(pid_buffer, sizeof(pid_buffer), "pgrep -x %s", cmd); pid_fp = popen(pid_buffer, "r");
  • snprintf : 버퍼와 버퍼 사이즈, format-string과 argument를 받아 포맷팅하여 pid_buffer 에 저장합니다.
  • pid_fp = popen(pid_buffer, "r"); : pid_buffer에 저장된 명령어를 실행하고, 실행한 명령어 파일을 r 모드로 읽은 후 그 결과를 pid_fp 에 저장합니다. 그러므로 pid_fp 에는 PID들의 리스트가 저장됩니다.
 

4. PID 목록을 파일로 저장 후, 시그널을 주는 방법?

→ 시그널은 kill 명령어로 줄 수 있습니다. 리눅스 상에서는 kill -시그널 PID 로 가능하고, C언어에서는 kill(PID, 시그널) 로 가능합니다. 제대로 시그널이 전달되지 않으면 -1을 반환합니다.
 

5. 이제 하나하나 PID를 순회하며 시그널을 전달 후 마피아를 찾는 법

// PID를 하나하나 순회하면서 시그널 주고, 마피아 찾기 while (fgets(pid_buffer, BUFFER_SIZE, pid_fp) != NULL) { // pid를 숫자로 변환해서 kill 시그널 주기 pid_t pid = atoi(pid_buffer); // 오류 처리 if (kill(pid, SIGUSR1) == -1) { perror("시그널 전달 실패"); } else { off_t cur_file_size; do { cur_file_size = get_file_size("confession.txt"); usleep(100000); // 파일 크기 변경 체크를 위한 여유시간 설정 } while (cur_file_size == pre_file_size); pre_file_size = cur_file_size; // 파일이 변경된 경우에만 파일 읽기 solution(pid); } }
  • 시그널을 주고, get_file_size 함수를 이용합니다.
  • get_file_size 함수를 이용해 텍스트가 제대로 업데이트되었는지 확인하고, 업데이트 되었다면 다시금 시그널을 전달해 텍스트를 업데이트 했는지 확인합니다. 텍스트가 작성되지 않았으면 업데이트 될 때까지 반복합니다. 이를 PID를 전체 순회하며 반복합니다.
 

6. 그렇다면 마피아를 찾을 solution 함수는 어떻게 구현해야 할까?

// 마피아를 찾는 함수 void solution(int pid) { FILE *confession_fp_read = fopen("confession.txt", "r"); // 오류처리 if (confession_fp_read == NULL) { perror("confession.txt 열기"); exit(EXIT_FAILURE); } char prevLine[BUFFER_SIZE] = ""; char line[BUFFER_SIZE]= ""; int debug_count = 0; // 파일을 계속 순회해서 현재 줄을 이전 줄에 넣음. 맨 끝 줄 바로 윗줄로 이동하게되어 prevLine이 ... 거나 !!!가 되게 됨 while (fgets(line, BUFFER_SIZE, confession_fp_read) != NULL) { strcpy(prevLine, line); debug_count++; } fclose(confession_fp_read); printf("현재 맨 끝 문자열 : %s, 지금 줄 번호 : %d\n", prevLine, debug_count); if (strstr(prevLine, "!!!") != NULL) { printf("마피아 프로세스 PID : %d\n\n", pid); count++; } }
  • 이제 마피아를 본격적으로 찾아야 합니다.
  • 문제 조건에서 마피아는 특정 시그널에 반응을 보이고, 이는 코드를 실행시켜 보면 알겠지만 텍스트 파일에 !!! 을 추가합니다. 일반 프로세스는 ... 을 추가합니다.
  • 그렇다면 PID에게 시그널을 줬을 때마다, 텍스트 파일의 맨 마지막 줄의 윗 줄 (맨 마지막 줄은 개행문자)에 !!! 이 포함되어 있는지 확인하면 되고, 위는 이를 위한 코드입니다.
 

7. 총 마피아의 수는? (결과는?)

1분반의 linuxtown_class1 파일에서는 총 17명 의 마피아가 탐색되었습니다.
 

 

번외 1. 파일 크기를 가져오는 함수는 어떻게 구현하나?

// 파일 크기를 가져오는 함수 off_t get_file_size(const char *fp) { struct stat file_buf; // 오류 처리 if (stat(fp, &file_buf) == -1) { perror("stat"); exit(EXIT_FAILURE); } return file_buf.st_size; }
  • Stack overflow 를 참고했습니다. 오류 처리도 추가했습니다.
 

번외 2. 왜 perrorexit(EXIT_FAILURE) 을 사용했나?

→ 더 성능이 좋다고 알려져 있어 사용했습니다. exit(EXIT_FAILURE) 을 사용하면 return 1 과 다르게, 종료함과 동시에 자원을 정리할 수 있습니다. 또한 perror 을 통해 사용자에게 명확하게 오류를 전달할 수 있습니다.
 

실행 과정과 결과

1. answer 실행파일 생성

 
 

2. 실행파일 실행 (linuxtown_class1도 같이 실행되고, 10초 후 부모 프로세스 재실행)

 

1-1. ver2 로 로직을 변경하고 터미널을 2개 사용해서 값이 같은지 확인할 수 있음 (물론 linuxtown_class1 이 재시작되면 PID도 달라짐)

notion image
 

성공한 코드 전체

ver1 : linuxtown_class1 을 내부에서 실행하는 버전

#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <unistd.h> #include <string.h> #include <sys/stat.h> #define BUFFER_SIZE 1024 off_t pre_file_size = 0; // 이전 파일 사이즈 미리 설정 pid_t pidList[200]; // 마피아 프로세스 담을 배열 설정 int cnt_all_pid = 0; // 총 프로세스 개수 합 (200개라 명시되어있지만 직접 세기) int count = 0; // 마피아 프로세스 총 개수, 배열의 인덱스와 같음 // 텍스트파일 초기화 함수 void init_text() { // 한번 초기화, 이전에 start를 실행했다면 텍스트 파일 비우기 FILE *confession_fp_write = fopen("confession.txt", "w"); // 오류 처리 if (confession_fp_write == NULL) { perror("confession.txt 열기"); exit(EXIT_FAILURE); } fclose(confession_fp_write); } // 파일 크기를 가져오는 함수 off_t get_file_size(const char *fp) { struct stat file_buf; // 오류 처리 if (stat(fp, &file_buf) == -1) { perror("stat"); exit(EXIT_FAILURE); } return file_buf.st_size; } // 마피아를 찾는 함수 void solution(int pid) { FILE *confession_fp_read = fopen("confession.txt", "r"); // 오류처리 if (confession_fp_read == NULL) { perror("confession.txt 열기"); exit(EXIT_FAILURE); } char prevLine[BUFFER_SIZE] = ""; char line[BUFFER_SIZE]= ""; // 파일을 계속 순회해서 현재 줄을 이전 줄에 넣음. 맨 끝 줄 바로 윗줄로 이동하게되어 prevLine이 ...이나 !!!가 되게 됨 while (fgets(line, BUFFER_SIZE, confession_fp_read) != NULL) { strcpy(prevLine, line); } fclose(confession_fp_read); // 마피아 함수 추가 if (strstr(prevLine, "!!!") != NULL) { pidList[count++] = pid; } } int main() { printf("== 마피아 프로세스 탐지 ===\n"); printf("=== 3초 후 linuxtown_class가 실행되고 10초 후에 마피아 프로세스를 찾습니다. ===\n"); fflush(stdout); // 위의 printf문을 바로 출력하기 위함 FILE *pid_fp; // 프로세스 PID를 가져오기 위한 파일 포인터 선언 char cmd[] = "linuxtown_class"; // 프로세스 CMD 이름 char pid_buffer[BUFFER_SIZE]; // linuxtown PID 임시 버퍼 int pid_linuxtown; usleep(3000 * 1000); // 3초 대기 if ((pid_linuxtown = fork()) == 0) { char *args[] = {"linuxtown_class1", NULL}; execv(args[0], args); perror("exec"); // exec가 실패하면 에러 메시지 출력 } else { // 자식 프로세스가 실행되기 위해 잠시 멈춤, 10초 usleep(10000 * 1000); // pgrep 명령어를 통해 linuxtown_class 명령어를 실행 중인 프로세스 PID를 가져옴 snprintf(pid_buffer, sizeof(pid_buffer), "pgrep -x %s", cmd); pid_fp = popen(pid_buffer, "r"); // 오류 처리 if (pid_fp == NULL) { // 오류 메세지 perror("popen"); // return 1보다 더 성능이 좋음 exit(EXIT_FAILURE); } // 시그널을 주기 전에 텍스트파일 초기화 init_text(); char pid_signal_buffer[BUFFER_SIZE]; // PID를 하나하나 순회하면서 시그널 주고, 마피아 찾기 while (fgets(pid_signal_buffer, BUFFER_SIZE, pid_fp) != NULL) { // pid를 숫자로 변환해서 kill 시그널 주기 pid_t pid = atoi(pid_signal_buffer); // 오류 처리 if (kill(pid, SIGUSR1) == -1) { perror("시그널 전달 실패"); } else { usleep(100); // 혹시모를 위험 방지? off_t cur_file_size; // 현재 파일 사이즈를 저장 do { cur_file_size = get_file_size("confession.txt"); usleep(100); // 파일 크기 변경 체크를 위한 여유시간 설정 } while (cur_file_size == pre_file_size); pre_file_size = cur_file_size; // 파일이 변경된 경우에만 파일 읽기 // 마피아 탐색 solution(pid); // 프로세스 개수 카운트 증가 cnt_all_pid++; } } // popen으로 열었던 파이프를 닫음 pclose(pid_fp); printf("총 마피아 : %d\n", count); printf("총 일반인 : %d\n", cnt_all_pid - count); printf("\n=== 마피아 리스트 ===\n\n"); for (int i = 0; i < count; ++i) { printf("%d\n", pidList[i]); } } // 자원 낭비 방지를 위해 프로세스 종료 system("pkill -x linuxtown_class"); printf("\nlinuxtown_class 프로세스 종료..\n"); return 0; }
 

ver2 : linuxtown_class1 을 외부에서 실행해야 하는 버전

#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <unistd.h> #include <string.h> #include <sys/stat.h> #define BUFFER_SIZE 1024 off_t pre_file_size = 0; // 이전 파일 사이즈 미리 설정 pid_t pidList[200]; // 마피아 프로세스 담을 배열 설정 int pidList_idx = 0; // 위의 배열에 담을 pid의 idx int count = 0; // 마피아 프로세스 총 개수 // 텍스트파일 초기화 함수 void init_text() { // 한번 초기화, 이전에 start를 실행했다면 텍스트 파일 비우기 FILE *confession_fp_write = fopen("confession.txt", "w"); // 오류 처리 if (confession_fp_write == NULL) { perror("confession.txt 열기"); exit(EXIT_FAILURE); } fclose(confession_fp_write); } // 파일 크기를 가져오는 함수 off_t get_file_size(const char *fp) { struct stat file_buf; // 오류 처리 if (stat(fp, &file_buf) == -1) { perror("stat"); exit(EXIT_FAILURE); } return file_buf.st_size; } // 마피아를 찾는 함수 void solution(int pid) { FILE *confession_fp_read = fopen("confession.txt", "r"); // 오류처리 if (confession_fp_read == NULL) { perror("confession.txt 열기"); exit(EXIT_FAILURE); } char prevLine[BUFFER_SIZE] = ""; char line[BUFFER_SIZE]= ""; // 파일을 계속 순회해서 현재 줄을 이전 줄에 넣음. 맨 끝 줄 바로 윗줄로 이동하게되어 prevLine이 ...이나 !!!가 되게 됨 while (fgets(line, BUFFER_SIZE, confession_fp_read) != NULL) { strcpy(prevLine, line); } fclose(confession_fp_read); if (strstr(prevLine, "!!!") != NULL) { pidList[pidList_idx++] = pid; count++; } } int main() { FILE *pid_fp; // 프로세스 PID를 가져오기 위한 파일 포인터 선언 char cmd[] = "linuxtown_class"; // 프로세스 CMD 이름 char pid_buffer[BUFFER_SIZE]; // PID 임시 버퍼 // pgrep 명령어를 통해 linuxtown_class 명령어를 실행 중인 프로세스 PID를 가져옴 snprintf(pid_buffer, sizeof(pid_buffer), "pgrep -x %s", cmd); pid_fp = popen(pid_buffer, "r"); // 오류 처리 if (pid_fp == NULL) { // 오류 메세지 perror("popen"); // return 1보다 더 성능이 좋음 exit(EXIT_FAILURE); } // 시그널을 주기 전에 텍스트파일 초기화 init_text(); char pid_signal_buffer[BUFFER_SIZE]; // PID 임시 버퍼 // PID를 하나하나 순회하면서 시그널 주고, 마피아 찾기 while (fgets(pid_signal_buffer, BUFFER_SIZE, pid_fp) != NULL) { // pid를 숫자로 변환해서 kill 시그널 주기 pid_t pid = atoi(pid_signal_buffer); // 오류 처리 if (kill(pid, SIGUSR1) == -1) { perror("시그널 전달 실패"); } else { usleep(100); // 혹시모를 위험 방지? off_t cur_file_size; // 현재 파일 사이즈를 저장 do { cur_file_size = get_file_size("confession.txt"); usleep(100); // 파일 크기 변경 체크를 위한 여유시간 설정 } while (cur_file_size == pre_file_size); pre_file_size = cur_file_size; // 파일이 변경된 경우에만 파일 읽기 solution(pid); } } // popen으로 열었던 파이프를 닫음 pclose(pid_fp); printf("총 마피아 : %d\n", count); printf("총 일반인 : %d\n", 200 - count); printf("\n=== 마피아 리스트 ===\n\n"); for (int i = 0; i < pidList_idx; ++i) { printf("%d\n", pidList[i]); } return 0; }
 

시행 착오

번외. 처음 실행할 때 오류?

가끔씩, 리눅스 서버를 처음 실행하고 ./linuxtown_class1 파일을 실행한 후, ver2 파일로 마피아를 찾으려고 하면 아주 가끔 18명이나 16명이 나옵니다.
로직이 잘못됐나 싶어 결과값인 메모장을 확인해봐도 시그널인 !!! 가 18개나 16개 존재하고, 마피아로 판정된 프로세스에게 모두 SIGUSR1 시그널을 수동으로 주어도 모두 !!! 을 작성해서 무엇이 문제를 일으키는지 모르겠습니다.
 

1. PID를 배열로 먼저 전부 저장한 후, 이를 텍스트 파일과 비교하려고 시도

출력된 PID에 직접 kill 명령어로 시그널을 주어도 문자열이 생성되지 않고 작동하지 않아 이상한 걸 알았지만, 왜 불가능한 지 잘 모르겠습니다. 해서 다른 로직으로 변경했습니다.
 
아래는 잘못된 코드입니다.
#include <stdio.h> #include <stdlib.h> #include <signal.h> #include <unistd.h> #include <string.h> #include <time.h> #define BUFFER_SIZE 1024 #define MAX_PIDS 200 // 텍스트파일 초기화 함수 void init_text() { // 한번 초기화, 이전에 start를 실행했다면 텍스트 파일 비우기 FILE *confession_fp_write = fopen("confession.txt", "w"); // 오류 처리 if (confession_fp_write == NULL) { perror("confession.txt 열기"); exit(EXIT_FAILURE); } fclose(confession_fp_write); } // 마피아를 찾는 함수 // pid 배열, 총 마피아 개수 인자로 받음 int solution(pid_t pids[], int count) { FILE *confession_fp_read = fopen("confession.txt", "r"); // 오류처리 if (confession_fp_read == NULL) { perror("confession.txt 열기"); exit(EXIT_FAILURE); } // 동기화를 위해 2초 쉬어줌 sleep(2); int idx = 0; char textLine[BUFFER_SIZE]; while (fgets(textLine, BUFFER_SIZE, confession_fp_read) != NULL) { // ... 이면 넘어가도록 if (strstr(textLine, "...") != NULL) { idx++; continue; } // !!! 이면 마피아 PID 출력 else if (strstr(textLine, "!!!") != NULL) { printf("마피아 PID: %d\n", pids[idx]); count++; } idx++; } fclose(confession_fp_read); return count; } int main() { FILE *pid_fp; // 프로세스 PID를 가져오기 위한 파일 포인터 선언 char cmd[] = "linuxtown_class"; // 프로세스 CMD 이름 char pid_buffer[BUFFER_SIZE]; // PID를 저장할 버퍼 pid_t pids[MAX_PIDS]; // PID 저장할 배열 int num_pids = 0; int count = 0; // pgrep 명령어를 통해 linuxtown_class 명령어를 실행 중인 프로세스 PID를 가져옴 snprintf(pid_buffer, sizeof(pid_buffer), "pgrep -x %s", cmd); pid_fp = popen(pid_buffer, "r"); // 오류 처리 if (pid_fp == NULL) { perror("popen"); exit(EXIT_FAILURE); } // 시그널을 주기 전에 텍스트파일 초기화 init_text(); // 결과를 읽어와서 각 PID를 배열에 저장 while (fgets(pid_buffer, BUFFER_SIZE, pid_fp) != NULL && num_pids < MAX_PIDS) { pid_t pid = atoi(pid_buffer); // 오류 처리 if (kill(pid, SIGUSR1) == -1) { perror("전달 실패"); } else { pids[num_pids++] = pid; } } // popen으로 열었던 파이프를 닫음 pclose(pid_fp); count = solution(pids, count); printf("총 마피아 : %d\n", count); return 0; }
 

2. fork를 사용해 linuxtown_class1 을 실행시킨 후 작성한 C언어 코드를 실행

linuxtown_class1 이후의 부모 프로세스가 실행되지 않아 실패했습니다.
 
아래는 잘못된 코드입니다.
if (pid == -1) { // fork 실패 perror("fork"); exit(EXIT_FAILURE); } else if (pid == 0) { // 자식 프로세스 char *args[] = { "./linuxtown_class1", NULL }; execv(args[0], args); // execv가 리턴했다면 오류가 발생한 것 perror("execv"); exit(EXIT_FAILURE); } else { // 부모 프로세스 // pgrep 명령어를 통해 linuxtown_class 명령어를 실행 중인 프로세스 PID를 가져옴 snprintf(buffer, sizeof(buffer), "pgrep -x %s", cmd); fp = popen(buffer, "r"); if (fp == NULL) { perror("popen"); exit(EXIT_FAILURE); } ...
 

3. 텍스트 파일 변경 여부를 확인하지 않고 진행

처음에 파일이 변경되었는지 확인하지 않고 진행한 결과, 총 마피아 프로세스의 합이 항상 다르게 나와 printf문으로 살펴본 결과, 텍스트가 바로바로 업데이트 되지 않았습니다.
 
아래는 잘못된 코드입니다.
if (kill(pid, SIGUSR1) == -1) { perror("kill"); } else { // confession.txt 파일을 열어 맨 윗줄부터 한 줄씩 매칭하고, !!!이 포함된 줄에서 해당 PID를 출력 usleep(100); FILE *confession_fp_read = fopen("confession.txt", "r"); if (confession_fp_read == NULL) { perror("confession.txt 열기"); exit(EXIT_FAILURE); } char lastLine[BUFFER_SIZE] = ""; // 이전 줄을 저장할 변수 char prevLine[BUFFER_SIZE] = ""; // 파일을 한 줄씩 읽으면서 이전 줄을 저장하고, 마지막 줄이 !!!를 포함하는지 확인 while (fgets(lastLine, sizeof(lastLine), confession_fp_read) != NULL) { strcpy(prevLine, lastLine); // 현재 줄을 이전 줄로 복사 } fclose(confession_fp_read); if (strstr(prevLine, "!!!") != NULL) { printf("마피아 PID: %d\n", pid); count++; } }
 
→ 해결을 위해 파일의 크기가 변경되어야지 다음 루프로 넘어가도록 수정했습니다.
 

4. 한 프로그램에서 전부 실행되도록 변경

시행착오 2번 을 다시 시도해서, execv 를 활용해 자식 프로세스를 linuxtown_class 로 변경하고 실행하도록 로직을 개선했습니다.
if ((pid_linuxtown = fork()) == 0) { char *args[] = {"linuxtown_class1", NULL}; execv(args[0], args); perror("exec"); // exec가 실패하면 에러 메시지 출력 } else { // 자식 프로세스가 실행되기 위해 잠시 멈춤, 10초 usleep(10000 * 1000); ...
 
 

소감


  • 실행 시간은 중요하지 않다 하셔서 구현에만 집중했더니 대략 13초 이상 걸립니다. 더 개선할 여지가 있는지 궁금합니다.
  • 자식 프로세스를 linuxtown_class로 변경했을 때 usleep 을 이용해 부모 프로세스의 실행을 기다리는 것보다 더 좋은 방법이 있는지 궁금합니다.
  • 또한 굳이 usleep 을 주어, 시그널을 줄 때마다 파일을 순회하는 것보다 더 좋은 로직이 있을까 궁금합니다.
 
 

참고문헌


  • 파일 크기 구하는 방법
 
 

댓글

guest