FSTWikiRev. 1.134 KernelApi
Login:
Password:
Join
E D R S I H P RSS
FrontPage|FindPage|TitleIndex|RecentChanges

Kernel API 1 - Core (1/2) #

-- 김도집 2005-09-22 14:20:31

Kernel API에 대한 첫번째 문서이다.

Contents

1 Kernel API 1 - Core (1/2)
1.1 서론
1.2 기본 자료형
1.3 주요 헤더 파일들
1.4 비트 연산
1.4.1 set_bit
1.4.2 clear_bit
1.4.3 change_bit
1.4.4 test_and_set_bit
1.4.5 test_and_clear_bit
1.4.6 test_and_change_bit
1.4.7 test_bit(nr,p)
1.5 initcall/exitcall
1.6 디바이스 등록 및 해제
1.6.1 struct platform_device
1.6.1.1 to_platform_device
1.6.1.2 platform_device_register
1.6.1.3 platform_device_unregister
1.6.1.4 platform_device_register_simple
1.7 드라이버 등록 및 해제
1.7.1 platform_driver
1.7.1.1 platform_driver_register
1.7.1.2 platform_driver_unregister
1.7.1.3 platform_get_drvdata/platform_set_drvdata
1.7.2 device_driver
1.7.2.1 driver_register
1.7.2.2 driver_unregister
1.7.2.3 dev_set_drvdata
1.7.2.4 dev_get_drvdata
1.8 문자 디바이스 드라이버
1.8.1 어떤 API를 사용할 것인가
1.8.2 chrdevs vs cdev_map
1.8.3 문자 디바이스 드라이버 API
1.8.3.1 struct file_operations
1.8.3.2 register_chrdev
1.8.3.3 unregister_chrdev
1.8.3.4 struct cdev
1.8.3.5 cdev_init
1.8.3.6 cdev_add
1.8.3.7 cdev_del
1.8.3.8 register_chrdev_region
1.8.3.9 alloc_chrdev_region
1.8.3.10 unregister_chrdev_region
1.9 장치 번호
1.9.1 MKDEV
1.9.2 MAJOR
1.9.3 MINOR
1.10 프로세스
1.10.1 스케줄링
1.10.1.1 schedule_timeout
1.10.1.2 set_current_state
1.10.1.3 wait_event_interruptible
1.10.1.4 wake_up_interruptible
1.11 타임(타이머)
1.11.1 ?BogoMIPS
1.11.2 loops_per_jiffy
1.11.3 jiffies
1.11.4 커널 타이머
1.11.4.1 자료 구조
1.11.4.2 TIMER_INITIALIZER
1.11.4.3 init_timer
1.11.4.4 add_timer
1.11.4.5 del_timer
1.11.4.6 mod_timer
1.11.5 High-resolution 커널 타이머
1.11.5.1 hrtimer_init
1.11.5.2 hrtimer_start
1.11.5.3 hrtimer_cacel
1.11.5.4 hrtimer_restart
1.11.5.5 hrtimer_get_remaining
1.11.5.6 hrtimer_get_res
1.11.5.7 hrtimer_active
1.11.5.8 hrtimer_forward
1.11.5.9 hrtimer_nanosleep
1.12 메모리
1.12.1 사용자/커널 공간
1.12.1.1 copy_from_user
1.12.1.2 copy_to_user
1.12.1.3 get_user
1.12.1.4 put_user
1.12.1.5 verify_area
1.12.1.6 access_ok
1.12.2 메모리 매핑
1.12.2.1 remap_page_range
1.12.2.2 remap_pfn_range
1.12.2.3 get_user_pages
1.12.3 IO 메모리 매핑
1.12.3.1 request_mem_region / release_mem_region
1.12.3.2 ioremap
1.12.3.3 iounmap
1.12.3.4 io_remap_pfn_range
1.12.3.5 readb/w/l
1.12.3.6 writeb/w/l
1.12.4 커널 메모리
1.12.4.1 kmalloc
1.12.4.2 kzalloc
1.12.4.3 vmalloc
1.12.4.4 kmem_cache_create
1.12.4.5 kmem_cache_alloc
1.12.4.6 kmem_cache_free
1.12.4.7 kmem_cache_destroy
1.12.4.8 get_zeroed_page
1.12.4.9 __get_free_page
1.12.4.10 __get_free_pages
1.12.5 유용한 매크로
1.13 MMAP
1.13.1 dma_mmap_writecombine
1.13.2 dma_free_writecombine
1.13.3 io_remap_pfn_range
2 DMA
2.1 메모리 할당
2.1.1 dma_alloc_coherent
2.1.2 dma_alloc_writecombine
2.1.3 Streaming DMA
2.1.4 dma_map_single
2.1.5 dma_unmap_single
2.1.6 dma_sync_single_for_cpu
2.1.7 dma_sync_single_for_device
2.2 DMA POOL
2.2.1 dma_pool_create
2.2.2 dma_pool_destroy
2.2.3 dma_pool_alloc
2.2.4 dma_pool_free

