강좌 & 팁
글 수 2,412
2011.10.10 16:19:17 (*.119.104.169)
43769
안녕하세요!! 이번주도 어김 없이 석사(과정)중인 이우영 입니다.
저번주는 감기에 걸려 한주간 고생했습니다 (ㅠ,ㅜ)
오늘은 저번주에 이어 /dev/mem의 memory_lseek, mmap_mem을 알아 보도옥 하겠습니다.
먼저 memory_lseek 부터 알아 보겠습니다.
linux/drivers/cahr/mem.c 766 라인 을 보시면
766static loff_t memory_lseek(struct file * file, loff_t offset, int orig) 767{ 768 loff_t ret; 769 770 mutex_lock(&file->f_path.dentry->d_inode->i_mutex); 771 switch (orig) { 772 case 0: 773 file->f_pos = offset; 774 ret = file->f_pos; 775 force_successful_syscall_return(); 776 break; 777 case 1: 778 file->f_pos += offset; 779 ret = file->f_pos; 780 force_successful_syscall_return(); 781 break; 782 default: 783 ret = -EINVAL; 784 } 785 mutex_unlock(&file->f_path.dentry->d_inode->i_mutex); 786 return ret; 787}
파일의 읽고 쓰기는 위치를 지정하는 offset의 위치를 변경하는 함수를 일반적으로 lseek라고 부릅니다.
여기서는 메모리의 읽고 쓸 위치를 변경해 주겠죠?
file의 f_pos 변수가 현재 읽고쓰는 위치를 가지고 있습니다. 이 값을 변경 함으로써
다음에 읽고 쓰는 위치를 변경 할 수 있습니다.
file->f_ops값을 변경 하기 전에 mutex_lock을 이용하여 임계영역을 보호해 줍니다.
lseek는 orig 값을통해 switch문으로 여러 동작을 정의 합니다.
0 값은 지정한 위치로 file->fops 값을 변경하고,
1 값은 현재 위치에서 offset 값 많큼 더해 준다.
그 외의 값은 에러를 발생 시킨다.
다음으로
336static int mmap_mem(struct file * file, struct vm_area_struct * vma) 337{ 338 size_t size = vma->vm_end - vma->vm_start; 339 340 if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size)) 341 return -EINVAL; 342 343 if (!private_mapping_ok(vma)) 344 return -ENOSYS; 345 346 if (!range_is_allowed(vma->vm_pgoff, size)) 347 return -EPERM; 348 349 if (!phys_mem_access_prot_allowed(file, vma->vm_pgoff, size, 350 &vma->vm_page_prot)) 351 return -EINVAL; 352 353 vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff, 354 size, 355 vma->vm_page_prot); 356 357 vma->vm_ops = &mmap_mem_ops; 358 359 /* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */ 360 if (remap_pfn_range(vma, 361 vma->vm_start, 362 vma->vm_pgoff, 363 size, 364 vma->vm_page_prot)) { 365 unmap_devmem(vma->vm_pgoff, size, vma->vm_page_prot); 366 return -EAGAIN; 367 } 368 return 0; 369}
353라인에서 phys_mem_access_prot 함수를 통해 mem에 접근 권한을 얻어 옵니다.
357라인 에서 mmap_mem_ops주소를 등록 합니다
mmap_mem_ops는 mem.c의 다음 위치에 정의 되어 있습니다.
328static struct vm_operations_struct mmap_mem_ops = { 329 .open = mmap_mem_open, 330 .close = mmap_mem_close, 331#ifdef CONFIG_HAVE_IOREMAP_PROT 332 .access = generic_access_phys 333#endif 334};
360라인에서는 remap_pfn_range 함수를 통해 유저공간에 커널 메모리를 매핑한다.
리턴 값이 0일 경우 에러이다. 다시 unmap_devmem을 해주고 에러를 반환한다.
정상일경우 0을 리턴 해줍니다.
오늘도 간단하게만 알아 보았습니다.
다음주는 미리미리 공부해서 실습을 할 수 있도록 준비를 해보겠습니다.
그럼 다음시간에 만나요~