当前位置: 技术问答>linux和unix
LINUX中date在内核实现代码在何处?请指点!
来源: 互联网 发布时间:2015-06-04
本文导语: 如提 | 给你一个通用的方法吧。 首先用strace命令分析date所用的系统调用 #strace date > output.txt 2>&1 然后看看output.txt的内容 execve("/bin/date", ["date"], [/* 21 vars */]) = 0 //Shell fork然后用exec执...
如提
|
给你一个通用的方法吧。
首先用strace命令分析date所用的系统调用
#strace date > output.txt 2>&1
然后看看output.txt的内容
execve("/bin/date", ["date"], [/* 21 vars */]) = 0 //Shell fork然后用exec执行命令
...... //打开动态链接库,并且读取相关的区域配置文件
time([1071706012]) = 1071706012 //最重要的一行,告诉你date所用的系统调用
...... //根据TZ算出正确的时区时间并打印出来
知道了系统调用就好办了
#cd /usr/src/linux-2.4
#grep -r "sys_time" *
查找的结果如下:
abi/svr4/misc.c: return sys_time(0);
arch/i386/kernel/entry.S: .long SYMBOL_NAME(sys_time)
arch/i386/kernel/entry.S: .long SYMBOL_NAME(sys_times)
drivers/sound/.depend:sys_timer.o: sys_timer.c
drivers/sound/Makefile: sequencer.o sequencer_syms.o sound_timer.o sys_timer.o
drivers/sound/sys_timer.c: * sound/sys_timer.c
include/linux/modules/ksyms.ver:#define __ver_sys_time _ver_str(1242c40e)
include/linux/modules/ksyms.ver:#define sys_time _set_ver(sys_time)
include/linux/syscall.h:extern asmlinkage long sys_time(int * tloc);
kernel/ksyms.c:EXPORT_SYMBOL(sys_time);
kernel/sys.c:asmlinkage long sys_times(struct tms * tbuf)
kernel/time.c: * sys_time() can be implemented in user-level using
kernel/time.c:asmlinkage long sys_time(int * tloc)
可以看出,sys_time在kernel/time.c中,然后你在看这个文件,就会知道具体的实现方式是:
asmlinkage long sys_time(int * tloc)
{
int i;
/* SMP: This is fairly trivial. We grab CURRENT_TIME and
stuff it to user space. No side effects */
i = CURRENT_TIME;
if (tloc) {
if (put_user(i,tloc))
i = -EFAULT;
}
return i;
}
/*
* sys_stime() can be implemented in user-level using
* sys_settimeofday(). Is this for backwards compatibility? If so,
* why not move it into the appropriate arch directory (for those
* architectures that need it).
*/
asmlinkage long sys_stime(int * tptr)
{
int value;
if (!capable(CAP_SYS_TIME))
return -EPERM;
if (get_user(value, tptr))
return -EFAULT;
write_lock_irq(&xtime_lock);
xtime.tv_sec = value;
xtime.tv_usec = 0;
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
time_esterror = NTP_PHASE_LIMIT;
write_unlock_irq(&xtime_lock);
return 0;
}
首先用strace命令分析date所用的系统调用
#strace date > output.txt 2>&1
然后看看output.txt的内容
execve("/bin/date", ["date"], [/* 21 vars */]) = 0 //Shell fork然后用exec执行命令
...... //打开动态链接库,并且读取相关的区域配置文件
time([1071706012]) = 1071706012 //最重要的一行,告诉你date所用的系统调用
...... //根据TZ算出正确的时区时间并打印出来
知道了系统调用就好办了
#cd /usr/src/linux-2.4
#grep -r "sys_time" *
查找的结果如下:
abi/svr4/misc.c: return sys_time(0);
arch/i386/kernel/entry.S: .long SYMBOL_NAME(sys_time)
arch/i386/kernel/entry.S: .long SYMBOL_NAME(sys_times)
drivers/sound/.depend:sys_timer.o: sys_timer.c
drivers/sound/Makefile: sequencer.o sequencer_syms.o sound_timer.o sys_timer.o
drivers/sound/sys_timer.c: * sound/sys_timer.c
include/linux/modules/ksyms.ver:#define __ver_sys_time _ver_str(1242c40e)
include/linux/modules/ksyms.ver:#define sys_time _set_ver(sys_time)
include/linux/syscall.h:extern asmlinkage long sys_time(int * tloc);
kernel/ksyms.c:EXPORT_SYMBOL(sys_time);
kernel/sys.c:asmlinkage long sys_times(struct tms * tbuf)
kernel/time.c: * sys_time() can be implemented in user-level using
kernel/time.c:asmlinkage long sys_time(int * tloc)
可以看出,sys_time在kernel/time.c中,然后你在看这个文件,就会知道具体的实现方式是:
asmlinkage long sys_time(int * tloc)
{
int i;
/* SMP: This is fairly trivial. We grab CURRENT_TIME and
stuff it to user space. No side effects */
i = CURRENT_TIME;
if (tloc) {
if (put_user(i,tloc))
i = -EFAULT;
}
return i;
}
/*
* sys_stime() can be implemented in user-level using
* sys_settimeofday(). Is this for backwards compatibility? If so,
* why not move it into the appropriate arch directory (for those
* architectures that need it).
*/
asmlinkage long sys_stime(int * tptr)
{
int value;
if (!capable(CAP_SYS_TIME))
return -EPERM;
if (get_user(value, tptr))
return -EFAULT;
write_lock_irq(&xtime_lock);
xtime.tv_sec = value;
xtime.tv_usec = 0;
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
time_maxerror = NTP_PHASE_LIMIT;
time_esterror = NTP_PHASE_LIMIT;
write_unlock_irq(&xtime_lock);
return 0;
}
|
例子代码如下:
/* date.c */
#include
#include
static const char invalid_date[] = "Invalid date %sn";
int main(int argc, char * argv[])
{
time_t tm;
struct tm tm_time;
time(&tm);
memcpy(&tm_time, localtime(&tm), sizeof(tm_time));
if (argc > 1) {
int nr;
nr = sscanf(argv[1], "%2d%2d%2d%2d%d",
&(tm_time.tm_mon),
&(tm_time.tm_mday),
&(tm_time.tm_hour),
&(tm_time.tm_min), &(tm_time.tm_year));
if (nr 5) {
fprintf(stderr, invalid_date, argv[1]);
return(0);
}
/* correct for century - minor Y2K problem here? */
if (tm_time.tm_year >= 1900)
tm_time.tm_year -= 1900;
/* adjust date */
tm_time.tm_mon -= 1;
if((tm = mktime(&tm_time))
/* date.c */
#include
#include
static const char invalid_date[] = "Invalid date %sn";
int main(int argc, char * argv[])
{
time_t tm;
struct tm tm_time;
time(&tm);
memcpy(&tm_time, localtime(&tm), sizeof(tm_time));
if (argc > 1) {
int nr;
nr = sscanf(argv[1], "%2d%2d%2d%2d%d",
&(tm_time.tm_mon),
&(tm_time.tm_mday),
&(tm_time.tm_hour),
&(tm_time.tm_min), &(tm_time.tm_year));
if (nr 5) {
fprintf(stderr, invalid_date, argv[1]);
return(0);
}
/* correct for century - minor Y2K problem here? */
if (tm_time.tm_year >= 1900)
tm_time.tm_year -= 1900;
/* adjust date */
tm_time.tm_mon -= 1;
if((tm = mktime(&tm_time))