출처 : http://damduc.tistory.com/308



리눅스 커널에서 사용하는 모듈은 어떤 기능을 구현하는 커널 부분을 의미하며 ELF 형식의 객체 파일을 의미한다.

리눅스 커널에서는 모듈을 다루기 위해 내부적으로 struct module 형식의 구조체를 선언하고, 리스트 형태로 모듈을 관리한다. 이 구주체는 include/linux/module.h에 선언되어 있다.

모듈 적재 과정
커널에 모듈을 적재하려면 insmod 명령을 실행해야 한다. 이 insmod는 다음과 같은 과정을 실행한다. 

1. 주어진 모듈명이 ".o" 나 ".ko"가 포함되면 파일명에서 모듈명을 얻는다. 그렇지 않다면 모듈명으로 간주하고, /lib/module/의 하부 디렉토리에서 해당 모듈에 해당하는 파일명을 찾아 파일을 읽는다.

2. 읽어온 파일의 코드와 모듈명 그리고 module 구조체를 저장하는데 필요한 메모리 영역의 크기를 구한다.

3. 이 정보를 이용해 create_module() 함수를 호출한다. 이 함수는 모듈을 처리할 수 있는 권한이 있는지 검사하고, find_module() 함수를 이용해 이미 적재된 모듈인가를 검사한다. 만약 커널에 적재되지 않았다면 vmalloc() 함수를 호출해 새로운 모듈을 위한 메모리 영역을 할당한다. 할당받은 메모리 영역 중 module 구조체의 내용을 초기하고 모듈명을 그뒤에 복사한다. 이후 모듈을 관리하는 커널 모듈 리스트에 적재한다. 마지막으로 모듈에 할당된 메모리의 시작 주소를 돌려준다.

4.  query_module() 함수를 이용해 커널 심볼 테이블과 커널에 적재된 다른 모듈의 심볼 테이블을 구한다. 이때 query_module() 함수에 QM_MODULES, QM_INFO, QM_SYMBOL 값을 지정하여 필요한 정보를 가져오는데, QM_MODULES는 커널에 포함된 모듈명을 얻어올 때 사용하며, QM_INFO는 각 모듈의 시작 주소와 크기를 얻기 위해 사용한다. 앞에서 구한 모듈 정보를 통해 QM_SYMBOL로 실질적인 커널 심볼 테이블과 커널에 적재된 다른 모듈의 심볼 테이블을 구한다.

5.  커널 심볼 테이블, 모듈 심볼 테이블 그리고 커널에 적재하려는 현재 모듈의 메모리 시작 번지를 이용해 읽어온 모듈의 프로그램 코드 주소를 재배치한다. 이때 모듈에서 참조하는 외부 함수나 변수의 외부 심볼과 전역 심볼에 대응하는 논리 주소 오프셋으로 바뀐다.

6. 사용자 모드 주소 공간에 메모리 영역을 할당하고, 이곳에 모듈 구조체의 내용과 모듈명 그리고 앞으로 재배치된 모듈 코드를 복사한다.

7. 모듈 구조체의 init 필드의 함수 주소와 exit 필드의 함수 주소를 할당한다.

8. 사용자 모드 주소 공간에 할당된 메모리 주소를 이용해 init_module() 함수를 호출한다. 이 함수는 create_module() 함수와 유사한 행동을 반복한다. 모듈 처리를 할 수 있는 권한이 있는지 검사하고, find_module() 함수와 create_module() 함수를 사용해 추가된 위치를 찾고, 사용자 모드에 설정된 모듈 구조체의 내용을 덮어쓴다. 이 후 module 구조체에 있는 주소들이 올바른지 검사한다. 이 후 모듈에 할당된 메모리에 나머지 내용을 모두 복사한다. 마지막으로 init 필드에 선언된 주소를 이용하여 모듈에 포함된 모듈 초기화 함수를 호출한다. 이후 사용자 모드 메모리를 해제하고 종료한다.



모듈이 커널에서 제거되는 과정
커널에서 모듈을 제거하려면 rmmod() 함수를 실행해야 하는데, 그 실행 과정은 다음과 같다.

1. 주어진 모듈명이 "*.o"나 "*.ko"가 포함되면 파일명에서 모듈명을 얻는다. 그렇지 않다면 모듈명으로 간주한다.

2. query_module() 함수를 이용해 모듈에 대한 정보와 사용되는 커널 심볼 테이블과 모듈 심볼 테이블을 얻는다.

3. 제거해야 할 모듈 목록을 이용하여 delete_module() 함수를 호출한다. 이 함수는 시스템을 이용하여 커널 심볼 테이블과 커널에 적재된 다른 모듈의 심볼 테이블을 구한다. 이때 모듈을 제거할 수 있는 권한이 있는가를 검사하고, find_module() 함수를 통해 이미 적재된 모듈인지 검사한다. 해당 모듈을 다른 모듈에서 참조하고 있는가를 검사한다. 참조하지 않고 있으면 혹시 사용되고 있는지를 검사한 후 사용중이 아니라면 module 구조체의 exit 필드에 정의된 함수를 호출한다. 이후 커널 내의 모듈 관리 리스트에서 해당 모듈을 제거하고, vfree() 함수를 이용하여 메모리를 해제한다.

