| ÂÛ̳ע²á| ¼ÓÈëÊÕ²Ø | ÉèΪÊ×Ò³| RSS
Google
Äúµ±Ç°µÄλÖãºÊ×Ò³ > LinuxƵµÀ > Linux¿ª·¢Çø > ÄÚºËÑо¿

¶¨Ê±Æ÷

ʱ¼ä£º2005-12-01 12:54:54  À´Ô´£º  ×÷Õߣº
£
4. ´¦ÀíÓû§½ø³Ì·¢³öµÄʱ¼äϵͳµ÷Óá£
5. ¶ÔϵͳijЩ²¿·ÖÌṩ¼àÊÓ¶¨Ê±Æ÷¡£
ÆäÖУ¬µÚÒ»ÏÄÜÊÇËùÓÐOS¶¼±ØÐëʵÏֵĻù´¡¹¦ÄÜ£¬ËüÊÇOSÄں˵ÄÔËÐлù´¡¡£Í¨³£ÓÐÈýÖÖ·½·¨¿ÉÓÃÀ´Î¬»¤ÏµÍ³µÄʱ¼äÓëÈÕÆÚ£º£¨1£©
×î¼òµ¥µÄÒ»ÖÖ·½·¨¾ÍÊÇÓÃÒ»¸ö64λµÄ¼ÆÊýÆ÷À´¶ÔʱÖӵδð½øÐмÆÊý¡££¨2£©µÚ¶þÖÖ·½·¨¾ÍÊÇÓÃÒ»¸ö32λ¼ÆÊýÆ÷À´¶ÔÃë½øÐмÆÊý¡£ÓÃÒ»
¸ö32λµÄ¸¨Öú¼ÆÊýÆ÷À´¶ÔʱÖӵδð¼ÆÊýÖ±ÖÁÀÛ¼ÆÒ»ÃëΪֹ¡£ÒòΪ232³¬¹ý136Ä꣬Òò´ËÕâÖÖ·½·¨Ö±ÖÁ22ÊÀ¼Í¶¼¿ÉÒÔ¹¤×÷µÃºÜ
ºÃ¡££¨3£©µÚÈýÖÖ·½·¨Ò²Êǰ´µÎ´ð½øÐмÆÊý£¬µ«È´ÊÇÏà¶ÔÓÚϵͳÆô¶¯ÒÔÀ´µÄµÎ´ð´ÎÊý£¬¶ø²»ÊÇÏà¶ÔÓÚÒ»¸öÈ·¶¨µÄÍⲿʱ¿Ì¡£µ±¶Áºó±¸
ʱÖÓ£¨ÈçRTC£©»òÓû§ÊäÈëʵ¼Êʱ¼äʱ£¬¸ù¾Ýµ±Ç°µÄµÎ´ð´ÎÊý¼ÆËãϵͳµ±Ç°Ê±¼ä¡£
UNIXÀàµÄOSͨ³£¶¼²ÉÓõÚÈýÖÖ·½·¨À´Î¬»¤ÏµÍ³µÄʱ¼äÓëÈÕÆÚ¡£

7£®4£®1 Linux¶ÔʱÖÓÖжϵijõʼ»¯
Linux¶ÔʱÖÓÖжϵijõʼ»¯ÊÇ·ÖΪ¼¸¸ö²½ÖèÀ´½øÐеģº£¨1£©Ê×ÏÈ£¬ÓÉinit_IRQ()º¯Êýͨ¹ýµ÷ÓÃinit_ISA_IRQ()º¯Êý¶ÔÖжÏÏòÁ¿
32¡«256Ëù¶ÔÓ¦µÄÖжÏÏòÁ¿ÃèÊö·û½øÐгõʼ»¯ÉèÖá£ÏÔÈ»£¬ÕâÆäÖÐÒ²¾Í°ÑIRQ0£¨Ò²¼´ÖжÏÏòÁ¿32£©µÄÖжÏÏòÁ¿ÃèÊö·û³õʼ»¯
ÁË¡££¨2£©È»ºó£¬init_IRQ()º¯ÊýÉèÖÃÖжÏÏòÁ¿32¡«256Ïà¶ÔÓ¦µÄÖжÏÃÅ¡££¨3£©init_IRQ()º¯Êý¶ÔPIT½øÐгõʼ»¯±à
³Ì£»£¨4£©sched_init()º¯Êý¶Ô¼ÆÊýÆ÷¡¢Ê±¼äÖжϵÄBottom Half½øÐгõʼ»¯¡££¨5£©×îºó£¬ÓÉtime_init()º¯Êý¶ÔLinuxÄں˵Ä
ʱÖÓÖжϻúÖÆ½øÐгõʼ»¯¡£ÕâÈý¸ö³õʼ»¯º¯Êý¶¼ÊÇÓÉinit/main.cÎļþÖеÄstart_kernel()º¯Êýµ÷Óõģ¬ÈçÏ£º
asmlinkage void __init start_kernel()
{
¡­
trap_init();
init_IRQ();
sched_init();
time_init();
softirq_init();
¡­
}

