꾸준한 개발자

계속적인 성장을 추구하는 개발자입니다. 꾸준함을 추구합니다.

계속 쓰는 개발 노트

시스템 프로그래밍 18

메모리와 mmap

동적 메모리 생성 heap 영역에 생성 - malloc 함수 molloc 함수는 heap 영역에 동적으로 메모리를 생성하는 함수입니다. 프로세스 user space에서 heap 영역은 malloc 계열의 함수로 동적 메모리를 할당할 수 있습니다. free() 함수로는 해제할 수 있습니다. 파일 처리 성능 개선 기법 - 메모리에 파일 매핑 ex) void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) // [start+offset] ~ [start+offset+length]만큼의 물리 메모리 공간을 mapping할 것을 요청 // 보통 start: NULL 또는 0 사용, offset: mapping되기 원하는 물리..

스레드 관리

Pthread thread 표준 API입니다. POSIX 스레드 또는 Pthread(피-스레드)라고 부릅니다. 저수준 API로 100여개의 함수를 제공합니다. 복잡하긴 하지만, 유닉스 시스템 핵심 스레딩 라이브러리입니다. 다른 스레딩 솔루션도 결국 Pthread를 기반으로 구현되어 있기 때문에 익혀둘 가치가 있습니다. Pthread 라이브러리 헤더 파일에 정의되어 있습니다. 모든 함수는 pthread_로 시작합니다. 크게 두 가지 그룹으로 나뉘는데, 스레드 관리(생성, 종료, 조인, 디태치 함수 등), 동기화(뮤텍스 등 동기화 관련 함수)로 나뉘어집니다. 기본 라이브러리(glibc)와 분리된 libpthread 라이브러리에 pthread가 구현되어 있기 때문에 컴파일 시 명시적으로 -pthread 옵션이..

쉘 스크립트

쉘을 사용해서 프로그래밍을 할 수 있습니다. 서버 작업 자동화 및 운영을 위해 기본적으로는 익혀둘 필요가 있습니다. 쉘 명령어를 기본으로 하되, 몇가지 문법이 추가된 형태입니다. 기본문법 쉘 스크립트는 파일로 작성 후, 파일을 실행하는 형식입니다. 파일의 가장 위의 첫 라인은 '#!/bin/bash'로 시작합니다. 쉘 스크립트 파일은 실행 권한을 가지고 있어야 합니다. 일반적으로 '파일이름.sh'와 같은 형태로 파일 이름을 작성합니다. (bash 쉘에서 제공하는 echo 함수를 이용해서 화면에 'Hello bash!' 출력 예시) --> hello.sh 파일에 작성 #!/bin/bash echo 'Hello bash!' --> 실행이 안된다면 실행 권한을 확인해야 합니다. 변수 선언 방법은 띄어쓰기 없이..

시그널 (signal)

