댓글 (0)
0/2000

내부 명령어 (Built-in Commands)
쉘 프로그램 (/bin/bash, /bin/zsh, /bin/sh 등) 내부에 함수나 로직으로 이미 구현되어 있는 명령어다.
특징
예시
cd # 디렉터리 변경
export # 환경 변수 설정
alias # 별칭 설정
history # 명령어 이력 조회
set # 쉘 옵션 설정
source (.) # 스크립트 실행
exit # 쉘 종료
echo # 텍스트 출력 (bash 내장)
pwd # 현재 디렉터리 표시 (bash 내장)외부 명령어 (External Commands)
별도의 실행 파일 (바이너리 또는 스크립트) 로 디스크에 저장되어 있는 명령어다.
특징
/bin, /usr/bin, /usr/local/bin 등)예시
ls # 디렉터리 내용 표시 (/bin/ls)
cat # 파일 내용 출력 (/bin/cat)
grep # 텍스트 검색 (/bin/grep)
find # 파일 검색 (/usr/bin/find)
gcc # C 컴파일러 (/usr/bin/gcc)
python # Python 인터프리터 (/usr/bin/python)PATH 란?
PATH는 쉘이 외부 명령어(실행 파일)를 찾을 때 검색하는 디렉토리 목록을 담고 있는 환경 변수다.
# PATH 내용 확인
$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games콜론(:)으로 여러 디렉터리 경로를 구분하고, 왼쪽부터 오른쪽 순서로 검색한다.
PATH=/첫번째/디렉터리:/두번째/디렉터리:/세번째/디렉터리내부 명령어 실행 과정

코드 예시 (의사 코드)
// bash 내부 구조 (단순화)
int main() {
while (1) {
char *command = read_command();
if (strcmp(command, "cd") == 0) {
// 내부 명령어 - 직접 실행
builtin_cd(args); // 함수 호출
} else if (strcmp(command, "export") == 0) {
builtin_export(args);
} else {
// 외부 명령어 - fork/exec
execute_external(command);
}
}
}
void builtin_cd(char *path) {
if (chdir(path) != 0) {
perror("cd failed");
}
// PWD 환경 변수 업데이트
update_pwd();
}외부 명령어 실행 과정

코드 예시 (의사 코드)
void execute_external(char *command, char **args) {
// PATH에서 실행 파일 찾기
char *path = find_in_path(command); // "/bin/ls"
pid_t pid = fork(); // 프로세스 복제
if (pid == 0) {
// 자식 프로세스
execve(path, args, env); // 프로그램 실행
perror("exec failed");
exit(1);
} else {
// 부모 프로세스 (쉘)
int status;
waitpid(pid, &status, 0); // 자식 종료 대기
}
}쉘 상태 변경 필요성
일부 명령어는 반드시 현재 쉘 프로세스의 상태를 변경해야 한다.
cd (디렉터리 변경)
내부 명령어로 구현해야 하는 이유
# cd가 만약 외부 명령어라면?
$ pwd
/home/user
$ cd /tmp # 외부 프로세스에서 디렉터리 변경
$ pwd
/home/user # 변경되지 않음!왜 그럴까?
chdir() 를 호출해도 자식의 디렉터리만 변경내부 명령어로 구현하면
$ pwd
/home/user
$ cd /tmp # 쉘 프로세스 자체에서 디렉터리 변경
$ pwd
/tmp # 변경됨!export (환경 변수 설정)
내부 명령어로 구현해야 하는 이유
# export가 만약 외부 명령어라면?
$ echo $MY_VAR
(비어있음)
$ export MY_VAR=hello # 외부 프로세스에서 환경 변수 설정
$ echo $MY_VAR
(여전히 비어있음)왜 그럴까?
내부 명령어로 구현하면
$ echo $MY_VAR
(비어있음)
$ export MY_VAR=hello # 쉘 자체의 환경 변수 설정
$ echo $MY_VAR
hello # 설정됨!속도와 효율성
외부 명령어 실행 비용
1. fork() 시스템 콜: 프로세스 복제
2. PATH 검색: 디스크에서 파일 찾기
3. 파일 읽기: 디스크 I/O
4. 메모리 로드: 프로그램을 RAM에 적재
5. exec() 시스템 콜: 프로그램 실행
6. exit() 및 wait(): 종료 처리차이가 나는 이유
디스크 vs RAM 속도 차이
접근 속도 비교
RAM 접근 시간: ~100 나노초 (0.0001 밀리초)
SSD 접근 시간: ~0.1 밀리초
HDD 접근 시간: ~10 밀리초
RAM이 SSD보다 1,000배 빠름
RAM이 HDD보다 100,000배 빠름매번 디스크에서 읽는 경우의 문제
외부 명령어 실행 과정 (디스크 읽기 포함)
# 사용자가 ls를 100번 실행한다면?
$ ls # 1번: 디스크에서 /bin/ls 읽기 (10ms)
$ ls # 2번: 디스크에서 /bin/ls 읽기 (10ms)
$ ls # 3번: 디스크에서 /bin/ls 읽기 (10ms)
...
$ ls # 100번: 디스크에서 /bin/ls 읽기 (10ms)
# 총 1000ms (1초) 소요문제점
내부 명령어로 RAM 에 상주시키는 경우
쉘 시작 시 한 번만 로드
부팅/쉘 시작 시:
1. /bin/bash 실행 파일을 디스크에서 읽기
2. bash 코드를 RAM에 로드
3. 내부 명령어 함수들도 함께 RAM에 로드
이후 명령어 실행 시:
1. RAM에서 직접 함수 호출 (~0.0001ms)
2. 디스크 접근 불필요장점
# 사용자가 cd를 100번 실행한다면?
$ cd /home # 1번: RAM에서 직접 실행 (0.0001ms)
$ cd /tmp # 2번: RAM에서 직접 실행 (0.0001ms)
$ cd /var # 3번: RAM에서 직접 실행 (0.0001ms)
...
# 총 0.01ms (거의 즉시)RAM 사용의 트레이드오프
장점
단점
균형점
자주 사용하는 명령어 → 내부 명령어 (RAM 상주)
- cd, export, alias, echo, pwd 등
- 총 메모리 사용: 매우 작음 (수백 KB)
가끔 사용하는 명령어 → 외부 명령어 (디스크 저장)
- find, gcc, ffmpeg 등
- 필요할 때만 로드 → RAM 절약페이지 캐시를 통한 최적화
실제로 외부 명령어도 자주 사용하면 빨라진다.
OS 의 페이지 캐시
첫 실행:
$ ls # 디스크에서 읽기 (10ms)
# OS가 /bin/ls를 페이지 캐시에 저장
이후 실행:
$ ls # 페이지 캐시에서 읽기 (0.1ms)
$ ls # 페이지 캐시에서 읽기 (0.1ms)메커니즘
장점
아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!