1.1 서론 #

본 내용은 리눅스 커널 내에서 자주 사용되는 API를 중심으로 열거식으로 정리한 것이다. 유기적인 기능들에 대해서는 설명하지 않으므로 이러한 것을 원한다면 기존의 서적들이나 문서들을 참고하기 바란다.

또한 본 내용은 직접 사용하거나 이럴 거 같다는 유추 식으로 작성된 내용도 있으므로 이것이 정확하다고 말할 수는 없다. 그러나 나름대로는 오류가 없도록 할 것이며 잘못된 내용이 있다면 최대한 빨리 수정할 수 있도록 할 것이다.

커널 버전은 2.6.11 또는 그 이후 버전들을 기준으로 작성하였다. 커널의 API는 고정된 것이 아니라 버전별로 조금씩 변경될 수도 있다. 커널 API에 대한 최신의 정보는 [http]http://lwn.net에서 확인할 수 있다.

- 2005.9.28 김도집 -

1.2 디바이스 등록 및 해제 #

리눅스 커널 2.6에서는 kobject라는 객체 기반으로 디바이스 및 드라이버의 계층적 구조를 갖고 있다. 예를 들어 등록된 버스가 있고 버스에 새로운 장치가 장착되면 버스 드라이버가 장치를 탐지하고 이에 맞는 드라이버를 찾아 등록하게 된다.

따라서 버스 상의 디바이스와 드라이버는 기본적으로 이름으로 찾게 된다. 따라서 버스 상에 등록된 디바이스의 이름과 드라이버의 이름이 서로 다르다면 정상적으로 드라이버가 동작하지 않는다.

다음은 platform_bus_type 라는 가상의 플랫폼 버스 상에 새로운 디바이스를 등록하는 방법이다.

1.2.1 자료 구조 #

platform_bus_type 라는 가상의 플랫폼 버스 상의 디바이스를 정의하는 구조체는 <linux/device.h>에 정의되어 있다. 그 구조체는 platform_device 이다.

구조체의 원형은 다음과 같다:
struct platform_device {
  char *name;
  u32 id;
  struct device dev;
  u32 num_resources;
  struct resource *resource;
};

필드설명
name
id
dev
num_resources
resource

간단한 사용 예는 다음과 같다:
static void xxx_relese_dev(struct device *dev)
{
}

static struct platform_device xxx_device = {
  .name =           "xxx_device",
  .id   =           0,
  .dev  = {
     .release = xxx_release_dev,
  },
  .num_resources = 0,
};

1.2.2 platform_device_register #

플랫폼 디바이스를 등록한다.

함수 원형은 다음과 같다:
int platform_device_register(struct platform_device *pdev)

1.2.3 platform_device_unregister #

플랫폼 디바이스의 등록을 해제한다.

함수 원형은 다음과 같다:
void platform_device_unregister(struct platform_device *pdev)

1.3 드라이버 등록 및 해제 #

1.3.1 자료 구조 #