시그널은 IPC 기법 중 하나로 사용할 수 있습니다. 또한 커널 또는 프로세스에서 다른 프로세스에 어떤 이벤트가 발생되었는지를 알려주는 기법입니다. 예로 'ctrl + c'를 눌렀을 때 프로세스를 종료시키는 것이 시그널을 사용한 것입니다. 시그널 종류 SIGKILL 프로세스 죽임 SIGALARM 알람 발생 SIGSTP 프로세스 멈춤 SIGCONT 멈춘 프로세스 이어서 실행 SIGNT 프로세스에 인터럽트를 보내서 프로세스를 죽임 SIGSEGV 프로세스가 다른 메모리 영역 침범 시그널 동작 프로그램에서 특정 시그널의 기본 동작 대신 동작을 하도록 구현 가능합니다. 각 프로세스에서 시그널 처리에 대해 다음과 같은 동작 설정이 가능합니다. - 시그널 무시 - 시그널 블록 (블록을 푸는 순간, 해당 프로세스에서 ..

프로세스 관리 - 프로세스 종료

exit() 시스템 콜 exit() 시스템 콜은 인자로 status 정보를 넘겨줍니다. status란 프로세스 종료 상태 번호를 말합니다. 예로 0은 정상종료를 나타냅니다. 보통 비정상 종료를 할 때 exit() 시스템 콜을 사용합니다. 부모 프로세스는 status & 0377(비트 계산) 계산 값으로 자식 프로세스 종료 상태 확인이 가능합니다. return 0;과 exit(0)의 차이 exit() 함수는 즉시 프로세스를 종료합니다. 다음에 있는 코드는 실행되지 않습니다. 'return 0'은 단지 main()이라는 함수를 종료합니다. main()에서 return 시, C 언어 실행 파일에 기본으로 포함된 _start() 함수를 호출하게 됩니다. 해당 함수는 결국 exit() 함수를 호출합니다. exit..

프로세스 관리 - 프로세스 생성 속도 향상 (copy on write)

리눅스 프로세스는 각각의 프로세스마다 4GB 가상 메모리를 할당합니다. Kernel Space가 3GB~4GB로 잡히며, 이영역에 커널 이미지가 들어갑니다. 0GB~3GB는 User Space영역으로써 사용자 실행 이미지가 들어갑니다. text, data, heap, stack이 User Space 영역에 들어갑니다. 커널에 할당된 가상 메모리는 프로세스간 공유가 가능합니다. 위 아이디어를 갖고 copy on write에 대해서 알아보겠습니다. 각 프로세스마다 가상 메모리는 4GB입니다. fork() 시스템 콜을 호출하면 4GB를 복사하게 됩니다. 새로운 프로세스 공간을 생성한 후, 기존 프로세스 공간을 복사합니다. 결과적으로 프로세스 생성 시간이 오래걸립니다. 이를 줄이기 위한 방법으로 copy on ..

프로세스 관리 - 프로세스 생성

프로세스는 어떻게 생성할까요? 프로세스가 생성된다는 것은 text, data, bss, heap, stack 영역을 생성한다는 것입니다. 영역 별 공간을 만들고 프로세스 이미지를 해당 공간에 업로드하고, 실행을 시작하면서 생성이 됩니다. fork()와 exec() 시스템콜 fork() 시스템 콜은 새로운 프로세스 공간을 별도로 만들고, fork() 시스템콜을 호출한 프로세스(부모 프로세스) 공간을 모두 복사합니다. 별도의 프로세스 공간을 만들고, 부모 프로세스 공간의 데이터를 그대로 복사합니다. exec() 시스템 콜을 호출한 현재 프로세스 공간의 text, data, bss 영역을 새로운 프로세스의 이미지로 덮어씌웁니다. 별도의 프로세스 공간을 만들지 않습니다. fork() 시스템 콜 pid = for..

프로세스 관리 - 프로세스 ID

프로세스 ID는 pid로 각 프로세스는 해당 시점에 unique한 pid를 갖고 있습니다. pid 최댓값은 32768이며, 부호형 16비트 정수값을 사용합니다. 'sudo vi /proc/sys/kernel/pid_max'를 통해서 볼 수 있습니다. 리눅스의 경우 최근 할당된 pid가 200이라면, 그 이후에는 201, 202 등이 할당됩니다. 프로세스 계층 최초 프로세스는 운영체제가 생성합니다. 다른 프로세스는 또 다른 프로세스로부터 생성됩니다. 부모 프로세스와 자식 프로세스 관계를 갖습니다. ppid값이 부모 프로세스의 pid를 뜻합니다. 'ps -ef'를 통해서 ppid를 확인할 수 있습니다. 프로세스와 소유자(owner) 관리 리눅스 내부에서는 프로세스의 소유자와 그룹을 UID/GID로 관리합니다..

리눅스 운영체제 종류와 장점

Debian GNU : 데비안의 특징으로 패키지 설치 및 업그레이드가 단순합니다. 먼저 인스톨을 한 후 패키지 매니저인 APT 업데이트 방식을 이용하면 소프트웨어의 설치나 업데이트에서 다른 패키지와의 의존성 확인, 보안 관련 업데이트 등을 자동으로 설정 및 설치해줍니다. 안정성과 보안에 중점을 두어 다른 리눅스 배포판들의 기반으로 사용되고 있습니다. Ubuntu : 리눅스를 처음 접해도 설치가 간단하도록 배포를 합니다. 파티션을 설정하는 것만 신경쓰면 클릭 몇 번으로 설치가 가능합니다. Unity라는 독자적인 데스크톱 환경을 제공합니다. 별다른 설정이 필요없을 정도로 간결한 데스크탑 환경입니다. 국내에서도 많은 사용자가 있어 정보를 얻기 쉽습니다. 주로 개인용 데스크톱과 노트북에서 가장 인기있는 리눅스 ..

시스템콜, API, ABI, 표준

시스템 콜 구현 시스템콜은 eax 레지스터에 시스템 콜 번호를 넣고, ebx 레지스터에는 시스템 콜에 해당하는 인자값을 넣고, 소프트웨어 인터럽트 명령을 호출하면서 0x80값을 넘겨줍니다. CPU는 사용자 모드를 커널 모드로 바꿉니다. IDT(Interrupt Descriptor Table)에서 0x80에 해당하는 주소를 찾아서 실행합니다. system_call() 함수에서 eax로부터 시스템 콜 번호를 찾아서, 해당 번호에 맞는 시스템 콜 함수로 이동합니다. 해당 시스템 콜 함수를 실행 후, 다시 커널 모드에서 사용자 모드로 변경하고, 다시 해당 프로세스 다음 코드를 진행합니다. API 응용 프로그램과 분리된 하위 호환 인터페이스입니다. 사용자가 사용하기 쉽게 인터페이스를 제공해줍니다. 실행파일과 분리..