본문 바로가기

컴퓨터 과학 & 영상처리 관련/임베디드

Device driver / System call / file_operations

문자 디바이스는 버퍼 캐쉬를 필요로 하지 않고, 데이터가 순차적으로 처리되어 지는
장치를 말한다. 블록 디바이스는 버퍼 캐쉬를 필요로 하며, 데이터가 블록 단위로
처리되는 장치를 말한다. 네트워크 디바이스는 Network Interface를 구성하는 장치를
말한다.











\include\linux\fs.h

struct file_operations {
 struct module *owner;
 loff_t (*llseek) (struct file *, loff_t, int);
 ssize_t (*read) (struct file *, char *, size_t, loff_t *);
 ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
 int (*readdir) (struct file *, void *, filldir_t);
 unsigned int (*poll) (struct file *, struct poll_table_struct *);
 int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
 int (*mmap) (struct file *, struct vm_area_struct *);
 int (*open) (struct inode *, struct file *);
 int (*flush) (struct file *);
 int (*release) (struct inode *, struct file *);
 int (*fsync) (struct file *, struct dentry *, int datasync);
 int (*fasync) (int, struct file *, int);
 int (*lock) (struct file *, int, struct file_lock *);
 ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *);
 ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);
 ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
 unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
}


loff_t (*llseek) (struct file *, loff_t, int);
llseek는 파일에서 현재의 read 및 write의 위치를 변경한다. 이 함수가 성공적으로 수행된 후에
는 새로운 위치 값을 리턴 하고, 에러에 대해서는 음수 값을 리턴 한다.

ssize_t (*read) (struct file *, char *, size_t, loff_t *);
read는 디바이스로부터 데이터를 사용자 공간으로 가져오기 위해 사용한다. 이 함수는 에러에
대해서 음수 값을 리턴 하며, 리턴 값이 양수일 경우 성공적으로 읽은 바이트 수를 의미한다.
실제로 이 함수는 데이터를 디바이스로부터 커널 공간으로 가져와서 사용자 공간에 쓰기를 수행
하게 된다.

ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
write는 디바이스에 데이터를 쓰기 위해 사용한다. 이 함수의 리턴 값은 에러에 대해서 음수 값
을 리턴 하고, 양수 값은 디바이스에 성공적으로 쓰여진 바이트 수이다. 실제로 이 함수는 데이
터를 사용자 공간으로부터 커널 공간으로 가져와 디바이스에 쓰기를 수행한다.

int (*readdir) (struct file *, void *, filldir_t);
readdir는 디렉터리의 내용을 찾기 위해서 파일 시스템에 의해 직접적으로 사용된다.

unsigned int (*poll) (struct file *, struct poll_table_struct *);
poll은 현재의 프로세스를 대기 큐에 넣고 응용 프로그램이 디바이스로부터 이벤트를 통지 받을
수 있게 해준다.

int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
ioctl은 디바이스에 대한 특별한 명령들을 보낼 수 있게 해준다. ioctl에 의해 디바이스로 보내진
명령들은 콘솔의 baud rate 설정과 같이 해당 디바이스를 제어하기 위해 필요한 명령들이다.

int (*mmap) (struct file *, struct vm_area_struct *);
mmap은 디바이스가 가진 메모리를 사용자 공간에 맵핑시켜 이 메모리를 사용자 공간에서 직접
접근 가능하게 하기 위해서 사용된다.

int (*open) (struct inode *, struct file *);
open은 시스템 콜(open)에 의해서 디바이스 파일을 열 때 호출되는 함수로 드라이버에서 이 함
수가 반드시 지정(정의)될 필요는 없다. 드라이버에 이 함수가 지정되어 있지 않으면 시스템 콜
(open)은 항상 성공한다.

int (*flush) (struct file *);
flush는 열린 디바이스를 닫기 전에 버퍼 캐시의 데이터를 디바이스(메모리)에 쓰도록 한다. 이
것은 버퍼 캐시를 이용하는 블록 디바이스에 사용된다.

int (*release) (struct inode *, struct file *);
release는 시스템 콜(close)에 의해서 디바이스 파일을 닫을 때 호출되는 함수로 open과 마찬가
지로 드라이버에 꼭 지정(정의)할 필요는 없다.

int (*fsync) (struct file *, struct dentry *, int datasync);
fsync는 버퍼 캐시에 있는 모든 데이터를 디바이스에 쓰고 디바이스 상태를 동기화 시킨다.

int (*fasync) (int, struct file *, int);
fasync는 시스템 콜(fcntl)에 의해 FASYNC 플래그를 변경하였을 때 호출되는 함수로 드라이버
의 비 동기 통지를 지원하기 위해 사용한다.

int (*lock) (struct file *, int, struct file_lock *);
lock은 파일에 락을 걸기 위해 사용한다.