在使用linuxptp的phc2sys程序的时候,有一种使用方式是:
phc2sys -d /dev/pps -s /dev/ptp -c CLOCK_REALTIME -m -O 0
这种方式会指定pps设置作为源来矫正系统时间,-s指定了ptp设备,作用是获取phc时间,phc时间提供绝对时间值,并不对矫正偏差产生作用。
如何通过设备名称来获取系统时间呢(gettime)?
首先需要进行初始化
ptp_qoriq_probe;// ptp_qoriq.c
ptp_qoriq_init(ptp_poriq,base,&ptp_qoriq_caps)
ptp_clock_register()//创建了ptp_clock ptp,并填充它的成员
ptp->clock.ops = ptp_clock_ops;
posix_clock_register(&ptp->clock, &ptp->dev)//创建 posix_clock
cdev_init(&clk->cdev, &posix_clock_file_operations)//用于初始化cdev的成员,并建立cdev和file_operations之间的连接
cdev->ops = fops;
cdev_device_add();向系统添加一个cdev
//至此 ptp->info->adjtime = ptp_qoriq_adjtime
ptp->info->enable = ptp_qoriq_enable
ptp->info->pps->cdev = pps_cdev_fops
ptp->clock.ops = ptp_clock_ops;
ptp->clock->cdev->ops = &posix_clock_file_operations
ptp->clock->dev = &ptp->dev
也就是posix_clock clk->dev = &ptp->dev
clk->ops = &posix_clock_file_operations
其次需要根据设备名称来open设备,进而获取或者修改系统时间。
例如通过-c指定的ptp设备,会执行如下过程
clock_add()
posix_clock_open//通过设备/dev/ptp*或者eth*,走下面不同的分支,返回clkid
phc_open//返回clkid
fd = open(phc,O_RDWR)//怎么对应上posix_clock_open
posix_clock_open(struct inode *inode, struct file *fp)//这部分为驱动代码posix-clock.c,file结构体由内核在打开文件时创建,这是 posix_clock_file_operations 的成员函数
clk->opt.open()//对应于ptp_clock_ops.open
ptp_open()//return 0;
fp->private_date = clk;//clk是posix_clock
FD_TO_CLOCKID(fd)//由文件描述符得到clkid
clock_gettime()------------------------以下为驱动代码
SYSCALL_DEFINE2(clock_gettime...)//posix-timers.c,内核态执行该函数
clockid_to_kclock()//clkid < 0 获取到clock_posix_dynamic
kc->clock_get()//使用这组函数进行时钟获取
pc_clock_gettime()
cd.clk->ops.clock_gettime
ptp_clock_gettime()
ptp->info->gettime64()
ptp_qoriq_caps.ptp_qoriq_gettime()
tmr_cnt_read()//读取寄存器
clock_adjtime(clkid,&tx)获取tx------------------------以下为驱动代码
syscall(__NR_clock_adjtime,id,tx);//用户态执行系统调用,__NR_clock_adjtime是系统调用号,内核中有与系统调用号对应的系统调用表
SYSCALL_DEFINE2(clock_adjtime, const clockid_t, which_clock, struct timex __user *, utx)//posix-timers.c,内核态执行该函数
do_clock_adjtime()
clockid_to_kclock()//clkid <0 (打印出来看就是负的) 获取到clock_posix_dynamic,选择了一组函数
kc->clock_adj()//使用这组函数进行频率调整
pc_clock_adjtime(id,tx)
get_clock_desc(id,&cd)//根据id获得fd,根据fd获取posix_clock, posix_clock = fp->private_date
fget(clockid_to_fd(id))//由fd获取到file结构体
cd->clk = get_posix_clock(fp)
cd.clk->ops.clock_adjtime//对应的就是 ptp_clock_ops.clock_adjtime = ptp_clock_adjtime
ptp_clock_adjtime()//根据posix_clock得到ptp_clock
ptp->info->adjtime()//info对应的是ptp_qoriq->caps
ptp_qoriq_caps.ptp_qoriq_adjtime()//ptp_qoriq_caps 是全局变量
tmr_cnt_write()写寄存器----最底层
在直接使用了posix_clock_file_operations.posix_clock_open函数之后,想要修改时间,通过系统调用执行到kc、 ptp_clock_ops ptp_qoriq_caps 写寄存器。
posix_clock_file_operations除了open之外的函数使用的都是 ptp_clock_ops的成员函数。
如果是系统时钟(CLOCK_REALTIME),则执行一下过程
clock_add()
posix_clock_open()//该函数返回clockid_t, 如果是CLOKC_REALTIME则直接返回CLOKC_REALTIME = 0
在使用clock_gettime(sysclk, &tdst1)时的调用栈
clock_gettime(sysclk, &tdst1)
SYSCALL_DEFINE2(clock_gettime...)//posix-timers.c,内核态执行该函数
clockid_to_kclock()//clkid = 0 获取到clock_realtime,选择了一组函数
kc->clock_get()//使用这组函数进行时钟获取
posix_get_realtime_get
ktime_get_real_ts64//获取系统时间