#include
#include
#include
#include
//#include
#define procfs_name "xtime"
struct proc_dir_entry
*clock_proc_file;
static int procfile_read(char *page,char
**start,off_t offset,int count,int *eof,void *data)
{
int ret;
struct timespec x_time=current_kernel_time();
//struct timeval tv;
//do_gettimeofday(&tv);
printk(KERN_INFO"procfile_read(/proc/%s)called\n",procfs_name);
//判断offset,这是很重要的,因为来自库的标准读函数将持续发布读系统调用直到内核答复没有更多信息
//或它的缓冲区被填满。
if(offset>0){
ret=0;
}
else{
ret=sprintf(page,"tv_sec:%ld\ttv_nsec:%ld\n",x_time.tv_sec,x_time.tv_nsec);
}
return ret;
}
static int __init proc_init(void){
clock_proc_file=create_proc_entry(procfs_name,0644,NULL);
if(clock_proc_file==NULL){
remove_proc_entry(procfs_name,NULL);
printk(KERN_ALERT"Error:Could not initialize
/proc/%s\n",procfs_name);
return -ENOMEM;
}
clock_proc_file->read_proc=procfile_read;
clock_proc_file->owner=THIS_MODULE;
clock_proc_file->mode=S_IFREG|S_IRUGO;
clock_proc_file->uid=0;
clock_proc_file->gid=0;
printk(KERN_INFO"/proc/%s created\n",procfs_name);
return 0;
}
static void __exit proc_exit(void){
remove_proc_entry(procfs_name,NULL);
printk(KERN_INFO"/proc/%s removed\n",procfs_name);
}
module_init(proc_init);
module_exit(proc_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("WuYang");
proc_root未定义(未找到需添加的头文件,搜索结果有的说也没找到办法,目前只能设为NULL)
WARNING: "xtime" [/home/wuyang/procfs.ko]
undefined!
xtime是全局变量,在linux/time.h中有
extern struct timespec
xtime;但是在程序中并不能直接使用(不知道什么原因)。一种方法是利用current_kernel_time()函数来得到xtime。
函数定义如下:struct timespec current_kernel_time(void)
528{
529 struct timespec now;
530 unsigned long seq;
531
532 do {
533 seq = read_seqbegin(&xtime_lock); 534
535 now = xtime_cache;
536 } while (read_seqretry(&xtime_lock, seq));
537
538 return now;
539}
可用cat等命令测试或者自己编写小程序,如下:
#include
#include
#include
int main(){
FILE *fp;
struct timeval time;
char buffer[40];
fp=fopen("/proc/xtime","r");
fgets(buffer,40,fp);
//printf("%d\nsizeof(char)=%d\nsize of
buffer=%d\n",n,sizeof(char),strlen(buffer));
gettimeofday(&time,NULL);
printf("%stv_sec:%ld\ttv_usec:%ld\n",buffer,time.tv_sec,time.tv_usec);
}
奇怪的是buffer小到一定时(比如50)输出就会有乱码,不知道什么原因fread用起来还挺复杂!
加上输出strlen(buffer)当设为50时输出为55设为55时输出为60100时,输出为21(21为正确长度)现改由fgets实现
另外,xtime时timespec解构体,其定义为:
14struct timespec {
15 time_t
tv_sec; 16 long tv_nsec; }
通过gettimeofday()得到的时timeval结构体,定义为:
20struct timeval {
21 time_t tv_sec; 22 suseconds_t tv_usec; }
ret=sprintf(page,"%ld\t%ld",x_time.tv_sec,x_time.tv_nsec);
发现sprintf可以直接将内核数据输出到用户空间缓冲区,而不用copy_to_user!
更正:此处的page为内核空间缓冲区,无需copy_to_user
但是不把数据放到用户空间缓冲区,用户程序怎么取得该数据呢?!
data为proc_dir_entry的私有数据指针,data指向的也即是该proc文件的缓冲区(数据存储区),初始化时为结构体中的data指针初始化后,read_proc和write_proc函数参数中的data指针会自动传递为结构体中初始化的指针值。