1. 시스템 프로그래밍
시스템 프로그래밍이란 일반적인 응용 프로그래밍(application programming)과 달리 시스템에서 제공하는 시스템 호출(시스템 함수, system call)을 사용해 프로그램을 작성하는 것을 말한다.
리눅스 시스템은 파일 시스템 접근, 사용자 정보, 시스템 시간 정보, 네트워킹 등 다양한 기능을 제공한다.
이러한 서비스를 이용해 프로그램을 구현할 수 있도록 제공되는 프로그래밍 인터페이스를 시스템 호출 이라고 한다.
즉, 시스템 호출을 사용하면 리눅스 시스템 서비스를 직접 사용하는 프로그램을 작성할 수 있다.
시스템 프로그래밍은 OS와 직접 상호작용하는 프로그램을 개발한다.
일반적인 응용 프로그램(e.g. 웹 브라우저, 워드 프로세서)와는 달리, 시스템 프로그래밍에서는 운영체제의 기능을 직접 사용해야 한다.
운영체제의 기능을 활용하기 위해 제공되는 것이 시스템 호출 이다.
1-1) 시스템 호출
시스템 호출은 프로그래밍 인터페이스 이며, 기본 형식은 C언어의 함수와 같다.
시스템 호출은 운영체제에서 제공하는 기능을 사용할 수 있도록 제공되는 프로그래밍 인터페이스이고, 이 인터페이스를 사용하면 파일 시스템, 프로세스 관리, 메모리 관리, 네트워크 등 운영체제의 기능을 직접 활용할 수 있다.
리턴값=시스템호출명(인자,...);
시스템 호출명은 함수명 처럼 사용할 이름이 정의되어 있다.
시스템 호출의 종류에 따라 인자는 있을 수도 있고 없을 수도 있다.
시스템 호출은 결괏값을 리턴하는 경우도 있지만 대부분은 시스템 호출의 성공이나 실패를 알리는 정숫값을 리턴한다.
(성공하면 일반적으로 0 이상의 값을 반환하고 실패하면 -1을 반환하며 errno를 통해 오류 원인을 확인할 수 있음.
운영체제의 커널이 직접 실행한다.)
✅ 자주 쓰이는 시스템 호출 예제
#include <unistd.h> // write(), read(), fork() 등을 포함
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
int main() {
int fd = open("test.txt", O_WRONLY | O_CREAT, 0644); // open()-> 파일 열기, 없으면 생성
if (fd == -1) {
perror("파일 열기 실패");
return 1;
}
write(fd, "Hello, System Call!\n", 20); //파일에 데이터 쓰기
close(fd); //파일 닫기
return 0;
}
1-2) 라이브러리 함수
라이브러리는 미리 컴파일된 함수를 묶어서 제공하는 특수한 형태의 파일이다.
C언어는 데이터 입출력, 수학 공식, 문자열 처리 등 응용 프로그램 개발에 필요한 함수를 유형별로 분류해 라이브러리로 제공한다.
라이브러리 함수는 라이브러리에 포함된 함수를 의미한다. 함수를 묶어서 라이브러리로 만드는 이유는 자주 사용하는 기능을 독립적으로 구현해 둠으로써 프로그램 개발과 디버깅을 쉽게 하고 컴파일을 좀 더 빠르게 할 수 있기 때문이다.
리눅스 시스템에서 라이브러리는 보통 /usr/lib에 위치한다.
대부분 리눅스 시스템에서 /lib는 /usr/lib에 대한 심벌릭 링크이다.
라이브러리 이름은 일반적으로 'lib'로 시작하고, 확장자는 .a나 .so이다.
lib*.a는 정적 라이브러리 이고, lib*.so는 공유 라이브러리 이다.
정적 라이브러리는 프로그램을 컴파일 할 때 같이 적재되어 실행 파일을 구성한다.
실행 파일에 라이브러리 코드가 포함 되므로 그만큼 크기가 커진다.
반면에 공유 라이브러리는 실행 파일에 포함되지 않는다. 공유 라이브러리를 이용해 생성한 실행 파일은 실행 시에 해당 라이브러리가 메모리에 적재된다. 이렇게 적재된 라이브러리는 다른 실행 파일에서도 공유할 수 있다.
최근에는 메모리를 효율적으로 사용하기 위해 공유 라이브러리를 많이 사용한다.
✅ 라이브러리 함수 예제
#include <stdio.h>
int main(){
FILE *fp=fopen("test.txt", "w");
if(fp==NULL){
perror("파일 열기 실패");
return 1;
}
fprintf(fp, "Hello, Libraray function!\n");
fclose(fp);
return 0;
}
- fopen()은 내부적으로 open() 시스템 호출을 사용한다.
- 하지만 fopen()은 버퍼링 기능을 제공해 성능이 더 좋을 수 있다.
✅ 라이브러리 함수 vs 시스템 호출 차이점
o.s의 시스템 호출을 직접 사용하는 것은 불편할 수도 있다.
그래서 printf(), scanf(), fopen()과 같은 라이브러리 함수가 제공되는데
이들은 시스템 호출을 감싸는 wrapper 역할을 하며 프로그래밍을 쉽게 만들어준다.
비교 항목 | 시스템 호출 | 라이브러리 함수 |
실행 위치 | 운영체제 커널 모드 | 사용자 모드 |
직접 실행 여부 | 운영 체제가 직접 실행 | 시스템 호출을 감싸는 래퍼(wrapper) |
예시 | open(), write(), read(), fork() | fopen(), printf(), malloc() |
2. 시스템 도구
시스템 프로그래밍을 할 때 유용하게 사용할 수 있는 기본 도구를 살펴본다.
시스템에서 프로그래밍을 할 때 반드시 알아야 할 기본 명령은 시스템 접속, 파일, 디렉토리에 대한 것이다.
📌 로그인/로그아웃 명령
명령 | 기능 | 주요 옵션 | 예제 |
telnet | 리눅스 시스템에 접속 (telnet: 원격 서버에 접속 ssh: ssh로 원격 접속) |
telent ***.co.kr | |
ssh | ssh ***.co.kr | ||
exit | 리눅스 시스템에 접속 해제 | exit | |
logout | logout |
📌 파일/디렉토리 명령
명령 | 기능 | 주요 옵션 | 예제 |
pwd | 현재 디렉토리 경로 출력 | pwd | |
ls | 디렉토리 내용 출력 | -a: 숨김 파일 출력 -l: 파일 상세 정보 출력 |
ls -a/tmp ls -l |
cd | 디렉토리 이동 | cd /tmp cd ~han01 |
|
cp | 파일 복사 디렉토리 복사 |
-r: 디렉토리 복사 | cp a.txt b.txt cp -r dir1 dir2 |
mv | 파일명/디렉토리명 변경 | mv a.txt b.txt mv dir1 dir2 |
|
파일/디렉토리 이동 | mv a.txt dir1 | ||
rm | 파일 삭제 | rm a.txt | |
디렉토리 삭제 | -r: 디렉토리 삭제 | rm -r dir1 | |
mkdir | 디렉토리 생성 | mkdir dir1 | |
rmdir | 빈 디렉토리 삭제 | rmdir dir1 | |
cat | 파일 내용 출력 | cat a.txt | |
more | 화면 크기 단위로 파일 내용 출력 | more a.txt | |
chmod | 파일/디렉토리 접근 권한 변경 | chmod 755 a.exe chmod go+x a.exe |
|
grep | 패턴 검색 | grep abcd a.txt |
📌 프로세스 명령
명령 | 기능 | 주요 옵션 | 예제 |
ps | 현재 실행 중인 프로세스 정보 출력 | -ef: 모든 프로세스의 상세 정보 출력 | ps ps -ef ps -ef | grep ftp |
kill | 프로세스 강제 종료 | -9: 강제 종료 | kill 5000 kill -9 5001 |
✅ 실행 중인 특정 프로그램 종료
ps -ef | grep firefox # 실행중인 프로세스 찾기
kill -9 <PID> # 해당 PID 종료
📌 기타 명령
명령 | 기능 | 주요 옵션 | 예제 |
su | 사용자 계정 변경 | - : 변경할 사용자의 환경 초기화 파일 실행 | su su - su -han02 |
tar | 파일/디렉토리 묶기 | cvf: tar 파일 생성 tvf: tar 파일 내용 보기 xvf: tar 파일 풀기 |
tar cvf a.tar * tar tvf a.tar tar xvf a.tar |
whereis which |
파일 위치 검색 | whereis ls which telnet |
3. 리눅스에서 파일 생성하고 수정해보기
1) 파일 생성 및 수정
echo "Hello, Linux"! > hello.txt # 파일 내용 생성 및 내용 입력
cat hello.txt # 파일 내용 확인
2) 프로세스 확인 및 종료
ps -ef | grep bash # 실행중인 bash 프로세스 찾기
kill -9 <PID> # 프로세스 종료
3) 디렉토리 압축 및 해제
tar cvf myfiles.tar mydir/ # mydir 폴더 압축
tar xvf myfiles.tar # 압축 해제