driver_register/device_unregister 함수에서 사용하는 자료형은 <linux/device.h>에 선언되어 있다.
struct device_driver {
  const char *name;
  struct bus_type *bus;

  struct completion unloaded;
  struct kobject kobj;
  struct klist klist_devices;
  struct klist_node knode_bus;

  struct module *owner;

  int (*probe) (struct device *dev);
  int (*remove) (struct device *dev);
  int (*shutdown) (struct device *dev);
  int (*suspend) (struct device *dev, pm_message_t state, u32 level);
  int (*resume) (struct device *dev, u32 level);
};

필드설명
name디바이스 드라이버의 이름을 문자열 형으로 지정한다 (필수)
bus보통은 &platform_bus_type으로 지정한다 (필수)
unloaded
kobj내부적으로 드라이버 객체를 관리하기 위한 것으로 직접적으로 사용하지 않는다 (임의 지정하지 않는다)
klist_devices
knode_bus
owner
probe()디바이스의 초기화 루틴이다 (필수)
remove()디바이스가 제거될 때 호출되는 루틴이다 (필수)
shutdown()
suspend()절전모드로 들어갈 때 호출된다 (필수)
resume()절전모드를 빠져나올 때 호출된다 (필수)
/!\ 위 테이블에서 foo()와 같이 ()가 붙은 필드는 함수(포인터)를 의미한다.

1.3.2 driver_register #

버스를 갖는 드라이버를 등록할 때 사용하는 함수이다. 함수의 원형은 다음과 같다:
int driver_register(struct device_driver *drv);

관련함수: driver_unregister

static struct device_driver foo_driver = {
  .name    = "foo”,
  .bus     = &platform_bus_type,
  .probe   = foo_probe,
  .remove  = foo_remove,
  .suspend = foo_suspend,
  .resume  = foo_resume,
};

static int __init foo_init(void) {
  int err;

  err = driver_register(&foo_driver);

  return err;
}

1.3.3 driver_unregister #

driver_register()를 통해 등록된 드라이버를 해제할 때 사용한다. 함수의 원형은 다음과 같다:
void driver_unregister(struct device_driver *drv)

관련함수: driver_register

1.3.4 dev_set_drvdata #

사용자 데이터를 device 구조체의 driver_data 필드를 통해 참조할 수 있도록 설정하는 wrapper 함수이다.

함수 원형은 다음과 같다:
void dev_set_drvdata(struct device *dev, void *data)

관련함수: dev_get_drvdata

1.3.5 dev_get_drvdata #

device 구조체의 driver_data 필드의 참조 주소를 가져오는 wrapper 함수이다.

함수 원형은 다음과 같다:
void * dev_get_drvdata(struct device *dev)

관련함수: dev_set_drvdata

1.4 문자형 디바이스 드라이버 #

문자형 드라이버와 관련된 헤더 파일은 <linux/cdev.h>이다.

리눅스 커널에서 지원하는 대표적인 드라이버의 형태는 문자형, 블록형, 네트워크 드라이버 등이 있다. 쉽게 접근할 수 있고 가장 많이 사용되는 것이 문자형 디바이스 드라이버이다.

디바이스 파일 중 ls -l를 통해 접근권한 내용중 crw-rw---- 등과 같이 c로 시작하는 것이 문자형 디바이스 드라이버이다.

커널 버전 2.6으로 넘어오면서 내부적으로 드라이버의 구조는 많은 변화를 겪었다. 그러나 여전히 이전 버전에서 사용하던 API는 그대로 사용 가능하다. 예를 들어 {((register_chrdev()}}} 등의 문자형 디바이스 드라이버의 등록 함수가 그러하다.

이후에 소개하는 내용은 커널 2.6에서 새롭게 적용된 API를 이용하여 문자형 디바이스 드라이버를 구현하는 방법을 소개하는 것이다. 사실, 커널 버전 2.6.11에서도 이들을 직접 사용하는 예는 그리 많지 않다.

1.4.1 struct file_operations #

1.4.2 register_chrdev #

