'ioctl'에 해당되는 글 2건

  1. 2011.07.08 (unlocked_ | compat_)ioctl (2)
  2. 2009.08.23 MTD partition unlock / erase

(unlocked_ | compat_)ioctl

Linux 2011. 7. 8. 11:28
예전에 공부할때는 struct file_operations에 ioctl을 지정할 때 걍 ioctl 멤버를 쓰면 되었는데, 이게 바뀌었나보다.  후배사원한테 한번 공부해보라고 device driver를 보라고 했는데, ioctl을 넣는데 멤버가 잘못됐다고 빌드가 안된다는 거다.

우선, include/linux/fs.h를 확인해보았다.  그쪽에 struct file_operaions가 정의되어있으므로.  음? ioctl 멤버가 없다.  ioctl은 없고 이름 비슷한 unlocked_ioctl과 compat_ioctl이 눈에 띈다.

이게 이름이 바뀐건가.. 하고 확인해본 결과, 그동안 커널 소스를 안보긴 진짜 엄청 안봤나보다. -_-; unlocked_ioctl과 compat_ioctl이 추가된지는 이미 6년 정도 되었다.. -_- (http://lwn.net/Articles/119652/)

이 아티클의 내용을 요약하자면 기존의 ioctl들은 BKL(Big Kernel Lock - lock_kernel())을 사용하게 되면서 관련없는 다른 process들에게도 영향을 주는 경우가 있었는데, BKL이 preemtible 해지면서 (선점이라고 많이 표현하는데 이게 맞는 표현인지는 아직도 헷갈린다) 각각의 lock mechanism을 사용하는 ioctl을 지정할 수 있는 멤버가 바로 unlocked_ioctl이다 (이름 그대로).

그리고, BKL이랑은 좀 상관 없는데 64bit kernel에서 32bit application을 돌릴때 argument를 변환시켜주는 ioctl이 바로 compat_ioctl이 된다.

이게 6년전 일이다.. -_- 2005년 1월 18일에 posting 되었으니..

그렇다 하더라도, http://lwn.net/Articles/119656/ 을 보면 두개의 새로운 멤버가 추가된 것이지, 기존의 멤버를 제거한 것은 아니었다.  그럼 도대체 언제 제거가 된 것일까? 내가 가장 열심히 리눅스 커널 소스코드를 볼때가 그래도 4~5년 전인데.. 그땐 ioctl 멤버를 문제 없이 썼었는데 말이다.

http://kerneltrap.org/mailarchive/linux-kernel/2010/7/3/4590322/thread 을 보니 의문이 풀렸다.  다행히도 비교적 얼마되지 않은 시점에 (그래도 1년전임 -_-) 변경된 것인데, 이 아티클을 보면 2.6.36부터 적용되는 것으로 나오는데, LXR에서 확인을 해보면,

2.6.35.9 에서의 file_operations
2.6.36 에서의 file_operations

2.6.36에서 변경된 것을 확인할 수 있다.  이젠 ioctl이란 멤버를 안쓰는게 확실해졌다... -_- 이거 덕분에 오랜만에 file_operations 구조체 들여다보게 되었다.

여러가지 느꼈지만 그중에 제일은 내가 나이를 좀 먹었다는거... -_-?
Posted by 강군님

댓글을 달아 주세요

  1. 리지 2011.08.09 21:06  댓글주소  수정/삭제  댓글쓰기

    저도 오류가 나서 찾던중, .unlocked_ioctl로 바꾸면 오류가 안날꺼라는 반토막 설명을 봤었습니다;
    설명 및 링크들 고맙습니다 ^^

MTD partition unlock / erase

STB 2009. 8. 23. 17:24
Open Source를 못믿는 것은 아니지만, 그 소스를 보지 않고 동작을 기대할 수는 없는 노릇이다.  특정 MTD partition을 erase해주는 flash_eraseall도 그 중의 하나일 것이다.  뭐 다른 이유도 있었지만 flash_eraseall을 구현해보았다.

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/mtd/mtd-abi.h>

int main(int argc, char **argv)
{
    int fd;
    char *dev_name;
    struct mtd_info_user mtd_info;
    struct erase_info_user erase_info;

    if (argc != 2)
    {
        printf("Usage : mtd_test /dev/mtd0\n");
        return 0;
    }

    dev_name = argv[1];

    fd = open(dev_name, O_RDWR);
    if (fd < 0)
    {
        perror("open error : ");
        return -1;
    }

    if (ioctl(fd, MEMGETINFO, &mtd_info) != 0)
    {
        perror("ioctl(MEMGETINFO) error : ");
        close(fd);
        return -1;
    }

    erase_info.length = mtd_info.erasesize;
    for (erase_info.start = 0x0; erase_info.start < mtd_info.size; erase_info.start += mtd_info.erasesize)
    {
        if (ioctl(fd, MEMUNLOCK, &erase_info) != 0)
        {
            perror("ioctl(MEMUNLOCK) error : ");
            close(fd);
            return -1;
        }

        if (ioctl(fd, MEMERASE, &erase_info) != 0)
        {
            perror("ioctl(MEMERASE) error : ");
            close(fd);
            return -1;
        }
    }

    close(fd);
    return 0;
}


ioctl로 처리되었고, 여기서 사용된 MEMUNLOCK, MEMERASE parameter와 struct mtd_info_user, struct erase_info_user는 linux/mtd/mtd-abi.h에 정의되어있다.  struct는 다음과 같다.

struct mtd_info_user {
    uint8_t type;
    uint32_t flags;
    uint32_t size;
    uint32_t erasesize;
    uint32_t writesize;
    uint32_t oobsize;
    uint32_t ecctype;
    uint32_t eccsize;
};

struct erase_info_user {
    uint32_t start;
    uint32_t length;
};


이런 저런 사정이 있어 application을 만든거지만, 다시 한번 느낀건 커널을 웬만하면 의심하지 말자... -.- D/D에 문제가 있을 거라고 생각하고 소스 파헤집다가 결국 문제가 없다는 것을 깨닫기까지 무려 2일이나 걸렸다 ;;
Posted by 강군님

댓글을 달아 주세요