2024. 12. 28. 14:40ㆍ디바이스 드라이버
파일 열기/닫기 구현
int(*open)(inode,file) : 파일 열기 동작 구현
void(*release)(inode,file) : 파일 닫기 동작 구현
inode : 파일에 대한 정보를 명시하는 구조체
● i_rdev : 디바이스 노드의 주번호와 부번호를 나타내는 번호 , MAJOR() MINOR() 매크로로 주번호,부번호를 추출 가능
file : open으로 열었을 때 반환되는 fd(file descriptor)의 커널 공간 데이터
● f_inode : 파일 정보를 갖고 있는 inode
● f_cred : 파일을 열었을 때의 로그인 정보 (사용자 아이디, 그룹 아이디)
● f_pos : 현재의 파일 커서 위치
● f_mode : open으로 열 때 사용 한 모드 (O_APPEND , O_TRUNC , O_RDWR)
- O_APPEND : 파일을 열 때 쓰기 작업이 항상 파일의 끝에서 시작해서 내용을 덧붙임
- O_TRUNC : 파일을 열 때 기존 내용을 모두 삭제하고 파일 크기를 0으로 만듦
- O_RDWR : 파일을 열 때 읽기와 쓰기 모두 가능하게 설정
● private_data : 커널에서 사용할 수 있는 임시 데이터
파일 읽기/쓰기 구현
ssize_t(*read)(file,buf,len,ppos) : 파일 읽기 동작 구현
ssize_t(*write)(file,buf,len,ppos) : 파일 쓰기 동작 구현
● buf와 len은 사용자가 read / write 함수로 넘겨주는 인자 ( copy_from_user / copy_to_user로 커널 공간 / 사용자 공간으로 데이터를 복사해야함)
● ppos는 현재의 위치를 나타내는 커널이 넘겨주는 인자
read를 구현한 모습이다.
● file : 읽고자 하는 파일을 나타내는 구조체
● buf : 데이터를 복사할 사용자 공간 버퍼
● len : 읽으려는 데이터의 길이
● ppos : 현재 파일 내에서의 위치
read를 호출할 때 먼저 read_lock이라는 락을 획득한다. 이 락을 획득하면 다른 프로세스들은 읽기는 가능하지만 쓰기 작업을 할 수 없다.
만약 요청한 데이터의 크기(len)과 현재 오프셋(*ppos)을 더한 값이 버퍼 크기(BUF_SIZE)보다 크다면, 읽을 수 있는 데이터의 크기(len)을 조정한다. 예를 들어 파일의 내용이 ABCDEFGHIJK 인 SIZE가 11인 파일이 있다고 치고 ppos는 J를 가리키는 9이고, len이 3이면 읽기를 시도할 때 K가 넘어가버리기 때문에 길이를 조절하는 것이다.
copy_to_user는 커널 공간에서 사용자 공간으로 데이터를 복사하는 함수이다. device_buf + *ppos는 현재 파일 위치 이후의 버퍼를 가리키며, 이 데이터를 buf로 복사한다. 만약 copy_to_user가 성공하면 반환 값은 0이고, 실패하면 복사되지 않은 바이트 수를 반환한다. 즉 ret에는 실제로 읽은 바이트 수를 기록될 것이다.
그 다음 *ppos += ret을 통해 ppos의 위치를 최신화 시켜주고, read_unlock을 통해 얻었던 락을 반환해준다.
write를 구현한 모습이다. read와 다른 점은 __user *buf의 변수형이 const인 것이다. const를 붙인 이유는 사용자 공간에서 커널로 넘어온 데이터를 커널에서 수정할 필요가 없기 때문에 고정된 값인 const를 붙인 것이다.
또한 copy_from_user는 사용자 공간에서 커널 공간으로 데이터를 복사하는 함수이기 때문에 인수의 순서를 바꿔준다.
device_buf + *ppos는 현재 위치에서부터 데이터를 쓸 버퍼를 가리키고, buf는 사용자 공간에서 넘어온 데이터이다.
open과 마찬가지로 read와 write를 추가해준다.
qemu 가상머신에 들어가서 echo를 통해 wow라는 문구를 write 하였으며, cat을 통해 문구를 read하였다.
'디바이스 드라이버' 카테고리의 다른 글
파일 특수 제어 (ioctl) 구현 (0) | 2024.12.29 |
---|---|
디바이스 드라이버 개발 (1) (1) | 2024.12.28 |
해시테이블 (Hash Table) (0) | 2024.12.23 |
커널의 기본 API 익히기 (0) | 2024.12.23 |
커널 모듈 만들기 (0) | 2024.12.19 |