시스템 콜
운영 체제 커널에 정의된 인터페이스로, 응용 프로그램에서 운영 체제의 기능을 시스템콜 핸들러의 도움을 받아 사용할 수 있게 해줍니다.
시스템 콜의 종류
Process Management
fork()
새로운 프로세스를 생성하는 데 사용됩니다. 부모 프로세스에서 fork()를 호출하면, 커널은 현재 실행 중인 부모 프로세스의 정확한 사본을 만들어 새로운 자식 프로세스를 생성합니다.
이때, 자식 프로세스는 부모 프로세스의 메모리, 파일 디스크립터, 환경 변수 등을 상속받습니다.
#include <unistd.h>
#include <stdio.h>
int main() {
pid_t pid = fork();
if (pid == 0) {
// 자식 프로세스 코드
printf("자식 프로세스\n");
} else if (pid > 0) {
// 부모 프로세스 코드
printf("부모 프로세스\n");
} else {
// fork() 호출에 실패한 경우
perror("fork failed");
return 1;
}
return 0;
}
waitpid()
부모 프로세스가 자식 프로세스의 종료를 기다리는 데 사용됩니다. 부모 프로세스는 waitpid() 함수를 호출하여 특정 자식 프로세스의 종료를 기다리거나, 모든 자식 프로세스의 종료를 기다릴 수 있습니다.
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
int main() {
pid_t pid;
int status;
// 자식 프로세스 생성
pid = fork();
if (pid < 0) {
// fork 실패
perror("fork failed");
return 1;
} else if (pid == 0) {
// 자식 프로세스
printf("자식 프로세스가 시작됨\n");
sleep(2); // 예시를 위해 2초간 대기
printf("자식 프로세스가 종료됨\n");
return 42; // 종료 코드 42 반환
} else {
// 부모 프로세스
printf("부모 프로세스가 시작됨\n");
// 자식 프로세스의 종료를 대기
waitpid(pid, &status, 0);
if (WIFEXITED(status)) {
printf("자식 프로세스가 정상적으로 종료됨, 종료 코드: %d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("자식 프로세스가 시그널에 의해 종료됨, 시그널 번호: %d\n", WTERMSIG(status));
}
printf("부모 프로세스가 종료됨\n");
}
return 0;
}
execve()
새로운 프로세스 이미지를 현재 실행 중인 프로세스에 로드하여 그 프로세스 이미지의 실행하는 시스템 콜입니다.
#include<stdio.h>
int main(){
printf("hello world\n");
return 0;
}
위에 코드를 컴파일하여 printHello 이름을 가진 프로세스 이미지를 생성해줍니다.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
// 새로운 프로세스 이미지의 경로
char *path = "/home/qwer1234/printHello";
// 새로운 프로세스 이미지의 인수들
char *args[] = { "printHello", NULL };
// 환경 변수
char *envp[] = { NULL };
// 새로운 프로세스 이미지를 실행
// 첫 번째 인자: 프로세스 이미지의 경로
// 두 번째 인자: 프로세스 이미지의 인수 배열
// 세 번째 인자: 환경 변수 배열
execve(path, args, envp);
// 만약 execve 함수가 정상적으로 실행되지 않으면 아래 코드가 실행될 것임
perror("execve"); // 에러 메시지 출력
return EXIT_FAILURE; // 실패 반환
}
exit()
프로세스가 종료되는 시점에서 호출되는 함수
프로세스의 자원을 동시에 해제 시킵니다.
정상적으로 프로세스가 종료 되었다면, 0을 인자로 전달합니다.
그렇지 않다면 0이 아닌 다른 값(종료 코드)을 인자로 전달합니다.
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("프로그램이 시작되었습니다.\n");
// 예상치 못한 오류 발생 시 비정상 종료
int *ptr = NULL;
if (ptr == NULL) {
fprintf(stderr, "오류: 포인터가 NULL입니다.\n");
exit(1); // 비정상 종료, 종료 코드 1 반환
}
// 프로그램이 여기까지 도달하지 못함
printf("프로그램이 종료되었습니다.\n");
return 0;
}
kill()
프로세스에 시그널을 보내는 데 사용됩니다.
다른 프로세스에게 특정 동작을 유도하거나 프로세스를 종료하는 데 사용됩니다.
#include <signal.h>
int kill(pid_t pid, int sig);
kill() 함수의 프로토타입니다.
pid_t 파라미터에 프로세스 아이디를 전달하고, sig 파라미터에 시그널의 종류를 전달합니다.
시그널의 종료로는 SIGKILL, SIGTERM, SIGINT등이 있습니다.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
int main() {
pid_t pid;
// 자식 프로세스 생성
pid = fork();
if (pid < 0) {
// fork 실패
perror("fork failed");
return EXIT_FAILURE;
} else if (pid == 0) {
// 자식 프로세스
printf("자식 프로세스가 시작됨\n");
// 자식 프로세스를 다른 프로그램으로 대체
char *args[] = {"ls", "-l", NULL};
execvp(args[0], args);
// execvp 함수가 성공적으로 실행되면 이후 코드는 실행되지 않음
perror("execvp failed");
printf("자식 프로세스를 종료시킵니다.\n");
return EXIT_FAILURE;
} else {
// 부모 프로세스
printf("부모 프로세스가 시작됨\n");
// 자식 프로세스를 종료
kill(pid, SIGKILL);
// 자식 프로세스의 종료를 대기
waitpid(pid, NULL, 0);
printf("부모 프로세스가 종료됨\n");
}
return 0;
}
'Linux' 카테고리의 다른 글
Linux) rootfs란? (0) | 2024.04.25 |
---|---|
Linux) Makefile란? (0) | 2024.04.25 |
Linux) Shell script (0) | 2024.04.22 |
Linux) 리눅스 개발 환경 이해하기(1) (0) | 2024.04.22 |
Linux) 환경 변수란? (0) | 2024.04.11 |