2009-07-26 32 views
73

Tôi biết tất cả các cuộc thảo luận về lý do tại sao người ta không nên đọc/ghi các tập tin từ hạt nhân, thay vào đó làm thế nào để sử dụng/proc hoặc netlink để làm điều đó. Tôi vẫn muốn đọc/ghi. Tôi cũng đã đọc Driving Me Nuts - Things You Never Should Do in the Kernel.Cách đọc/ghi tệp trong mô-đun hạt nhân Linux?

Tuy nhiên, sự cố là 2.6.30 không xuất sys_read(). Thay vào đó nó được bọc trong SYSCALL_DEFINE3. Vì vậy, nếu tôi sử dụng trong mô-đun của tôi, tôi nhận được cảnh báo sau đây:

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

Rõ ràng insmod không thể nạp module vì liên kết không xảy ra một cách chính xác.

Câu hỏi:

  • Làm thế nào để đọc/ghi trong kernel 2.6.22 sau (nơi sys_read()/sys_open() không xuất khẩu)?
  • Nói chung, cách sử dụng các cuộc gọi hệ thống được bao bọc trong macro SYSCALL_DEFINEn() từ bên trong hạt nhân?

Trả lời

94

Bạn nên lưu ý rằng bạn nên tránh tệp I/O khi có thể. Ý tưởng chính là để đi "một mức độ sâu hơn" và gọi VFS level functions thay vì xử lý syscall trực tiếp:

Bao gồm:

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

Mở một tập tin (tương tự để mở):

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; 
} 

Đóng một tệp (tương tự như đóng):

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

Đọc dữ liệu từ tệp (tương tự như prea d):

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; 
} 

Viết dữ liệu vào một tập tin (tương tự như 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; 
} 

Đồng bộ hoá thay đổi một tập tin (tương tự như fsync):

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

[Chỉnh sửa] Nguyên, Tôi đã đề xuất sử dụng file_fsync, đã biến mất trong các phiên bản hạt nhân mới hơn. Nhờ anh chàng nghèo gợi ý sự thay đổi, nhưng sự thay đổi của họ đã bị từ chối. Bản chỉnh sửa đã bị từ chối trước khi tôi có thể xem lại.

+2

Cảm ơn bạn. Tôi đã suy nghĩ để làm một cái gì đó tương tự bằng cách nhân rộng chức năng sys_read/sys_open. Nhưng đây là sự trợ giúp tuyệt vời. Một sự tò mò, có cách nào để sử dụng các cuộc gọi hệ thống được khai báo bằng SYSCALL_DEFINE không? – Methos

+5

Tôi đã thử mã này trong hạt nhân 2.6.30 (Ubuntu 9.04) và đọc tệp bị treo hệ thống. Bất kỳ ai cũng gặp phải vấn đề tương tự? –

+0

@Enrico Detoma? Tuyệt vời. Điều này có cách nào mà bạn có thể cho tôi các mô-đun bạn sử dụng? Chưa bao giờ thấy điều đó trước đây? – dmeister

Các vấn đề liên quan