Makefile은 리눅스 플랫폼에서 제공하는 빌드 자동화 유틸리티입니다. make 유틸리티는 프로그래밍언어처럼 그 안에서 사용되는 작은 규모의 문법이 있습니다. 변수를 정의할 수 있고, 몇 가지 유용한 함수도 제공합니다. CC = g++ CFLAGS = -lpcap TARGET = arp_spoof RM = rm -f SOURCE_DIR = src INCLUDE_DIR = include BINARY_DIR = bin default: (patsubst %.cpp, %.o, (SOURCE_DIR)/*.cpp)) HEADERS = (INCLUDE_DIR)/*.h) (OBJECTS) @m..
간단한 텍스트 파일은 단지 라인으로 구성되어 있습니다. 클라이언트가 서버에게 데이터를 요청하면 서버로부터 데이터를 받는 상황을 생각해봅시다. 서버에서 클라이언트로 데이터를 건네줘야하는데 이때 단지 라인으로 구성되어 있는 텍스트파일을 떡 하고 줘버리면 클라이언트 입장에서 이게 무슨 데이터인지 참 난감한 상황에 빠질겁니다. 클라이언트에서 알아보기 쉽도록 텍스트를 '구조화'할 필요가 있습니다. 대표적인 '구조화' 형식은 다음과 같습니다. CSV XML JSON YAML CSV 파일 다루기 .csv 파일은 스프레드시트-데이터베이스 간의 데이터 교환 형식입니다. 개인이 CSV Parser를 만들 수도 있겠지만, 그것보단 표준 csv 모듈을 사용해서 파싱하는게 더 좋은 판단입니다. import csv data = ..
파이썬의 '파일 입출력'은 표준 C 입출력 라이브러리를 모델로 만들어졌습니다. 먼저 파일을 오픈하는 인터페이스입니다. fileobj = open(filename, mode) 2번째 인자인 'mode'에 올 수 있는 값은 다음과 같습니다. r: 파일 읽기 w: 파일 쓰기(파일이 존재하지 않으면 생성, 존재하면 덮어씀) x: 파일 쓰기(파일이 존재하지 않을 경우에만 수행함) a: 파일 추가하기(파일이 존재하면 파일의 끝에서부터 쓴다.) 쓰기 파일 쓰기를 위한 인터페이스는 다음과 같습니다. fout = open('myfile', 'wt') fout.write(data) 읽기 파일 읽기를 위한 인터페이스는 다음과 같습니다. fin = open('myfile', 'rt') obj = fin.read() # 매개변..
생성자 파이썬의 생성자는 단지 멤버 초기화의 목적으로 쓰입니다. 그렇기에 생성자명은 __init__으로 고정되어있습니다. class Person(): def __init__(self): pass 클래스에서 __init__() 메서드의 첫 번째 파라미터는 무조건 self여야 합니다. 'self'는 C++, Java에서의 'this'와 같습니다. 상속 위의 예제에서 '어라?'하는 부분이 있으신가요? 클래스명 뒤에 () 괄호가 있는데요, 이는 상속을 위한 파이썬의 문법입니다. class Person(): def __init__(self, name): self.name = name class Professor(Person): def __init__(self, name): self.name = "Professor..
파이썬은 함수 안에 새로운 함수를 정의할 수 있습니다. 이를 내부 함수라 합니다. def outer(a, b): def inner(c, d): return c + d return inner(a, b) 이때, 내부 함수로 인해서 생기는 중요한 이슈가 있습니다. '내부 함수'는 자신의 스코프를 벗어나서 '외부 함수'의 변수에 접근할 수 있다. '내부 함수'는 '외부 함수'의 반환 값으로 사용될 수 있다. 위의 이슈를 담고 있는 예제를 살펴보겠습니다. def print_msg(msg): def inner(): print(msg); return inner print_msg() 함수가 종료되면 매개변수로 넘어온 msg는 사라져야되는데 '내부 함수'에서 해당 변수를 참조하고 있습니다. 거기다 print_msg() ..
Comprehension이란? 컴프리헨션(Comprehension)은 원하는 데이터를 파이썬에서 제공하는 자료구조(list, dictionary, set)에 담아 표현하려할 때 사용할 수 있는 문법으로 종류는 4가지입니다. list 컴프리헨션 dictionary 컴프리헨션 set 컴프리헨션 generator 컴프리헨션 list 컴프리헨션 [1, 6) 순차열이 담긴 list 컨테이너를 생성하기 위해선 어떻게 해야 할까요? >>> number_list = [] >>> number_list.append(1) >>> number_list.append(2) >>> number_list.append(3) >>> number_list.append(4) >>> number_list.append(5) >>> number..
프로세스 관리 프로세스는 유닉스 시스템에서 파일 다음으로 중요한 개념입니다. 알다시피 프로세스는 활성화되어 실행 중인 살아있는 코드 객체입니다. 유닉스는 새로운 바이너리 이미지를 메모리에 적재하는 과정에서 프로세스를 생성하는 부분을 분리했습니다. 예를 들어 Windows는 새로운 프로세스를 생성하기 위해 CreateProcess() 함수 1개를 호출하면되지만, 유닉스는 fork(), exec 류의 시스템콜 2가지를 사용해야 합니다. 프로세스 계층 새로운 프로세스를 생성하는 프로세스를 '부모 프로세스'라 하고, 새롭게 생성된 프로세스를 '자식 프로세스'라고 합니다. 리눅스에선 'init 프로세스'를 제외한 모든 프로세스는 부모 프로세스가 있습니다. 자신의 pid 값과 부모의 pid 값을 알고 싶다면 아래의..
메모리 맵 파일 프로그래밍은 데이터를 입력받아 처리하고 출력하는 작업이고, 이 데이터는 파일로써 디스크에 존재합니다. 내가 만약 '회원명단.csv'란 엑셀 파일을 가지고 여러 데이터 처리 작업을 해야한다고 가정해봅시다. 그렇다면 해당 파일에서 '읽기', '쓰기'를 할 때마다 디스크까지 접근해야할텐데 이러면 속도가 너무 느리지 않을까요? 만약 그 파일이 디스크가 아닌 메모리에 있다면 접근 속도는 엄청나게 향상되지않을까요? 이러한 발상은 최소한의 디스크 접근을 위한 버퍼 입출력에서 한 단계 더 나아간 발상입니다. '버퍼'란 개념이 아닌 디스크-메모리간의 '페이지(page)' 개념을 활용한 방식으로, 프로세스의 가상 메모리 주소 공간에 파일을 매핑한 뒤 가상 메모리 주소에 직접 접근하는 것으로 파일 읽기/쓰기..
대부분의 프로그래밍 과정은 데이터를 잘게 나누고, 이들을 붙여서 특정한 형태로 만듭니다. 그렇기 때문에 데이터를 어떤 형태로 담아서 처리할지, 즉 어떤 자료구조를 사용해 데이터를 처리할지는 중요한 문제입니다. 그렇기에 대부분의 프로그래밍 언어는 많이 사용되는 자료구조를 기본적으로 지원해 줍니다. 예를 들어, C++는 STL을 통해 컨테이너 형태로 vector, deque, list, map, set 자료구조를 지원합니다. C++에서는 STL을 배워야 사용할 수 있던걸 파이썬에서는 허무할 정도로 쉽게 사용이 가능합니다. 혹시 Java에서 모든 변수는 포인터 변수 혹은 참조자라는걸 알고 계신가요? Java에서 모든 것은 객체로 표현되고 변수는 해당 객체를 참조합니다. 파이썬도 마찬가지입니다. 지금부터 살펴볼..
버퍼 입출력 - 표준 입출력 라이브러리 파일 시스템의 최소 저장 단위는 '블록'이라는 추상 개념입니다. 따라서, 모든 입출력 연산은 블록 크기의 정수배에 맞춰서 일어납니다. 단지 1Byte를 읽고싶다하더라도, 512Byte만큼(1블록 = 512Byte라 가정) 읽어와야한다는 얘기입니다. 또는 내가 단지 2.5블록만큼(대략 1250Byte) '쓰기' 연산을 하고싶다하더라도 3블록에 대해 '쓰기' 연산을 해야한다는 얘기입니다. 그런데 잘 생각해보면 사용자 애플리케이션에서는 512Byte 단위로 입출력 연산이 이루어지지 않는 경우가 대부분입니다. 보통 CSV 파일을 다루기 위해 '필드' 단위의 입출력 연산이 필요하다거나, JSON 파일을 다루기 위해 단순히 '문자열' 단위의 입출력 연산이 필요한 경우가 대부분..
가상 파일 시스템 프로그래밍을 하다보면 빠지지 않는 것이 파일 처리인데요, 혹시 파일 작업을 하기 위해 read(), write()와 같은 시스템콜을 사용하면서 "왜 매개변수로 어떤 파일 시스템인지 넘겨주지않지?"라고 생각해보신적 있으신가요? 사실 조금만 생각해보면 답이 금방나오는 질문입니다. 이유는 파일 시스템이 추상화되어있기 때문입니다. 구조를 표현하면 다음 그림과 같습니다. 파일 시스템간의 공통된 인터페이스를 둠으로써 얻는 장점은 여러 가지가 있습니다. 1. 동일한 방법으로 접근이 가능하다. 2. 파일 시스템간의 이식성이 좋아진다. 3. 새로운 파일 시스템이 추가되더라도 설계를 변경할 필요가 없다.