Linux RTC駆動モデル分析のrtc-proc.c
8211 ワード
認識rtcノード
Procの下のrtcノードの位置は、/proc/driver/rtcです.このノードは、現在の時間、現在の日付、alarmの時間、日付、alarmが使用可能かどうかなどの詳細を明確に表示できます.コードを分析する前に認識しておきます.
rtc-proc.c
kmconfigでは、次のように構成の詳細を表示できます.
以下、rtc_proc_fopsの構造:
システムがこのファイルを開くとopen関数が呼び出されます.これはprocファイルシステムの実行プロセスで、この部分の重点ではありません.スキップします.
Procの下のrtcノードの位置は、/proc/driver/rtcです.このノードは、現在の時間、現在の日付、alarmの時間、日付、alarmが使用可能かどうかなどの詳細を明確に表示できます.コードを分析する前に認識しておきます.
root@test:test # cat /proc/driver/rtc
rtc_time : 06:25:56 //
rtc_date : 2012-01-12 //
alrm_time : 05:04:36 //alarm
alrm_date : 2033-04-23 //alarm
alarm_IRQ : no //alarm IRQ
alrm_pending : no //alarm pending
update IRQ enabled : no //update IRQ
periodic IRQ enabled : no //periodic( )IRQ
periodic IRQ frequency : 1 //periodic IRQ
max user IRQ frequency : 64 //periodic IRQ
24hr : yes //24
rtcノードを認識した後、コードを分析する.rtc-proc.c
void rtc_proc_add_device(struct rtc_device *rtc)
{
if (is_rtc_hctosys(rtc)) // rtc
proc_create_data("driver/rtc", 0, NULL, &rtc_proc_fops, rtc); // , proc
}
は、次のようにis_である.rtc_hctosysの実装:#if defined(CONFIG_RTC_HCTOSYS_DEVICE)
static bool is_rtc_hctosys(struct rtc_device *rtc)
{
int size;
char name[NAME_SIZE];
size = scnprintf(name, NAME_SIZE, "rtc%d", rtc->id);
if (size > NAME_SIZE)
return false;
return !strncmp(name, CONFIG_RTC_HCTOSYS_DEVICE, NAME_SIZE); // rtc config 。
}
#else
static bool is_rtc_hctosys(struct rtc_device *rtc)
{
return (rtc->id == 0);
}
#endif
カーネル構成:CONFIG_RTC_HCTOSYS_DEVICEが決定しました.kmconfigでは、次のように構成の詳細を表示できます.
CONFIG_RTC_HCTOSYS_DEVICE:
│ The RTC device that will be used to (re)initialize the system
│ clock, usually rtc0. Initialization is done when the system
│ starts up, and when it resumes from a low power state. This
│ device should record time in UTC, since the kernel won't do
│ timezone correction.
│
│ The driver for this RTC device must be loaded before late_initcall
│ functions run, so it must usually be statically linked.
│
│ This clock should be battery-backed, so that it reads the correct
│ time when the system boots from a power-off state. Otherwise, your
│ system will need an external clock source (like an NTP server).
│
│ If the clock you specify here is not battery backed, it may still
│ be useful to reinitialize system time when resuming from system
│ sleep states. Do not specify an RTC here unless it stays powered
│ during all this system's supported sleep states.
は、システムが起動すると、rtcデバイスが通常、システム時間を設定するために使用されることを概ね認識する.以下、rtc_proc_fopsの構造:
static const struct file_operations rtc_proc_fops = {
.open = rtc_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = rtc_proc_release,
};
システムがこのファイルを開くとopen関数が呼び出されます.これはprocファイルシステムの実行プロセスで、この部分の重点ではありません.スキップします.
static int rtc_proc_open(struct inode *inode, struct file *file)
{
int ret;
struct rtc_device *rtc = PDE_DATA(inode); // rtc
if (!try_module_get(THIS_MODULE))
return -ENODEV;
ret = single_open(file, rtc_proc_show, rtc); //
if (ret)
module_put(THIS_MODULE);
return ret;
}
cat/proc/driver/rtcのときread関数に呼び出され、最終的にrtc_に呼び出されるproc_show関数.static int rtc_proc_show(struct seq_file *seq, void *offset)
{
int err;
struct rtc_device *rtc = seq->private;
const struct rtc_class_ops *ops = rtc->ops;
struct rtc_wkalrm alrm;
struct rtc_time tm;
err = rtc_read_time(rtc, &tm); //
if (err == 0) {
seq_printf(seq,
"rtc_time\t: %02d:%02d:%02d
"
"rtc_date\t: %04d-%02d-%02d
",
tm.tm_hour, tm.tm_min, tm.tm_sec,
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
}
err = rtc_read_alarm(rtc, &alrm); // alarm
if (err == 0) {
seq_printf(seq, "alrm_time\t: "); //alarm
if ((unsigned int)alrm.time.tm_hour <= 24)
seq_printf(seq, "%02d:", alrm.time.tm_hour);
else
seq_printf(seq, "**:");
if ((unsigned int)alrm.time.tm_min <= 59)
seq_printf(seq, "%02d:", alrm.time.tm_min);
else
seq_printf(seq, "**:");
if ((unsigned int)alrm.time.tm_sec <= 59)
seq_printf(seq, "%02d
", alrm.time.tm_sec);
else
seq_printf(seq, "**
");
seq_printf(seq, "alrm_date\t: "); //alarm
if ((unsigned int)alrm.time.tm_year <= 200)
seq_printf(seq, "%04d-", alrm.time.tm_year + 1900);
else
seq_printf(seq, "****-");
if ((unsigned int)alrm.time.tm_mon <= 11)
seq_printf(seq, "%02d-", alrm.time.tm_mon + 1);
else
seq_printf(seq, "**-");
if (alrm.time.tm_mday && (unsigned int)alrm.time.tm_mday <= 31)
seq_printf(seq, "%02d
", alrm.time.tm_mday);
else
seq_printf(seq, "**
");
seq_printf(seq, "alarm_IRQ\t: %s
",
alrm.enabled ? "yes" : "no"); //alarm IRQ
seq_printf(seq, "alrm_pending\t: %s
",
alrm.pending ? "yes" : "no"); //alarm pending
seq_printf(seq, "update IRQ enabled\t: %s
",
(rtc->uie_rtctimer.enabled) ? "yes" : "no"); //update IRQ
seq_printf(seq, "periodic IRQ enabled\t: %s
",
(rtc->pie_enabled) ? "yes" : "no"); //periodic IRQ
seq_printf(seq, "periodic IRQ frequency\t: %d
",
rtc->irq_freq); //periodic IRQ
seq_printf(seq, "max user IRQ frequency\t: %d
", //
rtc->max_user_freq);
}
seq_printf(seq, "24hr\t\t: yes
");
if (ops->proc)
ops->proc(rtc->dev.parent, seq); // proc, 。
return 0;
}
は、/proc/driver/rtcをアンインストールするには、次の方法を使用します.void rtc_proc_del_device(struct rtc_device *rtc)
{
if (is_rtc_hctosys(rtc))
remove_proc_entry("driver/rtc", NULL);
}