在linux内核中读写文件2

Posted soul.stone

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在linux内核中读写文件2相关的知识,希望对你有一定的参考价值。

1,内核代码

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/spinlock.h>
#include <linux/blkdev.h>
#include <linux/module.h>  
#include <linux/fs.h>  
#include <linux/errno.h>  
#include <linux/mm.h>  
#include <linux/cdev.h>  
#include <linux/sched.h>

#define IO_CMD_LEN      1024  
#define CHAR_DEV_NAME   "klog"

typedef struct 
{
    int file_id; //todo
    int rw_pos;  //todo
    int cmd_type;
    int buff_len;
    char io_buff[IO_CMD_LEN - 16];
}KLOG_CMD_INFO;

#if 1

struct file *klog_fp = NULL;
loff_t klog_pos = 0;

static int user_cmd_proc(char *user_cmd, char *out_str)
{
    KLOG_CMD_INFO *klog_cmd = (KLOG_CMD_INFO *)user_cmd;
    KLOG_CMD_INFO *klog_ack = (KLOG_CMD_INFO *)out_str;
    
    if(klog_cmd->cmd_type == 1) { //open file
        if (klog_fp != NULL)  filp_close(klog_fp, NULL);
            
        klog_fp = filp_open(klog_cmd->io_buff, O_RDWR | O_CREAT | O_TRUNC, 0644);
        if (IS_ERR(klog_fp)){
            printk("filp_open error \n");
            return -1;
        }
        klog_pos = 0;
        sprintf(klog_ack->io_buff, "filp_open ok\n");
    }
    
    if(klog_cmd->cmd_type == 2) { //write file
        mm_segment_t old_fs;
        old_fs = get_fs();
        set_fs(KERNEL_DS); //to check why
        klog_pos += vfs_write(klog_fp, klog_cmd->io_buff, klog_cmd->buff_len, &klog_pos);
        set_fs(old_fs);
        sprintf(klog_ack->io_buff, "vfs_write ok\n");
    }

    if(klog_cmd->cmd_type == 3) { //close file
        filp_close(klog_fp, NULL);
        klog_fp = NULL;
        sprintf(klog_ack->io_buff, "filp_close ok\n");
    }
    
    return 0;
}
#endif

#if 1
  
int mem_open(struct inode *inode, struct file *filp)  
{  
    return 0;   
}  
  
int mem_release(struct inode *inode, struct file *filp)  
{  
    return 0;  
}  

char user_cmd[IO_CMD_LEN] = {0};
char out_str[IO_CMD_LEN] = {0};

int mem_ioctl( struct file *file, unsigned int cmd, unsigned long arg)
{    
    printk("mem_ioctl: %d \n", cmd);    
    
    if(copy_from_user(user_cmd,  (int *)arg, IO_CMD_LEN)) 
        return -EFAULT;
    
    user_cmd_proc(user_cmd, out_str);
    
    if(copy_to_user( (int *)arg, out_str, IO_CMD_LEN)) 
        return -EFAULT;

    return 0;
}

static int mem_major = 0;
struct class *pclass = NULL;  
struct cdev my_dev;   

static const struct file_operations mem_fops =  
{  
    .owner = THIS_MODULE,  
    .unlocked_ioctl = mem_ioctl,
    .open = mem_open,  
    .release = mem_release,  
};  

static int memdev_init(void)  
{  
    int result;  

    dev_t devno = MKDEV(mem_major, 0);  

    if (mem_major) { /* 静态申请设备号*/  
        result = register_chrdev_region(devno, 2, CHAR_DEV_NAME);  
    } else { /* 动态分配设备号 */  
        result = alloc_chrdev_region(&devno, 0, 2, CHAR_DEV_NAME);  
        mem_major = MAJOR(devno);  
    }   

    if (result < 0)  {  
        printk("alloc_chrdev failed!\n");  
        return result;  
    }  

    cdev_init(&my_dev, &mem_fops);  
    my_dev.owner = THIS_MODULE;  
    my_dev.ops = &mem_fops;  
    cdev_add(&my_dev, MKDEV(mem_major, 0), 2);   /*设备数2*/  

    pclass = class_create(THIS_MODULE, CHAR_DEV_NAME);  
    if (IS_ERR(pclass))  {  
        printk("class_create failed!\n");  
        goto failed;  
    }  

    device_create(pclass, NULL, devno, NULL, CHAR_DEV_NAME);  
    return 0;  

failed:   
    cdev_del(&my_dev);
    unregister_chrdev_region(devno, 1);  
    return result;  
}  
  
static void memdev_exit(void)  
{  
    device_destroy(pclass, MKDEV(mem_major, 0));  
    class_destroy(pclass);
    
    cdev_del(&my_dev);
    unregister_chrdev_region(MKDEV(mem_major, 0), 2); 
}  
#endif
  
MODULE_AUTHOR("derek yi");  
MODULE_LICENSE("GPL");  
  
module_init(memdev_init);  
module_exit(memdev_exit);  

 

 

2,测试代码

#include <stdio.h>  
#include <fcntl.h>  
#include <stdlib.h>  
#include <string.h>  
#include <sys/types.h>  
#include <sys/stat.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <sys/syscall.h>

#define IO_CMD_LEN      1024  

typedef struct 
{
    int file_id; //todo
    int rw_pos;  //todo
    int cmd_type;
    int buff_len;
    char io_buff[IO_CMD_LEN - 16];
}KLOG_CMD_INFO;

KLOG_CMD_INFO cmd_info;

int main()
{
    int fd;
    int ret = 0;

    fd = open("/dev/klog", O_RDWR);
    if( fd < 0 ) {
        printf("open memdev WRONG!\n");
        return 0;
    }

    sprintf(cmd_info.io_buff, "/home/derek/klog.txt");
    cmd_info.cmd_type = 1;
    ret = ioctl(fd, 0, &cmd_info);
    printf("open: ret=%d rdata:%s\n", ret, cmd_info.io_buff);

    for(int i = 0; i < 10; i++) {
        sprintf(cmd_info.io_buff, "%d: ==============================\n", i);
        cmd_info.buff_len = strlen(cmd_info.io_buff);
        cmd_info.cmd_type = 2;
        ret = ioctl(fd, 0, &cmd_info);
        printf("read: ret=%d rdata:%s\n", ret, cmd_info.io_buff);
    }

    cmd_info.cmd_type = 3;
    ret = ioctl(fd, 0, &cmd_info);
    printf("close: ret=%d rdata:%s\n", ret, cmd_info.io_buff);
   
    close(fd);
    return 0;
}

 

以上是关于在linux内核中读写文件2的主要内容,如果未能解决你的问题,请参考以下文章

提供的SDK包中,在linux内核中读写文件

提供的SDK包中,在linux内核中读写文件

linux下c通过虚拟地址映射读写文件的代码

linux内核之Kfifo环形队列

read()的Linux C

linux内核数据结构之kfifo