kernel_fgets 内核态按行读取文件
kernel_fgets
1、kernel_fgets 说明
(等效于用户态fgets,若不太明白,可参考fgets函数)
函数说明:内核态从fp文件描述符里,读取最大max_size-1字节的一行字符串,并存储于buf中。
返回值:正确情况下返回buf指针,error情况下返回NULL
参数说明:buf,读取的字符串存储于buf中。max_size,最大读取的字节数+1。fp,内核态filp_open打开文件后获取的文件描述符。
char *kernel_fgets(char *buf, int max_size, struct file *fp) { int i = 0; int read_size; if(0 > max_size) { printk(KERN_EMERG "read max_size invalid\n"); return NULL; } read_size = vfs_read(fp, buf, max_size, &(fp->f_pos)); if(1 > read_size) { return NULL; } while(buf[i++] != '\n' && i < read_size); buf[i-1] = '\0'; fp->f_pos += i-read_size; return buf; }
2、API使用示例代码:
#include <linux/module.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/uaccess.h> #include <linux/string.h> mm_segment_t fs; char buf_0[28] = "0"; char *kernel_fgets(char *buf, int max_size, struct file *fp) { int i = 0; int read_size; if(0 > max_size) { printk(KERN_EMERG "read max_size invalid\n"); return NULL; } read_size = vfs_read(fp, buf, max_size, &(fp->f_pos)); if(1 > read_size) { return NULL; } while(buf[i++] != '\n' && i < read_size); buf[i-1] = '\0'; fp->f_pos += i-read_size; return buf; } static int read_line(struct file *fp, char *buf1, int buf1_len, loff_t *point_pos) { int i = 0; int read_size; printk(KERN_EMERG "read i=%d pos=%d fp-f_ops=%d--%d\n", i, (int)*point_pos, (int)fp->f_pos, __LINE__); read_size = vfs_read(fp, buf1, buf1_len, point_pos); if(read_size < 1) { printk(KERN_EMERG "read end.\n"); return 0; } while(buf1[i++] != '\n' && i < read_size); if(i < read_size) { buf1[i] = '\0'; //if(0 == strcmp(" dialer number *999# autodial", buf1)) if(NULL != strstr(buf1, "dialer number *999# autodial")) { *point_pos = *point_pos - read_size; printk(KERN_EMERG "read i=%d pos=%d\n", i, (int)*point_pos); vfs_write(fp, " ", 28, point_pos); } *point_pos += i-read_size; } printk(KERN_EMERG "read i=%d pos=%d--%d\n", i, (int)*point_pos, __LINE__); return i; } int __init hello_init(void) { char buf1[100]; struct file *fp; loff_t pos; int read_size; int read_line = 10; printk(KERN_EMERG "hello enter\n"); #if 0 fp = filp_open("/root/test_ko/12345.cfg", O_RDWR, 0); if (IS_ERR(fp)) { printk(KERN_EMERG "create file error\n"); return -1; } fs = get_fs(); set_fs(KERNEL_DS); pos = fp->f_pos; while(1) { memset(buf1, 0, sizeof(buf1)); //read_size = vfs_read(fp, buf1, sizeof(buf1), &pos); //printk("read ret:%d, pos:%ld\n", read_size, pos); read_size = read_line(fp, buf1, sizeof(buf1), &pos); if(read_size < 1) { printk(KERN_EMERG "read end.\n"); filp_close(fp, NULL); set_fs(fs); return 0; } printk(KERN_EMERG "%s", buf1); } filp_close(fp, NULL); set_fs(fs); #endif fp = filp_open("/root/test_ko/xxx.txt", O_RDWR, 0); if (IS_ERR(fp)) { printk(KERN_EMERG "create file error\n"); return -1; } fs = get_fs(); set_fs(KERNEL_DS); while(read_line--) { memset(buf1, 0, sizeof(buf1)); if ( NULL == kernel_fgets(buf1, 100, fp)) { printk(KERN_EMERG "read end.\n"); filp_close(fp, NULL); } printk(KERN_EMERG "%s", buf1); } filp_close(fp, NULL); set_fs(fs); return 0; } void __exit hello_exit(void) { printk(KERN_EMERG "hello exit\n"); } MODULE_LICENSE("GPL"); module_init(hello_init); module_exit(hello_exit);