새로운 문자형 디바이스를 등록하는데, 이는 minor 번호가 0에서 시작해서 256개의 디바이스를 할당한다.

int register_chrdev(unsigned int major, const char *name, 
                    struct file_operations *fops);

1.4.3 unregister_chrdev #

register_chrdev를 통해 할당 받은 디바이스 자원을 해제한다.

void unregister_chrdev(unsigned int major, const char *name);

1.4.4 struct cdev #

문자 디바이스에서 사용하는 기본 자료형은 struct cdev;이다. 이는 에 선언되어 있다.

struct cdev {
  struct kobject kobj;
  struct module *owner;
  struct file_operations *ops;
  struct list_head list;
  dev_t dev;
  unsigned int count;
};

필드설명
kobjkobject 객체
owner모듈의 소유자로, 내부적으로 모듈의 ID정도로 사용된다. 일반적으로 THIS_MODULE 로 설정
ops파일 오퍼레이션을 지정한다.
list연결 리스트
dev디바이스 번호
count디바이스 개수

/!\ THIS_MODULE 는 매크로로 에 선언되어 있다. 이는 모듈을 컴파일 시에 그 값이 정해지며, 한 시스템 내에서 서로 다른 모듈은 서로 다른 값을 갖게 된다.

1.4.5 cdev_init #

cdev를 초기화 한다.

void cdev_init(struct cdev *cdev, struct file_operations *fops)

cdev를 0으로 모두 초기화 하고, cdev->kobj.ktype를 ktype_cdev_default 값으로 설정하고 cdev->kobj도 kobject_init를 통해 초기화 한다. 이후 cdev->ops를 fops로 설정한다.

위 설명이야 어떻든 사용자에게 중요한 것은 cdev 내의 ops를 사용자가 넘겨준 fops로 설정하는 것이다.

사용 예는 다음과 같다:
static struct file_operations xxx_fops = {
  .read = xxx_read,
  .write = xxx_write,
  .open = xxx_open,
  .release = xxx_release,
  .owner = THIS_MODULE,
};

static struct cdev xxx_cdev = {
  .kobj = {.name = "xxx", },
  .owner = THIS_MODULE,
};

