1,kernel
#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/miscdevice.h> #define MISC_NAME "miscdriver" #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; #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 "); return -1; } klog_pos = 0; sprintf(klog_ack->io_buff, "filp_open ok "); } 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 "); } if(klog_cmd->cmd_type == 3) { //close file filp_close(klog_fp, NULL); klog_fp = NULL; sprintf(klog_ack->io_buff, "filp_close ok "); } return 0; } #endif char user_cmd[IO_CMD_LEN] = {0}; char out_str[IO_CMD_LEN] = {0}; static int misc_open(struct inode *inode, struct file *file) { printk("misc_open "); return 0; } static int misc_ioctl( struct file *file, unsigned int cmd, unsigned long arg) { printk("misc_ioctl: %d ", 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 ssize_t misc_write(struct file *filp, const char __user *buf, size_t size, loff_t *ppos) { int ret; if(IO_CMD_LEN <= size) return 0; if (copy_from_user(user_cmd, buf, size)) ret = - EFAULT; user_cmd[size] = 0; printk(KERN_INFO "written %d bytes: %s ", size, user_cmd); return 0; } static const struct file_operations misc_fops = { .owner = THIS_MODULE, .open = misc_open, .write = misc_write, .unlocked_ioctl = misc_ioctl, }; static struct miscdevice misc_dev = { .minor = MISC_DYNAMIC_MINOR, .name = MISC_NAME, .fops = &misc_fops, }; static int __init misc_init(void) { int ret; ret = misc_register(&misc_dev); if (ret) { printk("misc_register error "); return ret; } return 0; } static void __exit misc_exit(void) { misc_deregister(&misc_dev); } module_init(misc_init); module_exit(misc_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("derek");
2,app
#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; #if 0 int main() { int fd; int ret = 0; fd = open("/dev/miscdriver", O_RDWR); if( fd < 0 ) { printf("open miscdriver WRONG! "); 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 ", ret, cmd_info.io_buff); for(int i = 0; i < 10; i++) { sprintf(cmd_info.io_buff, "%d: ============================== ", 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 ", ret, cmd_info.io_buff); } cmd_info.cmd_type = 3; ret = ioctl(fd, 0, &cmd_info); printf("close: ret=%d rdata:%s ", ret, cmd_info.io_buff); close(fd); return 0; } #else int main() { int fd; int ret = 0; char buf[]="this is a example for character devices driver by derek!"; fd = open("/dev/miscdriver", O_RDWR); if( fd < 0 ) { printf("open miscdriver WRONG! "); return 0; } ret = write(fd, buf, sizeof(buf)); printf("write: ret=%d ", ret); close(fd); return 0; } #endif