Linux RTC駆動モデル分析のrtc-proc.c

8211 ワード

認識rtcノード
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);
}