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
*/
댓글