(1)init_IRQ()º¯Êý¶Ô8254 PITµÄ³õʼ»¯±à³Ì
º¯Êýinit_IRQ()º¯ÊýÔÚÍê³ÉÖжÏÃŵijõʼ»¯ºó£¬¾Í¶Ô8254 PIT½øÐгõʼ»¯±à³ÌÉèÖã¬ÉèÖõIJ½ÖèÈçÏ£º£¨1£©ÉèÖÃ8254 PITµÄ¿Ø
ÖÆ¼Ä´æÆ÷£¨¶Ë¿Ú0x43£©µÄֵΪ¡°01100100¡±£¬Ò²¼´Ñ¡ÔñͨµÀ0¡¢ÏȶÁдLSBÔÙ¶ÁдMSB¡¢¹¤×÷ģʽ2¡¢¶þ½øÖÆ´æ´¢¸ñʽ¡££¨2£©½«ºê
LATCHµÄֵдÈëͨµÀ0µÄ¼ÆÊýÆ÷ÖУ¨¶Ë¿Ú0x40£©£¬×¢ÒâÒªÏÈдLATCHµÄLSB£¬ÔÙдLATCHµÄ¸ß×Ö½Ú¡£ÆäÔ´ÂëÈçÏÂËùʾ£¨arch/i386/
kernel/i8259.c£©£º
void __init init_IRQ(void)
{
¡­¡­
/*
* Set the clock to HZ Hz, we already have a valid
* vector now:
*/
outb_p(0x34,0x43); /* binary, mode 2, LSB/MSB, ch 0 */
outb_p(LATCH & 0xff , 0x40); /* LSB */
outb(LATCH >> 8 , 0x40); /* MSB */
¡­¡­
}

£¨2£©sched_init()¶Ô¶¨Ê±Æ÷»úÖÆºÍʱÖÓÖжϵÄBottom HalfµÄ³õʼ»¯
º¯Êýsched_init()ÖÐÓëʱ¼äÏà¹ØµÄ³õʼ»¯¹ý³ÌÖ÷ÒªÓÐÁ½²½£º£¨1£©µ÷ÓÃinit_timervecs()º¯Êý³õʼ»¯Äں˶¨Ê±Æ÷»úÖÆ£»£¨2£©µ÷
ÓÃinit_bh()º¯Êý½«BHÏòÁ¿TIMER_BH¡¢TQUEUE_BHºÍIMMEDIATE_BHËù¶ÔÓ¦µÄBHº¯Êý·Ö±ðÉèÖóÉtimer_bh()¡¢tqueue_bh()ºÍ
immediate_bh()º¯Êý¡£ÈçÏÂËùʾ£¨kernel/sched.c£©£º
void __init sched_init(void)
{
¡­¡­
init_timervecs();

init_bh(TIMER_BH, timer_bh);
init_bh(TQUEUE_BH, tqueue_bh);
init_bh(IMMEDIATE_BH, immediate_bh);
¡­¡­
}

