Linux 커널 모듈 내에서 파일 읽기 / 쓰기


99

커널에서 파일을 읽고 쓰면 안되는 이유에 대한 모든 토론을 알고 있습니다. 대신 / proc 또는 netlink 를 사용 하여이를 수행하는 방법을 알고 있습니다. 어쨌든 읽기 / 쓰기를 원합니다. 또한 드라이빙 미 너트-커널에서 절대하지 말아야 할 일도 읽었습니다 .

그러나 문제는 2.6.30이 sys_read(). 오히려 SYSCALL_DEFINE3. 따라서 모듈에서 사용하면 다음과 같은 경고가 표시됩니다.

WARNING: "sys_read" [xxx.ko] undefined!
WARNING: "sys_open" [xxx.ko] undefined!

insmod링크가 올바르게 발생하지 않기 때문에 분명히 모듈을로드 할 수 없습니다.

질문 :

  • 2.6.22 이후 커널 내에서 읽고 쓰는 방법 ( 내 보낸 sys_read()/ sys_open()내 보내지 않음)?
  • 일반적으로 SYSCALL_DEFINEn()커널 내 에서 매크로 로 래핑 된 시스템 호출을 사용하는 방법은 무엇입니까?

답변:


122

가능하면 Linux 커널 내에서 파일 I / O를 피해야합니다. 주요 아이디어는 "한 단계 더 깊게"가서 syscall 핸들러 대신 VFS 레벨 함수 를 직접 호출하는 것입니다.

다음을 포함합니다 :

#include <linux/fs.h>
#include <asm/segment.h>
#include <asm/uaccess.h>
#include <linux/buffer_head.h>

파일 열기 (열기와 유사) :

struct file *file_open(const char *path, int flags, int rights) 
{
    struct file *filp = NULL;
    mm_segment_t oldfs;
    int err = 0;

    oldfs = get_fs();
    set_fs(get_ds());
    filp = filp_open(path, flags, rights);
    set_fs(oldfs);
    if (IS_ERR(filp)) {
        err = PTR_ERR(filp);
        return NULL;
    }
    return filp;
}

파일 닫기 (닫기와 유사) :

void file_close(struct file *file) 
{
    filp_close(file, NULL);
}

파일에서 데이터 읽기 (pread와 유사) :

int file_read(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size) 
{
    mm_segment_t oldfs;
    int ret;

    oldfs = get_fs();
    set_fs(get_ds());

    ret = vfs_read(file, data, size, &offset);

    set_fs(oldfs);
    return ret;
}   

파일에 데이터 쓰기 (pwrite와 유사) :

int file_write(struct file *file, unsigned long long offset, unsigned char *data, unsigned int size) 
{
    mm_segment_t oldfs;
    int ret;

    oldfs = get_fs();
    set_fs(get_ds());

    ret = vfs_write(file, data, size, &offset);

    set_fs(oldfs);
    return ret;
}

동기화는 파일을 변경합니다 (fsync와 유사) :

int file_sync(struct file *file) 
{
    vfs_fsync(file, 0);
    return 0;
}

[편집] 원래는 최신 커널 버전에서 사라진 file_fsync 사용을 제안했습니다. 변경을 제안했지만 변경이 거부 된 가난한 사람 덕분입니다. 검토하기 전에 편집이 거부되었습니다.


2
감사합니다. sys_read / sys_open 기능을 복제하여 비슷한 일을 할 생각이었습니다. 그러나 이것은 큰 도움이됩니다. 궁금한 점은 SYSCALL_DEFINE을 사용하여 선언 된 시스템 호출을 사용하는 방법이 있습니까?
Methos

5
커널 2.6.30 (Ubuntu 9.04)에서이 코드를 시도했는데 파일을 읽으면 시스템이 충돌합니다. 누구든지 같은 문제를 경험 했습니까?
Enrico Detoma

@Enrico Detoma? 오 와우. 이게 당신이 사용한 모듈을 나에게 줄 수있는 방법이 있나요? 전에 본 적이 없습니까?
dmeister

2
그것은 즉시 "왜 FS 댄스, btw를하고 있는가"라는 질문을 제기하는데, 이것은 "Fixing the Address Space"섹션에있는 linuxjournal.com/node/8110/print 에서 아주 잘 대답 합니다.
PypeBros 2011-08-24

@dmeister, 개체 UR 링크 VFS 수준 함수를 찾을 수 없음
SREE

19

리눅스 커널의 버전 4.14 이후, vfs_read그리고 vfs_write기능은 더 이상 수출하지 모듈에 사용. 대신 커널의 파일 액세스 전용 기능이 제공됩니다.

# Read the file from the kernel space.
ssize_t kernel_read(struct file *file, void *buf, size_t count, loff_t *pos);

# Write the file from the kernel space.
ssize_t kernel_write(struct file *file, const void *buf, size_t count,
            loff_t *pos);

또한 filp_open더 이상 사용자 공간 문자열을 받아들이지 않으므로 커널 액세스에 직접 사용할 수 있습니다 (를 사용 하지 않고 set_fs).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.