My Project
Loading...
Searching...
No Matches
kernel_engine.c
Go to the documentation of this file.
1/*
2 * Advanced Kernel Engine Implementation
3 *
4 * Maintainer: Azabell1993 Github master
5 * Created : 2024-09-04
6 *
7 * Purpose : Implements advanced kernel operations, including
8 * thread/process management, error handling, synchronization
9 * mechanisms, and data structures.
10 */
11
12#include "kernel_engine.h"
13#include "kernel_print.h"
14#include <stdlib.h>
15#include <stdio.h>
16#include <string.h>
17#include <errno.h>
18#include <unistd.h>
19#include <sys/wait.h>
20
21// 고급 오류 처리 함수 구현
22#include "ename.c.inc"
23
24#define BUF_SIZE 500
25
32void safe_kernel_printf(const char *format, ...) {
33 va_list args;
34 va_start(args, format);
35
36 pthread_mutex_lock(&print_mutex); // 출력 뮤텍스 잠금
37 vprintf(format, args); // 커널 printf 함수 호출
38 fflush(stdout);
39 pthread_mutex_unlock(&print_mutex); // 출력 뮤텍스 해제
40
41 va_end(args);
42}
43
50void create_threads(int num_threads, ...) {
51 pthread_t* threads = (pthread_t*)malloc(num_threads * sizeof(pthread_t));
52 va_list args;
53 va_start(args, num_threads);
54
55 for (int i = 0; i < num_threads; i++) {
56 void* (*thread_func)(void*) = va_arg(args, void* (*)(void*));
57 int err = pthread_create(&threads[i], NULL, thread_func, NULL);
58 if (err != 0) {
59 kernel_errExitEN(err, "스레드 %d 생성 실패", i);
60 }
61 }
62
63 for (int i = 0; i < num_threads; i++) {
64 pthread_join(threads[i], NULL);
65 }
66
67 va_end(args);
68 free(threads);
69}
70
76void create_single_process(void (*func)()) {
77 pid_t pid = fork();
78 if (pid < 0) {
79 kernel_errExit("프로세스 생성 실패");
80 } else if (pid == 0) {
81 func();
82 exit(EXIT_SUCCESS);
83 } else {
84 wait(NULL);
85 }
86}
87
94void create_multi_processes(int num_processes, ...) {
95 va_list args;
96 va_start(args, num_processes);
97
98 for (int i = 0; i < num_processes; i++) {
99 pid_t pid = fork();
100 if (pid < 0) {
101 kernel_errExit("프로세스 %d 생성 실패", i);
102 } else if (pid == 0) {
103 void (*process_func)() = va_arg(args, void (*)());
104 process_func();
105 exit(EXIT_SUCCESS);
106 }
107 }
108
109 for (int i = 0; i < num_processes; i++) {
110 wait(NULL);
111 }
112
113 va_end(args);
114}
115
122sem_t* init_semaphore(int value) {
123 sem_t* sem = (sem_t*)malloc(sizeof(sem_t));
124 if (sem == NULL) {
125 perror("세마포어 메모리 할당 실패");
126 exit(EXIT_FAILURE);
127 }
128
129#ifdef __APPLE__
130 // macOS에서 named semaphore 사용
131 char sem_name[20];
132 snprintf(sem_name, sizeof(sem_name), "/semaphore_%d", getpid());
133 sem_unlink(sem_name); // 기존 세마포어 삭제 (중복 방지)
134 sem = sem_open(sem_name, O_CREAT, 0644, value);
135 if (sem == SEM_FAILED) {
136 perror("세마포어 초기화 실패 (macOS)");
137 free(sem);
138 return NULL;
139 }
140#else
141 // Linux에서는 unnamed semaphore 사용
142 if (sem_init(sem, 0, value) != 0) {
143 perror("세마포어 초기화 실패 (Linux)");
144 free(sem);
145 return NULL;
146 }
147#endif
148
149 return sem;
150}
151
157pthread_mutex_t* init_mutex() {
158 pthread_mutex_t* mutex = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
159 if (pthread_mutex_init(mutex, NULL) != 0) {
160 kernel_errExit("뮤텍스 초기화 실패");
161 }
162 return mutex;
163}
164
171 LinkedList* list = (LinkedList*)malloc(sizeof(LinkedList));
172 list->head = list->tail = NULL;
173 list->size = 0;
174 return list;
175}
176
183void push(LinkedList* list, void* data) {
184 Node* new_node = (Node*)malloc(sizeof(Node));
185 new_node->data = data;
186 new_node->next = NULL;
187
188 if (is_empty(list)) {
189 list->head = list->tail = new_node;
190 } else {
191 list->tail->next = new_node;
192 list->tail = new_node;
193 }
194 list->size++;
195}
196
203void* pop(LinkedList* list) {
204 if (is_empty(list)) {
205 kernel_errMsg("빈 리스트에서 pop 시도");
206 return NULL;
207 }
208
209 Node* temp = list->head;
210 void* data = temp->data;
211 list->head = list->head->next;
212
213 if (list->head == NULL) {
214 list->tail = NULL;
215 }
216
217 free(temp);
218 list->size--;
219 return data;
220}
221
229bool is_empty(LinkedList* list) {
230 return list->size == 0;
231}
232
239 while (!is_empty(list)) {
240 pop(list);
241 }
242 free(list);
243}
244
250static void terminate(bool useExit3) {
251 char *s = getenv("EF_DUMPCORE");
252
253 if (s != NULL && *s != '\0')
254 abort();
255 else if (useExit3)
256 exit(EXIT_FAILURE);
257 else
258 _exit(EXIT_FAILURE);
259}
260
270static void outputError(bool useErr, int err, bool flushStdout, const char *format, va_list ap) {
271 char buf[BUF_SIZE], userMsg[BUF_SIZE], errText[BUF_SIZE];
272
273 vsnprintf(userMsg, BUF_SIZE, format, ap);
274
275 if (useErr)
276 snprintf(errText, BUF_SIZE, " [%s %s]",
277 (err > 0 && err <= MAX_ENAME) ? ename[err] : "?UNKNOWN?", strerror(err));
278 else
279 snprintf(errText, BUF_SIZE, ":");
280
281 snprintf(buf, BUF_SIZE, "ERROR%s %s\n", errText, userMsg);
282
283 if (flushStdout)
284 fflush(stdout);
285
286 fputs(buf, stderr);
287 fflush(stderr);
288}
289
296void kernel_errMsg(const char *format, ...) {
297 va_list argList;
298 int savedErrno = errno;
299
300 va_start(argList, format);
301 outputError(true, errno, true, format, argList);
302 va_end(argList);
303
304 errno = savedErrno;
305}
306
313void kernel_errExit(const char *format, ...) {
314 va_list argList;
315
316 va_start(argList, format);
317 outputError(true, errno, true, format, argList);
318 va_end(argList);
319
320 terminate(true); // 프로그램이 올바르게 종료되도록 보장
321}
322
330void kernel_errExitEN(int errnum, const char *format, ...) {
331 va_list argList;
332
333 va_start(argList, format);
334 outputError(true, errnum, true, format, argList);
335 va_end(argList);
336
337 terminate(true); // 프로그램이 올바르게 종료되도록 보장
338}
339
346void kernel_fatal(const char *format, ...) {
347 va_list argList;
348
349 va_start(argList, format);
350 outputError(false, 0, true, format, argList);
351 va_end(argList);
352
353 terminate(true); // 프로그램이 올바르게 종료되도록 보장
354}
355
362void kernel_usageErr(const char *format, ...) {
363 va_list argList;
364
365 fflush(stdout);
366
367 fprintf(stderr, "Usage: ");
368 va_start(argList, format);
369 vfprintf(stderr, format, argList);
370 va_end(argList);
371
372 fflush(stderr);
373 exit(EXIT_FAILURE);
374}
375
382void kernel_cmdLineErr(const char *format, ...) {
383 va_list argList;
384
385 fflush(stdout);
386
387 fprintf(stderr, "Command-line usage error: ");
388 va_start(argList, format);
389 vfprintf(stderr, format, argList);
390 va_end(argList);
391
392 fflush(stderr);
393 exit(EXIT_FAILURE);
394}
395
402void* semaphore_thread(void* arg) {
403 sem_t* semaphore = (sem_t*)arg;
404
405 safe_kernel_printf("세마포어 대기\n");
406 sem_wait(semaphore);
407 safe_kernel_printf("세마포어 획득\n");
408
409 sleep(1); // 작업을 모방하기 위한 대기 시간
410
411 sem_post(semaphore); // 세마포어 해제
412 if(sem_post(semaphore) == -1) {
413 kernel_errExit("세마포어 해제 실패");
414 } else {
415 safe_kernel_printf("세마포어 해제\n");
416 }
417
418 return NULL;
419}
420
427void* mutex_thread(void* arg) {
428 pthread_mutex_t* mutex = (pthread_mutex_t*)arg;
429
430 safe_kernel_printf("뮤텍스 대기\n");
431 pthread_mutex_lock(mutex); // 뮤텍스 잠금
432 safe_kernel_printf("뮤텍스 획득\n");
433
434 sleep(1); // 작업을 모방하기 위한 대기 시간
435
436 safe_kernel_printf("뮤텍스 해제\n");
437 if(pthread_mutex_unlock(mutex) != 0) {
438 kernel_errExit("뮤텍스 해제 실패");
439 } else {
440 safe_kernel_printf("뮤텍스 해제\n");
441 }
442
443 return NULL;
444}
445
453void run_multithreading(int num_threads, int use_semaphore, ...) {
454 if (num_threads < 1 || num_threads > 100) {
455 safe_kernel_printf("쓰레드 수는 1 이상 100 이하의 값이어야 합니다.\n");
456 return;
457 }
458
459 safe_kernel_printf("멀티스레드 실행 시작 (쓰레드 수: %d, 동기화 방법: %s)\n",
460 num_threads, use_semaphore ? "세마포어" : "뮤텍스");
461
462 pthread_t* threads = (pthread_t*)malloc(num_threads * sizeof(pthread_t));
463 int* thread_ids = (int*)malloc(num_threads * sizeof(int));
464 va_list args;
465
466 sem_t* semaphore = NULL;
467 pthread_mutex_t* mutex = NULL;
468
469 if (use_semaphore) {
470 semaphore = init_semaphore(1); // 세마포어 초기화
471 safe_kernel_printf("세마포어 초기화 완료\n");
472 kernel_printf("세마포어 초기화 완료\n");
473 } else {
474 mutex = init_mutex(); // 뮤텍스 초기화
475 safe_kernel_printf("뮤텍스 초기화 완료\n");
476 kernel_printf("뮤텍스 초기화 완료\n");
477 }
478
479 va_start(args, use_semaphore);
480 for (int i = 0; i < num_threads; i++) {
481 thread_ids[i] = i + 1;
482
483 if (use_semaphore) {
484 int err = pthread_create(&threads[i], NULL, semaphore_thread, semaphore);
485 if (err != 0) {
486 kernel_errExitEN(err, "스레드 %d 생성 실패", i);
487 }
488 } else {
489 int err = pthread_create(&threads[i], NULL, mutex_thread, mutex);
490 if (err != 0) {
491 kernel_errExitEN(err, "스레드 %d 생성 실패", i);
492 }
493 }
494 }
495 va_end(args);
496
497 for (int i = 0; i < num_threads; i++) {
498 pthread_join(threads[i], NULL);
499 }
500
501 // 세마포어 또는 뮤텍스 해제
502 if (use_semaphore) {
503#ifdef __APPLE__
504 sem_close(semaphore);
505 sem_unlink("/semaphore");
506 safe_kernel_printf("세마포어 해제 완료 (macOS)\n");
507#else
508 sem_destroy(semaphore);
509 free(semaphore);
510 safe_kernel_printf("세마포어 해제 완료 (Linux)\n");
511#endif
512 } else {
513 pthread_mutex_destroy(mutex);
514 free(mutex);
515 safe_kernel_printf("뮤텍스 해제 완료\n");
516 }
517
518 free(threads);
519 free(thread_ids);
520
521 safe_kernel_printf("멀티스레드 실행 종료\n");
522}
sem_t * init_semaphore(int value)
세마포어 초기화 함수
void run_multithreading(int num_threads, int use_semaphore,...)
멀티스레드 실행 함수 (쓰레드 수 및 동기화 방법을 입력받음)
void push(LinkedList *list, void *data)
연결 리스트에 요소 추가 함수
void kernel_errExit(const char *format,...)
커널 오류 종료 함수
bool is_empty(LinkedList *list)
연결 리스트가 비었는지 확인하는 함수
void * semaphore_thread(void *arg)
세마포어를 사용하는 스레드 작업 함수
void create_multi_processes(int num_processes,...)
다중 프로세스 생성 함수
void create_threads(int num_threads,...)
스레드 생성 함수
void * pop(LinkedList *list)
연결 리스트에서 요소 제거 함수
void kernel_fatal(const char *format,...)
커널 치명적 오류 함수
void create_single_process(void(*func)())
단일 프로세스 생성 함수
#define BUF_SIZE
void kernel_errExitEN(int errnum, const char *format,...)
커널 오류 종료 함수 (오류 번호 사용)
void kernel_errMsg(const char *format,...)
커널 오류 메시지 출력 함수
LinkedList * create_linkedlist()
연결 리스트 생성 함수
void safe_kernel_printf(const char *format,...)
스레드 안전한 출력 함수
void kernel_cmdLineErr(const char *format,...)
커맨드 라인 오류 처리 함수
void * mutex_thread(void *arg)
뮤텍스를 사용하는 스레드 작업 함수
void kernel_usageErr(const char *format,...)
커널 사용법 오류 함수
pthread_mutex_t * init_mutex()
뮤텍스 초기화 함수
void destroy_linkedlist(LinkedList *list)
연결 리스트 삭제 함수
kernel_printf("5-4 = %d\n", 1)
연결 리스트를 정의하는 구조체
연결 리스트의 노드를 정의하는 구조체
void * data
struct Node * next