zerons's Blog

For The Dream

chanllenge 06 misc device 2

zerons posted @ 2014年12月22日 11:02 in chanllenge , 624 阅读

在上一个文章里面, 提到file_operations 结构体一般只需要前面.owner .read .write三个域,

最开始我只初始化了这三个, 然后我的模块中read和write都没对offset进行特殊处理, 由内部自动处理

read 函数只是简单返回一个字符串"888888888888"

write 函数只是对比一下用户空间的输入是不是888888888888, 然后返回错误码或者是字节

于是, 写了一个测试文件

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

#define BUFSIZE 16

int main(int argc, char *argv[])
{
	int fd;
	int ret;
	char *path = "/dev/this";
	char buf[BUFSIZE];
	static char *test_str[] = {"888888888888", "8888888888888",
			"88888888888", "000000000000",
			"888888888888888888888888",
			(char *)0,
	};
	char **tmp = test_str;

	fd = open(path , O_RDWR);
	if (fd == -1) {
		printf("open %s error: %s\n", path, strerror(errno));
		exit(0);
	}

	memset(buf, '\0', BUFSIZE);

	ret = read(fd, buf, BUFSIZE);
	if (ret == -1)
		printf("read error: %s\n", strerror(errno));
	printf("return is %s\n", buf);
	lseek(fd, 0, SEEK_SET);

	while (*tmp) {
		ret = write(fd, *tmp, strlen(*tmp));
		if (ret == -1)
			printf("%s error: %s\n", *tmp, strerror(errno));
		else
			printf("%s successfully\n", *tmp);
		tmp++;
		lseek(fd, 0, SEEK_SET);
	}
	close(fd);
	return 0;
}

 

这个测试在模块中没有lseek的时候   系统会调用一个默认的lseek函数, 起初以为这个lseek函数确实做了些什么, 但是运行这个测试的时候, 传入匹配字串"888888888888"也返回错误码

 

于是在源码中找相应的代码, google了一下, 找到了如下

使用ftrace查看内核函数调用过程

# cd /sys/kernel/debug/tracing/

# echo 0 > tracing_on

# echo function_graph > current_tracer

# echo *seek* > set_ftrace_filter

# echo "test_pid"(测试程序的pid) > set_ftrace_pid

# echo 1 > tracing_on

之后运行测试程序 结束之后

# cat trace

结果显示, test中调用lseek系统调用, 然后实际调用的默认lseek是no_lseek函数, 这个函数只是简单的返回-ESPIPE, 并没有对文件位置进行操作.

 

在对普通文件读写的时候, 涉及到相应的文件系统, 比如我用的ext4, 在读写普通文件test.txt时

lseek的调用过程是

SyS_lseek() -> ext4_llseek() -> generic_file_llseek_size()


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter