VMware の時計あわせ


WindowsXP上のVMware 4.5 で linux を動かしていると,どんどん時計が遅れる.いや時計はほとんど進まなくなる. vmware-toolbox を起動しておけば時計を合わせてくれるのだけど,vmware-toolbox はX用のアプリなのでコンソールonlyな環境だとそもそも起動できない.そこで,コンソール版の時計あわせプログラムを作成する.


google で検索すると VMware を解析しておられる方がいるようで,以下のようにあるアドレスのIOポート叩けばホストの時計を参照することができるとのこと.と言うわけで早速プログラム作成.

/**
 *  vmware-sync-time.c
 *
 */
#include <stdio.h>
#include <sys/time.h>
#include <errno.h>

int 
get_host_time(long *sec, long *usec)
{
    int eax, ebx, ecx, edx;
    __asm__  __volatile__ ("
        mov $0x564D5868, %%eax; /* magic number */
        mov $0x00000000, %%ebx; /* ebx will be ignored */
        mov $0x00000017, %%ecx; /* command. 17h is for getting time.*/
        mov $0x5658, %%edx;     /* VMware I/O port */

        in %%dx, %%eax;

        mov %%eax, %0;
        mov %%ebx, %1;
        mov %%ecx, %2;
        mov %%edx, %3;
        "
        : "=r"(eax), "=r"(ebx), "=r"(ecx), "=r"(edx)
        );

    *sec  = eax;
    *usec = ebx;
    return 0;
}

int 
main(int argc, char argv[])
{
    struct timeval tv;

    get_host_time(&tv.tv_sec, &tv.tv_usec);
    
    if (0 != settimeofday(&tv, NULL)){
        perror("can not set system time.");
    }

    return 0;
}

gccインラインアセンブラには不慣れながら,なんとか完成に至る.


で,このプログラムをcrontabで数分おきに起動すれば万事解決と思いきや…そもそもシステムの時計がほとんど進まないので,crontabの起動も遅れることが発覚.orz

int 
main(int argc, char argv[])
{
   while (!0){
     struct timeval tv;
     get_host_time(&tv.tv_sec, &tv.tv_usec);

     if (0 != settimeofday(&tv, NULL)){
        perror("can not set system time.");
     }

     usleep(10*1000);
   }
   return 0;
}

で,こうなった.うーん,ださい.カーネルソースいじったほうがスマートなんだろうなぁ.

VMware徹底入門 (DVD付)
VMware徹底入門 (DVD付)
posted with amazlet at 09.01.10
ヴイエムウェア株式会社
翔泳社
売り上げランキング: 3586
おすすめ度の平均: 5.0
5 実践的なノウハウがよい