£¨3£©time_init()º¯Êý¶ÔÄÚºËʱÖÓÖжϻúÖÆµÄ³õʼ»¯
Ç°ÃæÁ½¸öº¯ÊýËù½øÐеijõʼ»¯²½Öè¶¼ÊÇΪʱ¼äÖжϻúÖÆ×öºÃ×¼±¸¶øÒÑ¡£ÔÚÖ´ÐÐÍêinit_IRQ()º¯ÊýºÍsched_init()º¯Êýºó£¬CPUÒÑ
¾­¿ÉÒÔΪIRQ0ÉϵÄʱÖÓÖжϽøÐзþÎñÁË£¬ÒòΪIRQ0Ëù¶ÔÓ¦µÄÖжÏÃÅÒѾ­±»ÉèÖúÃÖ¸ÏòÖжϷþÎñº¯ÊýIRQ0x20_interrupt()¡£µ«ÊÇ
ÓÉÓÚ´ËʱÖжÏÏòÁ¿0x20µÄÖжÏÏòÁ¿ÃèÊö·ûirq_desc£Û0£Ý»¹ÊÇ´¦ÓÚ³õʼ״̬£¨Æästatus³ÉÔ±µÄֵΪIRQ_DISABLED£©£¬²¢Î´¹Ò½ÓÈÎ
ºÎ¾ßÌåµÄÖжϷþÎñÃèÊö·û£¬Òò´ËÕâʱCPU¶ÔIRQ0µÄÖжϷþÎñ²¢Ã»ÓÐÈκξßÌåÒâÒ壬¶øÖ»Êǰ´Õչ涨µÄÁ÷³Ì¿ÕÅÜÒ»ÌË¡£µ«Êǵ±CPUÖ´ÐÐ
Íêtime_init()º¯Êýºó£¬ÇéÐξʹó²»Ò»ÑùÁË¡£
º¯Êýtime_init()Ö÷Òª×öÈý¼þÊ£º£¨1£©´ÓRTCÖлñÈ¡ÄÚºËÆô¶¯Ê±µÄʱ¼äÓëÈÕÆÚ£»£¨2£©ÔÚCPUÓÐTSCµÄÇé¿öÏÂУ׼TSC£¬ÒÔ±ãΪºóÃæ
ʹÓÃTSC×öºÃ×¼±¸£»£¨3£©ÔÚIRQ0µÄÖжÏÇëÇóÃèÊö·ûÖйҽӾßÌåµÄÖжϷþÎñÃèÊö·û¡£ÆäÔ´ÂëÈçÏÂËùʾ£¨arch/i386/kernel/
time.c£©£º
void __init time_init(void)
{
extern int x86_udelay_tsc;

xtime.tv_sec = get_cmos_time();
xtime.tv_usec = 0;

/*
* If we have APM enabled or the CPU clock speed is variable
* (CPU stops clock on HLT or slows clock to save power)
* then the TSC timestamps may diverge by up to 1 jiffy from
* 'real time' but nothing will break.
* The most frequent case is that the CPU is "woken" from a halt
* state by the timer interrupt itself, so we get 0 error. In the
* rare cases where a driver would "wake" the CPU and request a
* timestamp, the maximum error is handlerº¯ÊýÖ¸ÕëËùÖ¸ÏòµÄ
timer_interrupt()º¯Êý¶ÔʱÖÓÖжÏÇëÇó½øÐÐÕæÕýµÄ·þÎñ£¬¶ø²»ÊÇÏòÇ°ÃæËù˵µÄÄÇÑùÖ»ÊÇÈÃCPU¡°¿ÕÅÜ¡±Ò»ÌË¡£´Ëʱ£¬LinuxÄں˿É
ÒÔ˵ÊÇÕæÕýµÄ¡°Ìø¶¯¡±ÆðÀ´ÁË¡£
ÔÚ±¾½ÚÒ»¿ªÊ¼ËùÊöµÄ¶ÔʱÖÓÖжÏÇý¶¯µÄ5ÏîÒªÇóÖУ¬Í¨³£Ö»ÓеÚÒ»Ï¼´timekeeping£©ÊÇ×îΪÆÈÇеģ¬Òò´Ë±ØÐëÔÚʱÖÓÖжϷþÎñÀý
³ÌÖÐÍê³É¡£¶øÆäÓàµÄ¼¸¸öÒªÇó¿ÉÒÔÉÔ»º£¬Òò´Ë¿ÉÒÔ·ÅÔÚʱÖÓÖжϵÄBottom HalfÖÐÈ¥Ö´ÐС£ÕâÑù£¬LinuxÄں˾ÍÊÇ
timer_interrupt()º¯ÊýµÄÖ´ÐÐʱ¼ä¾¡¿ÉÄܵĶ̣¬ÒòΪËüÊÇÔÚCPU¹ØÖжϵÄÌõ¼þÏÂÖ´Ðеġ£
º¯Êýtimer_interrupt()µÄÔ´ÂëÈçÏ£¨arch/i386/kernel/time.c£©£º
/*
* This is the same as the above, except we _also_ save the current
* Time Stamp Counter value at the time of the timer interrupt, so that
* we later on can estimate the time of day more exactly.
*/
static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
int count;

/*
* Here we are in the timer irq handler. We just have irqs locally
* disabled but we don't know if the timer_bh is running on the other
* CPU. We need to avoid to SMP race with it. NOTE: we don' t need
* the irq version of write_lock because as just said we have irq
* locally disabled. -arca
*/
write_lock(&xtime_lock);

if (use_tsc)
{
/*
* It is important that these two operations happen almost at
* the same time. We do the RDTSC stuff first, since it's
* faster. To avoid any inconsistencies, we need interrupts
* disabled locally.
*/

/*
* Interrupts are just disabled locally since the timer irq
* has the SA_INTERRUPT flag set. -arca
*/

/* read Pentium cycle counter */

rdtscl(last_tsc_low);

spin_lock(&i8253_lock);
outb_p(0x00, 0x43); /* latch the count ASAP */

count = inb_p(0x40); /* read the latched count */
count |= inb(0x40) last_rtc_update + 660 &&
xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 &&
xtime.tv_usec eflags) || (3 & (regs)->xcs))
¡­¡­
#endif
£¨3£©µ÷ÓÃmark_bh()º¯Êý¼¤»îʱÖÓÖжϵÄBottom HalfÏòÁ¿TIMER_BHºÍTQUEUE_BH£¨×¢Ò⣬TQUEUE_BH½öÔÚÈÎÎñ¶ÓÁÐtq_timer
²»Îª¿ÕµÄÇé¿öϲŻᱻ¼¤»î£©¡£