static int __init xxx_init(void)
{
  dev_t dev = MKDEV(XXX_MAJOR, 0);
  
  if (register_chrdev_region(dev, MAX_XXX_MINORS, "xxx"))
    goto error;

  cdev_init(&xxx_cdev, &xxx_fops);

  ...

1.4.6 cdev_add #

문자 디바이스에 대한 객체의 관리는 cdev_map를 통해 디바이스 번호와 매핑이 된다. 이 함수는 cdev_map에 dev 라는 디바이스 번호를 등록한다.

int cdev_add(struct cdev *p, dev_t dev, unsigned count)

예시:
다음은 drivers/char/raw.craw_init() 함수의 일부 내용이다.
static int __init raw_init(vodi)
{
  int i;
  dev_t dev = MKDEV(RAW_MAJOR, 0);

  if (register_chrdev_region(dev, MAX_RAW_MINORS, "raw"))
    goto error;

  cdev_init(&raw_cdev, &raw_fops;
  if (cdev_add(&raw_cdev, dev, MAX_RAW_MINORS)) {
    unregister_chrdev_region(dev, MAX_RAW_MINORS);
    goto error;
  }

  ...
  return 0;

error:
  ...
  return 1;
}

1.4.7 cdev_del #

cdev_add를 통해 할당 받은 자원을 반환한다.

void cdev_del(struct cdev *p)

관련함수: cdev_add

예시:
다음은 drivers/char/raw.craw_exit 함수의 일부 내용이다.
static void __exit raw_exit(void)
{
  ...
  cdev_del(&raw_cdev);
  unregister_chrdev_region(MKDEV(RAW_MAJOR, 0), MAX_RAW_MINORS);
}

1.4.8 register_chrdev_region #

cdev_init를 통해 cdev를 초기화 하기 전에 호출된다. 이는 name의 문자 디바이스를 from에 해당하는 major와 minor 번호에서 부터 시작해서 count 개수 만큼의 디바이스를 할당 받는다. 본 함수는 에 선언되어 있다.


경우에 따라서는 디바이스 번호를 동적으로 할당 받고자 할 때가 있을 것이다. 이런 경우엔 reigster_chrdev_region 대신 alloc_chrdev_region을 사용한다.

int register_chrdev_region(dev_t from, unsigned count, const char *name)

/!\ 주의할 점은 count 값에 따라 시작 디바이스의 major 번호와 마지막 디바이스의 major 번호가 서로 다를 수가 있다.

관련함수: alloc_chrdev_region, unregister_chrdev_region

1.4.9 alloc_chrdev_region #

디바이스 번호를 동적으로 할당 받고자 할 때 register_chrdev_region 대신 사용한다. 해제할 때는 디바이스 번호를 알고 있으므로 unregister_chrdev_region을 사용한다.

int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
                        const char *name);

dev는 할당 받은 디바이스 번호를 넘겨 받을 포인터이다. name이라는 이름을 갖는 문자형 디바이스를 디바이스 번호의 minor 번호는 baseminor로 시작해서 count 개수 만큼 할당 받는다.

1.4.10 unregister_chrdev_region #

register_crhdev_region의 대응 함수로, from에서 count 개수 만큼 할당 받은 디바이스의 자원을 반환한다. 본 함수는 <linux/fs.h>에 선언되어 있다.

void unregister_chrdev_region(dev_t from, unsigned count)

관련함수: register_chrdev_region

예시:
다음은 drivers/char/raw.craw_exit 함수의 일부 내용이다.
static void __exit raw_exit(void)
{
  ...
  cdev_del(&raw_cdev);
  unregister_chrdev_region(MKDEV(RAW_MAJOR, 0), MAX_RAW_MINORS);
}

1.5 장치 번호 #

장치 번호는 dev_t 형으로 u32형이다. 상위 20비트가 주번호이며 하위 12비트가 부번호이다.

내부적으로 *chrdevs?MAX_PROBE_HASH가 선언되어 있다. MAX_PROBE_HASH는 255이다. 즉, 주번호가 인덱스가 되어야 하는데, 20비트라면 255개만으로는 주번호를 모두를 포함할 수 없다. 그래서 커널에서는 주번호%MAX_PROBE_HASH 로 나눈 값을 인덱스로 사용하여 그 인덱스를 기준으로 linked list로 연결하게 된다.

1.5.1 MKDEV #

ma라는 major 번호와 mi라는 minor 번호를 통해 디바이스 번호를 만든다.

dev_t MKDEV(ma, mi)

1.5.2 MAJOR #

디바이스 번호에서 major 번호를 가져온다.

unsigned int MAJOR(dev_t n)

1.5.3 MINOR #

디바이스 번호에서 minor 번호를 가져온다.

unsigned int MINOR(dev_t n)

1.6 프로세스 #

1.6.1 스케줄링 #

1.6.1.1 schedule_timeout #

적어도 일정 시간(timeout)동안 휴면상태로 있다가 다시 실행 가능 상태가 된다. 실행 가능 상태가 된다는 말은 바로 실행된다는 것이 아니라 스케줄러에 의해 조건이 충족되면 실행된다는 의미이다. 즉, 스케줄링에 따라 일정 시간 보다 더 오랫 동안 잠정적인 휴면 상태에 있을 수도 있다.

함수 원형은 다음과 같다:
signed long __sched schedule_timeout(signed long timeout)

timeout은 jiffies 단위 값으로 적어도 timeout 동안 휴면 상태에 있게 된다.

timeout동안 휴면 상태에 있을 때 task의 상태는 다음과 같을 수 있다:
상태를 나타내는 매크로설명
TASK_UNINTERRUPTIBLEtimeout 이후에만 깨어난다
TASK_INTERRUPTIBLE시그널 받거나 timeout이 되면 깨어난다

timeout을 통해 깨어나게 되면 0을 반환하고 TASK_INTERRUPTIBLE 상태에서 시그널을 받아 깨어나게 되면 남은 jiffies 값을 반환한다.

관련함수: set_current_state

set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(2);
2 jifffies 이후에 실행 가능한 상태가 되며 그때까지 휴면 상태로 있는다. 휴면 상태에서 시그널을 받는 경우에도 깨어난다.

1.6.1.2 set_current_state #

현 task의 상태를 변경한다. 이는 <linux/sched.h>헤더 파일에 정의되어 있다.

void set_cureent_state(int state)

state 값은 다음과 같다:
state설명
TASK_RUNNING실행 가능한 상태
TASK_INTERRUPTIBLE시그널을 받거나 wakeup 조건을 만족하면 깨어날 수 있는 휴면 상태
TASK_UNINTERRUPTIBLEwakeup 조건을 만족할때만 깨어날 수 있는 휴면 상태

1.7 타임(타이머) #

1.7.1 jiffies #

커널은 필수적으로 하나의 타이머 인터럽트를 갖게 된다. 이는 스케줄링 및 타이머 등의 기준이 된다. 이때 타이머 인터럽트가 한 번 발생할 때마다 이를 tick이라 하며 하나의 tick마다 jiffies 값이 1씩 증가하게 된다.

jiffies는 커널 전역 변수로 원형은 다음과 같다:
volatile unsigned long jiffies;

1.7.2 커널 타이머 #

커널 타이머 관련 함수는 <linux/timer.h>에 정의되어 있다.

1.7.2.1 자료 구조 #

struct timer_list {
  struct list_head entry;
  unsigned long expires;

  spinlock_t lock;
  unsigned long magic;

  void (*function)(unsigned long);
  unsigned long data;

  struct tvec_t_base_s *base;
};

1.7.2.2 TIMER_INITIALIZER #

TIMER_INITIALIZER(function, expires, data)

static struct timer_list foo_timer = 
  TIMER_INITIALIZER(foo_timer_function, 0, 0);

1.7.2.3 init_timer #

void init_timer(struct timer_list *timer)

1.7.2.4 add_timer #

커널 타이머를 등록하는 것으로, 내부적으로 mod_timer를 호출하여 구현된다. 그러나 mod_timer와 달리 만료 시간인 jiffies 값을 변경하는 경우엔 add_timer를 사용할 수 없다.

void add_timer(struct timer_list *timer)

1.7.2.5 del_timer #

int del_timer(struct timer_list *timer)

/!\ SMP머신에서 del_timer_sync()를 사용한다.

1.7.2.6 mod_timer #

int mod_timer(struct timer_list *timer, unsigned long expires)

1.8 메모리 #

1.8.1 사용자/커널 공간 #

메모리 영역은 사용자 영역과 커널 영역으로 나뉜다. 일반적으로 사용자 영역의 경우 page out(swap out)된 경우가 있을 수 있다. 이런 메모리 공간을 커널 영역에서 직접 접근하는 경우 page fault 등이 생길 수 있는데, 커널 공간의 일부 처리 중에는 이러한 것이 문제가 될 수 있다.

반대로 커널 영역의 메모리는 사용자 영역의 프로세스에서 직접 접근할 수 없다.

따라서 서로 다른 영역을 메모리를 접근하기 위해서는 이에 필요한 적절한 API를 이용해야 한다.

1.8.1.1 copy_from_user #

사용자 영역의 메모리에 있는 데이터를 커널 영역의 메모리 영역으로 복사할 때 사용하는 함수이다. 이 함수는 아키텍처에 의존적인 함수로 <asm/uaccess.h> 헤더 파일에 선언되어 있다.

unsigned long copy_from_user(void *to, const void __user *from, unsigned long n)

매개변수설명
to커널 영역의 메모리 주소
from사용자 영역의 메모리 주소
n바이트 단위의 데이터 크기

성공하면 0을 반환하고 실패하면 0이 아닌 값을 반환한다.

관련함수: copy_to_user

/!\ 함수 내부적으로 access_ok를 통해 사용자의 메모리 영역을 검사하므로 별도의 access_ok를 호출할 필요는 없다.

1.8.1.2 copy_to_user #

unsigend long copy_to_user(void __user *to, const void *from, unsigned long n)

1.8.1.3 get_user #

사용자 영역의 데이터를 커널 영역으로 복사할 때 사용한다. 이는 아키텍처 의존적인 함수로 <asm/uacess.h>에 선언되어 있다.

int get_user(x, void *from)

x는 char, short, int 형으로 넘겨지는 데이터 형에 따라 복사 할 데이터의 길이(바이트 단위)가 결정된다.

1.8.1.4 put_user #

커널 영역의 데이터를 사용자 영역으로 복사한다. 이는 아키텍처 의존적인 함수로 <asm/uaccess.h>에 선언되어 있다.

int put_user(x, void *to)

x는 char, short, int 형으로 넘겨지는 데이터 형에 따라 복사 할 데이터의 길이(바이트 단위)가 결정된다.

1.8.1.5 verify_area #

다음절에서 소개하는 access_ok의 wrapper 함수이다.

int verify_area(int type, const void __user * addr, unsigned long size)

메모리가 유효하면 0을 반환하고 그렇지 않으면 -EFAULT 값을 반환한다.

/!\ acess_ok함수와 동일한 것이며 사용자는 verify_area함수를 사용하길 권한다.

1.8.1.6 access_ok #

사용자 영역의 메모리가 유효한지 검사한다. <asm/uaccess.h>에 선언되어 있다.

int access_ok(int type, void *addr, unsigned long size);

매개변수설명
type어떤 유효 검사를 할지를 결정한다. 다음 표를 참조
addr유효 검사를 시작할 주소
size유효 검사를 할 영역의 바이트 단위 크기

type 매개 변수는 매크로로 선언되어 있는데, 다음과 같다:
type설명
VERIFY_READ읽기에 대한 유효 검사
VERIFY_WRIT쓰기에 대한 유효 검사

/!\ 다른 함수와 달리 유효하다면 0이 아닌 값을 반환하고 유효하지 않다면 0을 반환한다.

/!\ 동일한 기능의 함수로 access_ok의 wrapper함수가 있는데 verify_area함수가 있다. 사용자는 이것을 사용하길 권한다.

관련함수: verify_area()

copy_from_user/copy_to_user 또는 get_user/put_user 등의 함수는 access_ok를 사용할 필요가 없다. __get_user 등과 같이 더 저 수준의 함수를 직접 호출하여 사용할 때만 사용하게 된다.

다음은 access_ok를 사용한 예이다.
static inline unsigned long copy_from_user(void *to, const void __user *from,
 unsigned long n)
{
  if (access_ok(VERIFY_READ, from, n))
    n = __arch_copy_from_user(to, from, n);
  else
    memzero(to, n);
  return n;
}

1.8.2 IO 메모리 #

io 메모리와 관련된 함수는 <asm/io.h>에 선언되어 있다.

1.8.2.1 ioremap #

void __iomem *ioremap(unsigned long offset, unsigned long size)

1.8.2.2 iounmap #

void iounmap(volatile void __iomem *addr)

1.8.2.3 readb #

unsigned char readb(const volaltile void __iomem *addr)

1.8.2.4 readw #

unsigned short readw(const volaltile void __iomem *addr)

1.8.2.5 readl #

unsigned int readl(const volaltile void __iomem *addr)

1.8.2.6 writeb #

void writeb(unsigned char b, const volaltile void __iomem *addr)

1.8.2.7 writew #

void writew(unsigned short b, const volaltile void __iomem *addr)

1.8.2.8 writel #

void writel(unsigned int b, const volaltile void __iomem *addr)

last modified 2007-03-11 13:55:12
ShowPage|FindPage|DeletePage|LikePages Valid XHTML 1.0! Valid CSS! powered by MoniWiki
2.6036 sec