Bir Linux çekirdek modülü içindeki dosyaları oku / yaz


100

Bunun için / proc veya netlink'in nasıl kullanılacağından ziyade neden kernel'den dosya okumaması / yazmaması gerektiğine dair tüm tartışmaları biliyorum . Yine de okumak / yazmak istiyorum. Ayrıca Driving Me Fındık - Çekirdeğin Asla Yapmaması Gereken Şeyler'i okudum .

Ancak sorun 2.6.30'un dışa aktarmamasıdır sys_read(). Aksine, sarılıdır SYSCALL_DEFINE3. Yani modülümde kullanırsam şu uyarıları alıyorum:

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

Açıkçası insmodmodülü yükleyemiyor çünkü bağlantı doğru şekilde gerçekleşmiyor.

Sorular:

  • 2.6.22'den sonra çekirdek içinde nasıl okunur / yazılır (nerede sys_read()/ sys_open()dışa aktarılmaz)?
  • Genel olarak, SYSCALL_DEFINEn()çekirdek içinden makroya sarılmış sistem çağrıları nasıl kullanılır ?

Yanıtlar:


124

Mümkün olduğunda Linux çekirdeği içinden dosya G / Ç'den kaçınmanız gerektiğini bilmelisiniz. Ana fikir, "bir düzey daha derine" gitmek ve doğrudan sistem çağrısı işleyicisi yerine VFS düzeyi işlevleri çağırmaktır :

İçerir:

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

Bir dosyayı açmak (açmaya benzer):

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

Bir dosyayı kapatın (kapatmaya benzer):

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

Bir dosyadan veri okuma (pread'e benzer):

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

Bir dosyaya veri yazma (pwrite'a benzer):

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

Senkronizasyon bir dosyayı değiştirir (fsync'e benzer):

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

[Düzenle] Başlangıçta, daha yeni çekirdek sürümlerinde kullanılan file_fsync kullanmayı önerdim. Değişimi öneren ama değişikliği reddedilen zavallı adama teşekkürler. Düzenleme, ben gözden geçiremeden reddedildi.


2
Teşekkür ederim. Sys_read / sys_open işlevini kopyalayarak benzer bir şey yapmayı düşünüyordum. Ama bu harika bir yardım. Bir merak, SYSCALL_DEFINE kullanılarak bildirilen sistem çağrılarını kullanmanın herhangi bir yolu var mı?
Methos

5
Bu kodu kernel 2.6.30'da (Ubuntu 9.04) denedim ve dosyayı okumak sistemin çökmesine neden oluyor. Aynı sorunu yaşayan var mı?
Enrico Detoma

@Enrico Detoma? Vay vay. Kullandığın modülü bana vermenin herhangi bir yolu var mı? Bunu daha önce hiç görmedin mi?
dmeister

2
Bu hemen, burada oldukça güzel bir şekilde yanıtlanan "FS dansını neden yapıyorsun, btw" sorusunu gündeme getiriyor : linuxjournal.com/node/8110/print "Adres Alanını Düzeltme" bölümü altında.
PypeBros

@dmeister, ur link VFS seviyesi işlevleri için Nesne Bulunamadı
sree

23

Linux çekirdeğinin 4.14 sürümünden bu yana vfs_readve vfs_writeişlevler artık modüllerde kullanılmak üzere dışa aktarılmamaktadır . Bunun yerine, yalnızca çekirdeğin dosya erişimine yönelik işlevler sağlanır:

# 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);

Ayrıca, filp_openartık kullanıcı alanı dizesini kabul etmemektedir, bu nedenle doğrudan çekirdek erişimi için kullanılabilir (dans etmeden set_fs).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.