ÖÁ´Ë£¬Äں˶ÔʱÖÓÖжϵķþÎñÁ÷³ÌÐû¸æ½áÊø£¬ÏÂÃæÎÒÃÇÏêϸ·ÖÎöÒ»ÏÂupdate_process_times()º¯ÊýµÄʵÏÖ¡£

7£®4£®3 ¸üÐÂʱ¼ä¼ÇÕÊÐÅÏ¢¡ª¡ªCPU·ÖʱµÄʵÏÖ
º¯Êýupdate_process_times()±»ÓÃÀ´ÔÚ·¢ÉúʱÖÓÖжÏʱ¸üе±Ç°½ø³ÌÒÔ¼°ÄÚºËÖÐÓëʱ¼äÏà¹ØµÄͳ¼ÆÐÅÏ¢£¬²¢¸ù¾ÝÕâЩÐÅÏ¢×÷³öÏà
Ó¦µÄ¶¯×÷£¬±ÈÈç£ºÖØÐ½øÐе÷¶È£¬Ïòµ±Ç°½ø³Ì·¢³öÐźŵȡ£¸Ãº¯Êý½öÓÐÒ»¸ö²ÎÊýuser_tick£¬È¡ÖµÎª1»ò0£¬Æäº¬ÒåÔÚÇ°ÃæÒѾ­ÐðÊö
¹ý¡£
¸Ãº¯ÊýµÄÔ´´úÂëÈçÏ£¨kernel/timer.c£©£º
/*
* Called from the timer interrupt handler to charge one tick to the current
* process. user_tick is 1 if the tick is user time, 0 for system.
*/
void update_process_times(int user_tick)
{
struct task_struct *p = current;
int cpu = smp_processor_id(), system = user_tick ^ 1;

update_one_process(p, user_tick, system, cpu);
if (p->pid) {
if (--p->counter counter = 0;
p->need_resched = 1;
}
if (p->nice > 0)
kstat.per_cpu_nice[cpu] += user_tick;
else
kstat.per_cpu_user[cpu] += user_tick;
kstat.per_cpu_system[cpu] += system;
} else if (local_bh_count(cpu) || local_irq_count(cpu) > 1)
kstat.per_cpu_system[cpu] += system;
}
£¨1£©Ê×ÏÈ£¬ÓÃsmp_processor_id()ºêµÃµ½µ±Ç°½ø³ÌµÄCPU ID¡£
£¨2£©È»ºó£¬Èþֲ¿±äÁ¿system£½user_tick^1£¬±íʾµ±·¢ÉúʱÖÓÖжÏʱCPUÊÇ·ñÕý´¦ÓÚºËÐÄ̬Ï¡£Òò´Ë£¬Èç¹ûuser_tick=1£¬Ôò
system=0£»Èç¹ûuser_tick£½0£¬Ôòsystem=1¡£
£¨3£©µ÷ÓÃupdate_one_process()º¯ÊýÀ´¸üе±Ç°½ø³ÌµÄtask_struct½á¹¹ÖеÄËùÓÐÓëʱ¼äÏà¹ØµÄͳ¼ÆÐÅÏ¢ÒÔ¼°³ÉÔ±±äÁ¿¡£¸Ãº¯
Êý»¹»áÊÓÐèÒªÏòµ±Ç°½ø³Ì·¢ËÍÏàÓ¦µÄÐźţ¨signal£©¡£
£¨4£©Èç¹ûµ±Ç°½ø³ÌµÄPID·Ç0£¬ÔòÖ´ÐÐÏÂÁв½ÖèÀ´¾ö¶¨ÊÇ·ñÖØÐ½øÐе÷¶È£¬²¢¸üÐÂÄÚºËʱ¼äͳ¼ÆÐÅÏ¢£º
l ½«µ±Ç°½ø³ÌµÄ¿ÉÔËÐÐʱ¼äƬ³¤¶È£¨ÓÉtask_struct½á¹¹ÖеÄcounter³ÉÔ±±íʾ£¬Æäµ¥Î»ÊÇʱÖӵδð´ÎÊý£©¼õ1¡£Èç¹û¼õµ½0Öµ£¬Ôò
˵Ã÷µ±Ç°½ø³ÌÒѾ­ÓÃÍêÁËϵͳ·ÖÅ䏸ËüµÄµÄÔËÐÐʱ¼äƬ£¬Òò´Ë±ØÐëÖØÐ½øÐе÷¶È¡£ÓÚÊǽ«µ±Ç°½ø³ÌµÄtask_struct½á¹¹ÖеÄ
need_resched³ÉÔ±±äÁ¿ÉèÖÃΪ1£¬±íʾÐèÒªÖØÐÂÖ´Ðе÷¶È¡£
l Èç¹ûµ±Ç°½ø³ÌµÄtask_struct½á¹¹ÖеÄnice³ÉÔ±Öµ´óÓÚ0£¬ÄÇô½«ÄÚºËÈ«¾Öͳ¼ÆÐÅÏ¢±äÁ¿kstatÖеÄper_cpu_nice£Ûcpu£ÝÖµ½«
ÉÏuser_tick¡£·ñÔò¾Í½«user_tickÖµ¼Óµ½ÄÚºËÈ«¾Öͳ¼ÆÐÅÏ¢±äÁ¿kstatÖеÄper_cpu_user£Ûcpu£Ý³ÉÔ±ÉÏ¡£
l ½«system±äÁ¿Öµ¼Óµ½ÄÚºËÈ«¾Öͳ¼ÆÐÅÏ¢kstat.per_cpu_system£Ûcpu£ÝÉÏ¡£
£¨5£©·ñÔò£¬¾ÍÅжϵ±Ç°CPUÔÚ·þÎñʱÖÓÖжÏǰÊÇ·ñ´¦ÓÚsoftirqÈíÖжϷþÎñµÄÖ´ÐÐÖУ¬»òÔòÕýÔÚ·þÎñÒ»´ÎµÍÓÅÏȼ¶±ðµÄÓ²¼þÖжÏ
ÖС£Èç¹ûÊÇÕâÑùµÄ»°£¬Ôò½«system±äÁ¿µÄÖµ¼Óµ½ÄÚºËÈ«¾Öͳ¼ÆÐÅÏ¢kstat.per_cpu.system£Ûcpu£ÝÉÏ¡£

