drivers/mtd/nandsim.c
<1>:打开文件
cfile = filp_open(cache_file, O_CREAT | O_RDWR | O_LARGEFILE, 0600);
if (IS_ERR(cfile))
return PTR_ERR(cfile);
if (!cfile->f_op || (!cfile->f_op->read && !cfile->f_op->aio_read)) {
NS_ERR("alloc_device: cache file not readable/n");
err = -EINVAL;
goto err_close;
}
if (!cfile->f_op->write && !cfile->f_op->aio_write) {
NS_ERR("alloc_device: cache file not writeable/n");
err = -EINVAL;
goto err_close;
}
<2>:读文件
static ssize_t read_file(struct nandsim *ns, struct file *file, void *buf, size_t count, loff_t *pos)
{
mm_segment_t old_fs;
ssize_t tx;
int err, memalloc;
err = get_pages(ns, file, count, *pos);
if (err)
return err;
old_fs = get_fs();
set_fs(get_ds()); //将地址空间设置为内核空间,防止vfs_read返回失败
memalloc = set_memalloc();
tx = vfs_read(file, (char __user *)buf, count, pos);
clear_memalloc(memalloc);
set_fs(old_fs);
put_pages(ns);
return tx;
}
<3>:写文件
static ssize_t write_file(struct nandsim *ns, struct file *file, void *buf, size_t count, loff_t *pos)
{
mm_segment_t old_fs;
ssize_t tx;
int err, memalloc;
err = get_pages(ns, file, count, *pos);
if (err)
return err;
old_fs = get_fs();
set_fs(get_ds()); //#define get_ds() (KERNEL_DS)
memalloc = set_memalloc();
tx = vfs_write(file, (char __user *)buf, count, pos);
clear_memalloc(memalloc);
set_fs(old_fs);
put_pages(ns);
return tx;
}
/* * createfile.c * Author: Woody <[email protected]> * * Use kernel APIs to create a file * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * */ #include <linux/module.h> /* MODULE_LICENSE */ #include <linux/kernel.h> /* printk,pr_info */ #include <linux/errno.h> /* EINVAL,EAGAIN,etc. */ #include <linux/err.h> /* IS_ERR */ #include <linux/init.h> /* module_init */ #include <linux/delay.h> /* mdelay,msleep */ #include <linux/hrtimer.h> /* hrtimer APIs */ #include <linux/time.h> /* struct timespec */ #include <linux/device.h> /* device_create */ #include <linux/fs.h> #include <linux/slab.h> /* kzalloc */ #include <asm/uaccess.h> /* get_fs */ #include <linux/mutex.h> /* struct mutex */ struct kernel_test { /* Just for kernel test code */ wait_queue_head_t waitq; struct mutex test_lock; struct class *sys_print_class; struct device *dev; int rw_flag; int print_flag; }; static struct kernel_test *data; static ssize_t enable_show(struct device *dev, struct device_attribute *attr, char *buf) { int ret = 0; DECLARE_WAITQUEUE(wait, current); set_current_state(TASK_UNINTERRUPTIBLE); add_wait_queue(&data->waitq, &wait); if (data->rw_flag == 0) { printk("Begin to sched...>/n"); schedule(); } printk("@@@@@@@@@@@@Wake up the current/n"); remove_wait_queue(&data->waitq, &wait); set_current_state(TASK_RUNNING); ret = sprintf(buf, "%d/n", data->print_flag); data->rw_flag = 0; return ret; } static ssize_t enable_store( struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { sscanf(buf, "%d", &data->print_flag); data->rw_flag = 1; wake_up(&data->waitq); return size; } static DEVICE_ATTR(enable, 0644, enable_show, enable_store); static int open_file(void) { struct file * cfile; uint32_t err = 0; mm_segment_t old_fs; ssize_t tx; uint8_t buf[16] = "Hello World!"; loff_t pos = 0; cfile = filp_open("/kernel_test", O_CREAT | O_RDWR | O_LARGEFILE, 0644); if (IS_ERR(cfile)) return PTR_ERR(cfile); if (!cfile->f_op || (!cfile->f_op->read && !cfile->f_op->aio_read)) { printk("alloc_device: cache file not readable/n"); err = -EINVAL; goto err_close; } if (!cfile->f_op->write && !cfile->f_op->aio_write) { printk("alloc_device: cache file not writeable/n"); err = -EINVAL; goto err_close; } printk("Open the file /huyugui/log/n"); old_fs = get_fs(); set_fs(get_ds()); tx = vfs_write(cfile, (char __user *)buf, 16, &pos); set_fs(old_fs); err_close: filp_close(cfile, NULL); return err; } static int __init file_init_module(void) { int ret = 0; printk("[%s,%d]/n", __FUNCTION__, __LINE__); data = kzalloc(sizeof(struct kernel_test), GFP_KERNEL); if (data == NULL) { printk("[%s,%d]out of memory!/n", __FUNCTION__, __LINE__); return -ENOMEM; } mutex_init(&data->test_lock); init_waitqueue_head(&data->waitq); data->rw_flag = 0; /* when write new data,the rw_flag will be set to "1" */ data->sys_print_class = class_create(THIS_MODULE, "kernel_test"); if (IS_ERR(data->sys_print_class)) { ret = PTR_ERR(data->sys_print_class); goto fail; } else { printk("Create the /sys/class/kernel_test/n"); } data->dev = device_create(data->sys_print_class, NULL, MKDEV(255, 0), NULL, "file"); printk("Create the foder:/sys/class/kernel_test/file/n"); ret = device_create_file(data->dev, &dev_attr_enable); ret = open_file(); if (ret == 0) { printk("Create file successfully!/n"); } else { printk("Create file failed!/n"); } goto out; fail: kfree(data); out: return ret; } static void __exit file_cleanup_module(void) { printk("[%s,%d]/n", __FUNCTION__, __LINE__); device_remove_file(data->dev, &dev_attr_enable); device_destroy(data->sys_print_class, MKDEV(255, 0)); class_destroy(data->sys_print_class); kfree(data); /* free the memory when remove modules */ } module_init(file_init_module); module_exit(file_cleanup_module); MODULE_AUTHOR("Woody <[email protected]>"); MODULE_DESCRIPTION("Use Kernel APIs to create files"); MODULE_LICENSE("GPL");