Linux kernel v4.4에서 간단한 블록 장치 드라이버 만들어보기

사용자 어플과 커널간의 데이터 이동

copy_from_user_to_mybrd()

사용자로부터 커널을 통해 전달된 데이터를 램디스크에 쓰는 함수입니다.

함수 인자는

- src_page: 데이터가 저장된 페이지

- len: 데이터의 크기

- src_offset: 페이지 안에 어디서부터 데이터가 시작하는지를 알려주는 offset

- sector: 커널이 요청한 섹터 번호

섹터 번호를 알고있으니 트리에서 해당 섹터를 포함하는 페이지를 찾아올 수 있습니다. 그런데 그 페이지 전체의 데이터를 사용할게 아니지요. 그 중에 요청된 섹터만 필요합니다. 따라서 섹터 번호를 가지고 트리에서 찾아낸 페이지 안에 어디부터가 우리가 쓸 데이터인지를 알아내야합니다. 그게 바로 target_offset입니다. sector & (8-1)은 섹터 번호를 8로 나눈 나머지를 의미합니다. 한 페이지에 8개의 섹터가 들어가니까요. 이렇게하면 페이지 안에 섹터의 위치를 알 수 있고 여기에 512를 곱하면 offset이 됩니다.

그 다음은 얼마만큼 복사할지 copy 변수에 저장합니다. 하나의 bio가 가질 수 있는 데이터의 크기는 4096바이트입니다. 우리가 디스크의 블럭 사이즈를 4096으로 지정했기 때문입니다. 세그먼트는 블럭 내에 저장되는 단위이므로 한 블럭의 크기를 초과할 수 없고, 결국 한 페이지보다 클 수 없습니다. 하지만 만약 offset이 2048이고 총 복사해야할 길이가 4096이라면 두개의 페이지를 찾아야합니다. 따라서 copy값을 계산할 때 len값을 그대로 쓸지, 한 페이지에서 복사할 크기만을 쓸지를 선택합니다.

그 다음은 요청된 섹터를 갖는 페이지를 찾습니다. 페이지가 없을 수 있습니다. 처음 쓰기가 발생한 섹터라면 트리에 페이지가 없겠지요. 그럴때는 트리에 페이지를 추가해주면 됩니다. 이때도 마찬가지로 2개의 페이지에 걸쳐서 데이터가 있을 수 있으므로 2개의 페이지를 추가할 수 있습니다.

이제 페이지에 있는 데이터를 복사해와야합니다. 커널이 전달한 페이지는 src_page이고 우리가 할당한 페이지는 dst_page이므로 각각 kmap()함수를 써서 메모리 주소를 알아낸 다음 메모리 복사를 하면 됩니다.

copy_from_mybrd_to_user()

램디스크의 데이터를 사용자에게 보내주는 함수입니다. 커널이 이미 어떤 페이지의 어떤 위치에 데이터를 저장하라고 지정해줬기 때문에 드라이버는 자신이 가진 데이터를 정해진 위치에 복사하기만하면 됩니다.

그런데 처음 접근되는 섹터라면 해당되는 페이지가 없을 수 있습니다. 그럴때는 데이터가 없는 영역이므로 0으로된 데이터를 보냅니다. 나중에 해당 섹터에 쓰기가 발생되면 트리에 데이터를 추가합니다.

댓글

댓글 본문
작성자
비밀번호
버전 관리
gurugio
현재 버전
선택 버전
graphittie 자세히 보기