l update_one_process()º¯Êý
ʵÏÖÔÚkernel/timer.cÎļþÖеÄupdate_one_process()º¯ÊýÓÃÀ´ÔÚʱÖÓÖжϷ¢Éúʱ¸üÐÂÒ»¸ö½ø³ÌµÄtask_struc½á¹¹ÖеÄʱ¼ä
ͳ¼ÆÐÅÏ¢¡£ÆäÔ´ÂëÈçÏ£¨kernel/timer.c£©£º

void update_one_process(struct task_struct *p, unsigned long user,
unsigned long system, int cpu)
{
p->per_cpu_utime[cpu] += user;
p->per_cpu_stime[cpu] += system;
do_process_times(p, user, system);
do_it_virt(p, user);
do_it_prof(p);
}
×¢ÊÍÈçÏ£º
£¨1£©ÓÉÓÚÔÚÒ»¸ö½ø³ÌµÄÕû¸öÉúÃüÆÚ£¨Lifetime£©ÖУ¬Ëü¿ÉÄÜ»áÔÚ²»Í¬µÄCPUÉÏÖ´ÐУ¬Ò²¼´Ò»¸ö½ø³Ì¿ÉÄÜÒ»¿ªÊ¼ÔÚCPU1ÉÏÖ´ÐУ¬µ±
ËüÓÃÍêÔÚCPU1ÉϵÄÔËÐÐʱ¼äƬºó£¬Ëü¿ÉÄÜÓֻᱻµ÷¶Èµ½CPU2ÉÏÈ¥Ö´ÐС£ÁíÍ⣬µ±½ø³ÌÔÚij¸öCPUÉÏÖ´ÐÐʱ£¬Ëü¿ÉÄÜÓÖ»áÔÚÓû§Ì¬ºÍ
ÄÚºË̬Ï·ֱð¸÷Ö´ÐÐÒ»¶Îʱ¼ä¡£ËùÒÔΪÁËͳ¼ÆÕâЩʼþÐÅÏ¢£¬½ø³Ìtask_struct½á¹¹ÖеÄper_cpu_utime£ÛNR_CPUS£ÝÊý×é¾Í±íʾ
¸Ã½ø³ÌÔÚ¸÷CPUµÄÓû§Ì¨ÏÂÖ´ÐеÄÀÛ¼ÆÊ±¼ä³¤¶È£¬per_cpu_stime£ÛNR_CPUS£ÝÊý×é¾Í±íʾ¸Ã½ø³ÌÔÚ¸÷CPUµÄºËÐÄ̬ÏÂÖ´ÐеÄÀÛ¼ÆÊ±
¼ä³¤¶È£»ËüÃǶ¼ÒÔʱÖӵδð´ÎÊýΪµ¥Î»¡£
ËùÒÔ£¬update_one_process()º¯ÊýµÄµÚÒ»¸ö²½Öè¾ÍÊǸüнø³ÌÔÚµ±Ç°CPUÉϵÄÓû§Ì¬Ö´ÐÐʱ¼äͳ¼Æper_cpu_utime£Ûcpu£ÝºÍºË
ÐÄִ̬ÐÐʱ¼äͳ¼Æper_cpu_stime£Ûcpu£Ý¡£
£¨2£©µ÷ÓÃdo_process_times()º¯Êý¸üе±Ç°½ø³ÌµÄ×Üʱ¼äͳ¼ÆÐÅÏ¢¡£
£¨3£©µ÷ÓÃdo_it_virt()º¯ÊýΪµ±Ç°½ø³ÌµÄITIMER_VIRTUALÈí¼þ¶¨Ê±Æ÷¸üÐÂʱ¼ä¼ä¸ô¡£
£¨4£©µ÷ÓÃdo_it_prof£¨£©º¯ÊýΪµ±Ç°½ø³ÌµÄITIMER_PROFÈí¼þ¶¨Ê±Æ÷¸üÐÂʱ¼ä¼ä¸ô¡£

l do_process_times()º¯Êý
º¯Êýdo_process_times()½«¸üÐÂÖ¸¶¨½ø³ÌµÄ×Üʱ¼äͳ¼ÆÐÅÏ¢¡
 3/7   |‹ ‹‹ 1 2 3 4 5 6 ›› ›|

À´¶¥Ò»ÏÂ
½ü»ØÊ×Ò³
·µ»ØÊ×Ò³
·¢±íÆÀÂÛ ¹²ÓÐÌõÆÀÂÛ
Óû§Ãû: ÃÜÂë:
ÑéÖ¤Âë: ÄäÃû·¢±í
Ïà¹ØÎÄÕÂ
    ÎÞÏà¹ØÐÅÏ¢
À¸Ä¿¸üÐÂ
À¸Ä¿ÈÈÃÅ