1

문자 장치 인터페이스가있는 플랫폼 장치 드라이버와 장치 별 데이터 구조에 데이터 저장 사이의 연결을 이해하는 데 어려움을 겪고 있습니다. 플랫폼 드라이버 및 문자 장치 인터페이스를 사용하는 장치 별 데이터 구조

내가 내 장치에 관련된 데이터의 구조체 유지 트랙을 생성 한 후 프로브 기능의 디바이스 구조체에 추가 :

dev_set_drvdata(dev, data_struct); 

나는 또한 data_struct의 글로벌 사본을 보관.

나는 mmap()이 될 수있는 기타 장치를 등록하고 ioctl() 명령을 통해 장치에 액세스합니다. 이 장치의 data_struct에 액세스하고 현재 전역 복사본을 통해 액세스하고 싶습니다. inode 또는 file 포인터를 통해 다른 방법으로 장치 구조체에 저장된 데이터에 액세스 할 수 있습니까?

저는 현재 장치의 인스턴스 하나만 허용하고 있지만, 동일한 드라이버를 사용하는 장치가 여러 개인 미래의 구현을 위해 이것을 올바르게 구현하고 싶습니다.

답변

2

하여 miscdevice 처음 오픈 될 때, miscdevice 프레임 워크에 file->private_data을 설정할 것이다 struct miscdevice (misc_open() 함수와 같은 함수 comment to misc_register() 참조). 이 작업에 의존하여 파일 작업에 file->private_data을 사용하여 container_of() 매크로를 사용하여 사용자 지정 구조를 얻을 수 있습니다. 물론 사용자 정의 구조에는 struct miscdevice이 있어야합니다. 깔끔하고 일반적으로 사용되는 방법은 to_*()이라는 도우미 함수를 작성하여 file 포인터로 사용자 정의 구조체를 찾아서 반환합니다. 따라서 사용자 정의 구조체 my_struct을 호출 한 경우 해당 도우미 함수를 to_my_struct()으로 호출해야합니다.

또한 플랫폼 드라이버를 작성하는 경우 dev_set_drvdata() 대신 platform_set_drvdata()을 사용할 수 있습니다. 플랫폼 드라이버의 기능 remove()에서 사용자 지정 구조를 얻을 수 있도록이 작업이 필요합니다.

$ git grep -l --all-match -e 'misc_register(' -e 'platform_device' -e 'file->private_data' -- drivers/ 
: 당신은 그냥이 같은 키워드를 사용하여, 커널 코드에서 예를 찾을 수있는 방법으로

struct my_struct { 
    struct platform_device *pdev; 
    struct miscdevice mdev; 
}; 

static inline struct my_struct *to_my_struct(struct file *file) 
{ 
    struct miscdevice *miscdev = file->private_data; 

    return container_of(miscdev, struct my_struct, mdev); 
} 

static ssize_t my_read(struct file *file, char __user *buf, size_t count, 
       loff_t *pos) 
{ 
    struct my_struct *my = to_my_struct(file); 

    return simple_read_from_buffer(buf, count, pos, "my text", 7); 
} 

static const struct file_operations my_fops = { 
    .owner = THIS_MODULE, 
    .read = my_read, 
}; 

static int my_probe(struct platform_device *pdev) 
{ 
    struct my_struct *my; 
    int ret; 

    my = devm_kzalloc(&pdev->dev, sizeof(*my), GFP_KERNEL); 
    if (!my) 
     return -ENOMEM; 

    platform_set_drvdata(pdev, my); 
    my->pdev = pdev; 

    my->mdev.minor = MISC_DYNAMIC_MINOR; 
    my->mdev.name = "my"; 
    my->mdev.fops = &my_fops; 
    my->mdev.parent = NULL; 

    ret = misc_register(&my->mdev); 
    if (ret) { 
     dev_err(&pdev->dev, "Failed to register miscdev\n"); 
     return ret; 
    } 

    dev_info(&pdev->dev, "Registered\n"); 

    return 0; 
} 

static int my_remove(struct platform_device *pdev) 
{ 
    struct my_struct *my = platform_get_drvdata(pdev); 

    misc_deregister(&my->mdev); 
    dev_info(&pdev->dev, "Unregistered\n"); 

    return 0; 
} 

: 여기

모든 것이 위에서 설명한에 대한 예입니다