4. 제거해야 할 모듈 목록을 모두 처리하면 종료한다. 



'관련TIP' 카테고리의 다른 글

정규표현식 정리  (0) 2017.12.23
라이브러리 .a 파일 .so 파일  (0) 2017.04.28

정규표현식이란


정규 표현식(正規表現式, 영어: regular expression, 간단히 regexp[1] 또는 regex, rational expression)[2][3] 또는 정규식(正規式)은 특정한 규칙을 가진 문자열의 집합을 표현하는 데 사용하는 형식 언어이다.




메타 문자 정리


문자클래스 [] 

- [ 와 ] 사이 문자들의 매치

- [ ] 내의 ^ : 다음 문자를 제외 (ex) [^p].

- [ ] 내의 - : 범위 표현  (ex) [a-z]

- \d : 숫자,   \w : 숫자+영문자,   \s : 공백문자, 대문자의 경우 반대


. (Dot)

- \n을 제외한 모든 문자와 매치


*

- 반복, 0부터 무한개까지 매칭


+

- 반복, 1부터 무한개까지 매칭


?

- 반복, 0부터 1개까지 매칭


{m,n}

- 반복, m개 이상, n개 이하개 매칭

- 즉,   * == {0,}    + == {1,}      ? == {0,1}


^

- 문자열 시작문자와 매칭 (ex) ^p


$

- 문자열 마지막 문자와 매칭 (ex) ;$

- . $ ^ 을 문자열로 사용하고 싶으면 [] 안에 넣어 사용하면 됨 


( )

- 그룹핑에 사용

- group(0) : 매칭된 전체 문자열,   group(n) : n번째 그룹




정규표현식 테스트 사이트


https://regexr.com/


참고 : https://wikidocs.net/4309

'관련TIP' 카테고리의 다른 글

커널 모듈의 관리  (0) 2018.02.07
라이브러리 .a 파일 .so 파일  (0) 2017.04.28





정적라이브러리

- 동적(공유)라이브러리에 비해 실행 속도가 빠르고 배포에 제약이 없음

- 다만, 해당 라이브러리를 필요로 하는 모든 경우 같은 정적 라이브러리가 링크되기 때문에 배포 파일들의 사이즈가 커짐

- 그러므로 하드디스크 공간도 더 차지하고 메모리도 더 많이 차지함

- 그러나 유닉스 시스템의 경우 그때그때 필요한 부분만 메모리에 로딩하는 demand paging을 사용하기 때문에 정적인 라이브러리의 메모리 사용률과 공유 라이브러리의 메모리 사용률의 차이가 크지 않음


시스템에서 응급시에 필수로 쓰이는 유틸리티와 실행속도를 극대화해야 하는 몇몇 서버를 제외하고는 대부분 동적 라이브러리를 사용한다.



*shared library와 dynamic link library는 다른 개념이다

그러나 대부분의 경우 dynamic link library는 shared library를 만들 때 사용됨



확장자별 라이브러리 종류

*.a: 리눅스/정적 라이브러리

*.so: 리눅스/동적라이브러리

*.lib: 윈도우/정적라이브러리

*.dll: 윈도우/동적라이브러리




정적 라이브러리를 가지고 동적라이브러리로 만들기

a파일(정적라이브러리)에서 o파일(오브젝트)을 뽑아낸 다음 ld로 so타겟으로 해서 만들면된다.

$ar x abc.a

 a.o, b.o, c.o

$gcc -shared -o abc.so *.o //다시 o를 lib로 묶는다



라이브러리와 헤더파일

1. 다르다.

라이브러리는 기계어로 번역된 라이브러리이고,

헤더파일은 컴파일 하기 전의 즉, 프로그래머가 이해할 수 있고 문법에 맞게 작성되어 있는 선언들의 집합이다.


헤더가 여러개 모이는 것 != 라이브러리

컴파일된 산물인 *.o(오브젝트)파일을 여러개 모아 놓은 것 == 라이브러리


라이브러리를 사용하기 위해서 해당 라이브러리의 헤더파일이 있어야한다. 링커가 알아먹을 수 있는 심볼네임을 가지고 라이브러리를 뒤져서 링크를 하게 된다.

컴파일러가 이런 헤더파일을 가지고 심볼네임을 만들어서 오브젝트 파일에 넣어주면 링커가 해당 심볼네임을 가지고 라이브러리를 뒤져서 링크를 하게 된다.



공유와 동적의 차이

- 두개의 차이를 특별히 나누지 않는다. 다만 동적lib를 공유방식으로 사용하느냐, 독립적으로 사용하느냐는 메모리에 load할 때 결정된다. 'man dlopen'참조



출처: http://ndlessrain.tistory.com/entry/라이브러리-a-파일-so-파일 [ndlessrain]

'관련TIP' 카테고리의 다른 글

커널 모듈의 관리  (0) 2018.02.07
정규표현식 정리  (0) 2017.12.23

+ Recent posts