IT 그리고 정보보안/Knowledge base

리눅스 디렉토리 관리

plummmm 2021. 4. 14. 13:37
반응형

디렉토리 만들고 삭제하는 mkdir, rmdir 함수에 대해 알아보자.

먼저 디렉토리를 생성하는 mkdir 함수이다.

 

mkdir로 디렉토리를 생성하면 자동적으로 dot(.), dot-dot(..) 디렉토리가 생성된다.

권한에 대해 설정할 때 읽기,쓰기만 설정하고 실행권한을 설정안하면 디렉토리 안에 있는 파일에 대해 접근이 불가능하다.(주의) ,,, 다음 디렉토리를 삭제하는 rmdir 함수이다.

디렉토리 안에 파일이 있으면 안된다. dot, dot-dot 디렉토리만 있는 상태여야 삭제가 됨.

 

디렉토리 읽기

이번에는 디렉토리 읽기에 관련된 함수들에 알아보자. 디렉토리 읽기라 함은.. ls 명령을 치는 것과 일맥상통한다.

디렉토리에 대한 읽기는 누구나 가능하다.

초기 UNIX 시스템에서는 디렉토리 구조가 총 16바이트 중 14바이트가 파일이름 이고  2바이트가 i-node 번호였다.

근데 이후 버전 부터는 긴 파일이름을 지원하기 시작하면서 디렉토리 길이 형식이 가변적으로 변했다.

그래서 디렉토리를 읽는 (ls) 프로그램을 시스템에 독립적으로 작성하는 것이 불가능하게 되었다.

 

그리하여 여러가지 루틴들이 개발되었다.

opendir(), closedir(), readdir(), rewinddir() 등인데, 

얘내들은 POSIX.1 표준에 포함되어있다.

 

시스템콜 함수들이 아니다!!!

 

하나의 시스템콜로 구현하지 못하는 경우가 발생해서 개발된 POSIX.1 루틴들이다.

위에 언급한 4개 말고 더있는데 일단 4개만 알아보자.

 

opendir 함수는 디렉토리를 여는 함수이다.

다른건 됐고.. 반환값을 주목할 필요가 있다.

DIR 이라는 포인터가 반환되는데, 디렉토리 정보가 담긴 구조체의 포인터이다.

구조체는 dirent.h 파일에 정의되어 있다.

 

열었으니 읽어야할 것이다. readdir()을 보자.

 

readdir은 말그대로 디렉토리를 읽는 함수이다.  한번 호출할 때마다 디렉토리에 있는 파일을 순서대로 하나씩 읽어온다.

 

opendir() 하여 열린 디렉토리에 대한 포인터를 인자로 갖고, dirent 라는 구조체의 포인터를 반환하는 함수이다.

이 구조체는 아래와 같이 생겨먹었다.

출처: http://forum.falinux.com/zbxe/index.php?document_srl=408491&mid=C_LIB

APUE에서는 구조체가 위에꺼 보다 간단하게 나오는데..  책이 오래되서 그런가? 하튼 아래와 같이 생겼다.

어쨋든.. readdir()에 대해 아는 것이 핵심이니.. 다음은 closedir()을 보자.

정보를 읽었으니 닫아야 할 것이 아닌가. 이것 또한 opendir 에서 반환된 포인터를 인자로 갖는다.

설명은 필요가 없다고 생각한다.  다음 마지막 rewinddir() 이다.

read를 디렉토리의 처음부터 하고 싶다면 rewinddir 함수를 사용하면된다.

역시나 DIR 포인터를 인자로 가짐. 이걸 호출하고 readdir 하면 첫 파일을 읽음

 

----------------------------------------------------------------

 

위 코드는 readdir()을 디렉토리가 끝날 때 까지 읽고 rewinddir()로 처음으로 돌아가 다시한번 더 디렉토리를 읽고

끝나면 closedir()로 닫는 코드이다.

 

마지막으로, 현재 디렉토리를 변경하는 chdir과 fchdir 그리고 현재 디렉토리를 출력하는 getcwd에 대해 알아보자.

chdir과 fchdir부터 보자.

시스템콜 함수들은 f가 붙으면 전부 열린 파일에 대한 함수인듯 하다. 열린 파일이냐 아니냐 차이지 뭐 하는 기능은 동일하다. 예제를 보면서 이해도를 높여주겠다.

 

현재 프로세스의 경로를 변경시키는 함수가 chdir 이다.

근데 실행해보면 예상과 다른(?) 결과가 나온다.

 

왜 이런결과가 나오는 것일까.

먼저 첫 줄의 pwd 명령을 실행할 때 프로세스는 셸(shell)이다.

그리고 mycd(예제 코드 컴파일한 실행파일)은 셸의 자식 프로세스가 된다.

 

실행 되어 있는 상태에서 mycd 프로세스의 작업경로가 바뀌는 것이지

셸은 영향을 받지 않는다는 말이 되겠다.

 

cd명령이 외부 프로세스가 아니라 셸의 내장명령인 이유가 여기있다.

 

이렇게 커널이 현재 작업 디렉토리에 대한 내용을 저장하고 있으니, (셸이 원래 경로로 돌아온걸 보고)

경로 이름까지 커널이 저장하고 있을거라고 착각할 수 있다.

아닙니당. 커널은 전체 경로에 대한 내용은 모른다. 그래도 귀찮게 하나하나 따라 올라가며 찍을 필요 없이

시스템콜 함수가 정의되어 있다.

 

getcwd()라는 함수이다.

 

현재 디렉토리의 전체 경로 문자열을 저장할 buf를 반환한다. size를 넉넉하게 잡아주지 않으면 오류가 난다..

(넉넉하게 잡아주세요 쓸 때) 간혹 size에 NULL을 주어 동적할당하여 사용하는 경우도 있었다고 한다. 하지만 지금 구현이 size를 명시해줘야 하므로 ~  

반응형