[Tasks] 운영체제 HW2
💼

[Tasks] 운영체제 HW2

카테고리
📒 Assignment
작성자
박용성박용성
작성일
2024년 06월 02일
태그
C
Slug
task-os-2
all: launch sumfact launch: launch.c gcc -o launch launch.c sumfact: sumfact.c gcc -o sumfact sumfact.c -lpthread clean: rm -f launch sumfact
/* 조건 1 : ./launch 4와 같이 2이상의 숫자 N을 인자로 받아야 함 조건 2 : fork()를 이용해 child process 만듦 조건 3 : 위에서 받은 인자로 N까지의 합을 출력, 종료 조건 4 : child는 execlp()를 활용해 sumfact 프로그램 실행, N을 넘김 */ #include <stdio.h> // 입출력 위해 추가 #include <stdlib.h> // atoi, exit 위해 추가 #include <sys/wait.h> // waitpid를 사용하기 위해 추가 #include <unistd.h> // execlp 위해 추가 int sum(int n) { // sum 함수 int res = 0; // 수의 합 공식 for (int i = 1; i <= n; ++i) { res += i; } return res; } int main(int argc, char *argv[]) { if (argc != 2) { // 입력받은 인수 검증 printf("인수가 적거나 너무 많습니다.\n"); exit(EXIT_FAILURE); // 종료 } int N = atoi(argv[1]); // 입력받은 문자열을 정수로 변환 if (N < 2) { // 조건 1 : ./launch 4와 같이 2이상의 숫자 N을 인자로 받아야 함 printf("N이 2 이상이어야 합니다.\n"); exit(EXIT_FAILURE); } pid_t pid = fork(); // 조건 2 : fork()를 이용해 child process 만듦 if (pid == -1) { // fork 실패 체크 perror("fork"); // fork: 오류 메세지 <- 이런 식으로 출력됨 exit(EXIT_FAILURE); // 종료 } if (pid > 0) { // 부모 프로세스일 시 int sumValue = sum(N); // 조건 3 : 위에서 받은 인자로 N까지의 합을 출력, 종료 int status; // 자식 프로세스 종료 상태 저장할 status 변수 printf("launch : sum = %d\n", sumValue); // 합 출력 waitpid(pid, &status, 0); // 자식 프로세스 종료 대기, 대기하지 않으면 출력이 다음 명령줄 위로 덮어씌워져서 보기 좋게 하도록 위해 추가 // wait(pid); // 자식 프로세스 종료 대기 } else { // 자식 프로세스일 시 printf("launch : start sumfact %d\n", N); // 자식 프로세스가 sumfact를 실행한다고 표시, 출력 execlp("./sumfact", "sumfact", argv[1], NULL); // 조건 4 : child는 execlp()를 활용해 sumfact 프로그램 실행, N을 넘김 perror("execlp"); // execlp: 오류 메세지 <- 이런식으로 출력됨, execlp가 활성화되면 아래 코드가 전부 교체되므로 실패했을 때만 실행됨 exit(EXIT_FAILURE); // 종료 } return 0; } /* 시행착오 #1 wait(pid) 사용하려고 했으나, launch.c:43:14: warning: passing argument 1 of ‘wait’ makes pointer from integer without a cast [-Wint-conversion] 43 | wait(pid); // 자식 프로세스 종료 대기 | ^~~ | | | pid_t {aka int} In file included from launch.c:10: /usr/include/x86_64-linux-gnu/sys/wait.h:77:27: note: expected ‘int *’ but argument is of type ‘pid_t’ {aka ‘int’} 77 | extern __pid_t wait (int *__stat_loc); | ~~~~~^~~~~~~~~~ 이런 경고가 떠서 찾아보니 waitpid를 사용하는 게 더 좋다 해서 바꾸었습니다. */
/* 조건 1 : 2 이상의 숫자를 명령행 인자로 받아야 함 조건 2 : pthread를 이용해 N개의 thread 생성해야 함 조건 3 : 맨 처음 생성되는 thread는 factorial 값을 구해서 출력 조건 4 : 나머지는 1부터 N까지의 합 출력 */ #include <pthread.h> // 스레드 헤더파일 추가 #include <stdint.h> // intptr_t 사용을 위해 추가 #include <stdio.h> // 입출력 위해 추가 #include <stdlib.h> // atoi, exit 위해 추가 int N; // 모든 스레드가 접근할 수 있도록 전역 변수 사용 long factorial(int n) { // 팩토리얼 계산 함수, 혹시 몰라 res에 long 사용 long res = 1; // 팩토리얼 공식 사용 for (int i = 1; i <= n; ++i) res *= i; return res; } int sum(int n) { // 합계 계산 함수 int res = 0; // 합계 계산 for (int i = 1; i <= n; ++i) res += i; return res; } // 동기화의 오류는 일어나지 않음. 왜냐하면 전역 변수 N을 읽기만 하고 쓰지는 않기 때문 // 그러므로 mutex는 사용하지 않았음. // Process 강의자료 참고함, 포인터를 받고 다시 캐스팅하여 건네줘야 함 void *run_thread(void *var) { // 스레드 생성 intptr_t index = (intptr_t)var; // 인덱스 전달받음, intptr_t형으로 캐스팅. 아래에 후술 if (index == 0) { // 조건 3: 만약 처음 스레드라면 factorial 출력 printf("sumfact : factorial = %ld\n", factorial(N)); } else { // 조건 4: 두번째부터 합 출력 printf("sumfact : sum = %d\n", sum(N)); } return NULL; // 널포인터 반환 } int main(int argc, char *argv[]) { if (argc != 2) { // 입력받은 인수 검증 printf("인수가 적거나 너무 많습니다.\n"); exit(EXIT_FAILURE); } N = atoi(argv[1]); // 전달받은 문자열을 정수로 변환 후 대입 // 조건 1: 이미 launch에서 2 이상인 것은 검증했으므로 하지 않아도 되지만 따로 실행할 수도 있으므로 조건 삽입 if (N < 2) { printf("N이 2 이상이어야 합니다.\n"); exit(EXIT_FAILURE); } pthread_t threads[N]; // 스레드 배열 생성 for (int i = 0; i < N; ++i) { // 조건 2 : N개의 스레드 생성 // 스레드 생성 pthread_create(&threads[i], NULL, run_thread, (void *)(long)i); } for (int i = 0; i < N; ++i) { pthread_join(threads[i], NULL); // 스레드가 모두 종료할때까지 대기 } return 0; } /* 39 line에서 sumfact.c: In function ‘run_thread’: sumfact.c:38:17: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] 38 | int index = (int)var; // 인덱스 전달받음, int형으로 캐스팅 컴파일 시 이러한 오류가 나서 구글링한 결과 intptr_t를 사용하면 좋다는 말을 듣고 변경 참고 : https://seoulforest.tistory.com/entry/%ED%8F%AC%EC%9D%B8%ED%84%B0-%EA%B4%80%EB%A0%A8-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%83%80%EC%9E%85-intptrt%EC%99%80-uintptrt */

댓글

guest