linux内核空间访问文件系统代码实现

本文代码是从互联网收集而来,我记录下来主要为学习方便,版权归原作者所有。
以下代码实现了在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); 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值