本文代码是从互联网收集而来,我记录下来主要为学习方便,版权归原作者所有。
以下代码实现了在linux内核空间打开、读、写文件等相关函数,有兴趣的可以研究一下并在此基础上扩展。
 
#include <linux/config.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/file.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
 
/*
  file I/O in kernel module
*/
#define EOF (-1)
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
 
// Context : User
// Parameter :
// filename : filename to open
// flags :
// O_RDONLY, O_WRONLY, O_RDWR
// O_CREAT, O_EXCL, O_TRUNC, O_APPEND, O_NONBLOCK, O_SYNC, ...
// mode : file creation permission.
// S_IRxxx S_IWxxx S_IXxxx (xxx = USR, GRP, OTH), S_IRWXx (x = U, G, O)
// Return :
// file pointer. if error, return NULL
 
struct file *klib_fopen(const char *filename, int flags, int mode)

    struct file *filp = filp_open(filename, flags, mode);
 
    return (IS_ERR(filp)) ? NULL : filp;
}
 
// Context : User
// Parameter :
// filp : file pointer
// Return :
void klib_fclose(struct file *filp)
{
    if (filp)
        fput(filp);
}
 
// Context : User
// Parameter :
// filp : file pointer
// offset :
// whence : SEEK_SET, SEEK_CUR
// Comment :
// do not support SEEK_END
// no boundary check (file position may exceed file size)
int klib_fseek(struct file *filp, int offset, int whence)
{
 
    int pos = filp->f_pos;
 
    if (filp) {
 
        if (whence == SEEK_SET)
            pos = offset;
        else if (whence == SEEK_CUR)
            pos = offset;
 
        if (pos < 0)
            pos = 0;
 
        return (filp->f_pos = pos);
    } else
        return -ENOENT;
 
}
 
// Context : User
// Parameter :
// buf : buffer to read into
// len : number of bytes to read
// filp : file pointer
// Return :
// actually read number. 0 = EOF, negative = error
int klib_fread(char *buf, int len, struct file *filp)
{
    int readlen;
 
    mm_segment_t oldfs;
 
    if (filp == NULL)
        return -ENOENT;
 
    if (filp->f_op->read == NULL)
        return -ENOSYS;
 
    if (((filp->f_flags & O_ACCMODE) & O_RDONLY) != 0)
        return -EACCES;
 
    oldfs = get_fs();
    set_fs(KERNEL_DS);
 
    readlen = filp->f_op->read(filp, buf, len, &filp->f_pos);
 
    set_fs(oldfs);
 
    return readlen;
}
 
// Context : User
// Parameter :
// filp : file pointer
// Return :
// read character, EOF if end of file
 
int klib_fgetc(struct file *filp)
{
 
    int len;
    unsigned char buf[4];
 
    len = klib_fread((char *)buf, 1, filp);
 
    if (len > 0)
        return buf[0];
    else if (len == 0)
        return EOF;
    else
        return len;
}
 
// Context : User
// Parameter :
// str : string
// size : size of str buffer
// filp : file pointer
// Return :
// read string. NULL if end of file
// Comment :
// Always append trailing null character
 
char *klib_fgets(char *str, int size, struct file *filp)
{
 
    char *cp;
    int len, readlen;
    mm_segment_t oldfs;
 
    if (filp && filp->f_op->read
        && ((filp->f_flags & O_ACCMODE) & O_WRONLY) == 0) {
        oldfs = get_fs();
        set_fs(KERNEL_DS);
 
        for (cp = str, len = -1, readlen = 0; readlen < size - 1;
             cp, readlen) {
 
            if ((len =
                 filp->f_op->read(filp, cp, 1, &filp->f_pos)) <= 0)
                break;
 
            if (*cp == '/n') {
                cp;
                readlen;
                break;
 
            }
        }
 
        *cp = 0;
        set_fs(oldfs);
 
        return (len < 0 || readlen == 0) ? NULL : str;
    } else
        return NULL;
 
}
 
// Context : User
// Parameter :
// buf : buffer containing data to write
// len : number of bytes to write
// filp : file pointer
// Return :
// actually written number. 0 = retry, negative = error
 
int klib_fwrite(char *buf, int len, struct file *filp)
{
    int writelen;
    mm_segment_t oldfs;
 
    if (filp == NULL)
        return -ENOENT;
 
    if (filp->f_op->write == NULL)
        return -ENOSYS;
 
    if (((filp->f_flags & O_ACCMODE) & (O_WRONLY | O_RDWR)) == 0)
        return -EACCES;
 
    oldfs = get_fs();
    set_fs(KERNEL_DS);
    writelen = filp->f_op->write(filp, buf, len, &filp->f_pos);
    set_fs(oldfs);
 
    return writelen;
}
 
// Context : User
// Parameter :
// filp : file pointer
// Return :
// written character, EOF if error
int klib_fputc(int ch, struct file *filp)
{
    int len;
    unsigned char buf[4];
 
    buf[0] = (unsigned char)ch;
    len = klib_fwrite(buf, 1, filp);
 
    if (len > 0)
        return buf[0];
    else
        return EOF;
}
 
// Context : User
// Parameter :
// str : string
// filp : file pointer
// Return :
// count of written characters. 0 = retry, negative = error
int klib_fputs(char *str, struct file *filp)
{
    return klib_fwrite(str, strlen(str), filp);
}
 
// Context : User
// Parameter :
// filp : file pointer
// fmt : printf() style formatting string
// Return :
// same as klib_fputs()
int klib_fprintf(struct file *filp, const char *fmt, ...)
{
    static char s_buf[1024];
 
    va_list args;
    va_start(args, fmt);
    vsprintf(s_buf, fmt, args);
    va_end(args);
    return klib_fputs(s_buf, filp);
}
Logo

更多推荐