無料Wikiサービス | デモページ
検索

アクセス数
最近のコメント
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
はじめ - ノース
はじめ - ノース
はじめ - 楽打連動ユーザー
はじめ - 楽打連動ユーザー
Adsense
広告情報が設定されていません。

uname


unameコマンドはシステム情報の表示をします。私の環境では以下の通りです。
[root@localhost test]# uname -a
Linux localhost.localdomain 3.3.8-1.fc16.i686 #1 SMP Mon Jun 4 21:30:50 UTC 2012 i686 i686 i386 GNU/Linux
unameコマンドはシステムコールの122(ただし、i386の場合で他のシステムは異なっています。それ故下記サンプルが動作しなくて悩みました。)また、システムの応じて3つのフォーマットを有しています。
struct oldold_utsname {
       char sysname[9];
       char nodename[9];
       char release[9];
       char version[9];
       char machine[9];
};

#define __NEW_UTS_LEN 64

struct old_utsname {
       char sysname[65];
       char nodename[65];
       char release[65];
       char version[65];
       char machine[65];
};

struct new_utsname {
       char sysname[65];
       char nodename[65];
       char release[65];
       char version[65];
       char machine[65];
       char domainname[65];
};

asmlinkage int sys_uname(struct old_utsname __user * name)
{
       int err;
       if (!name)
               return -EFAULT;
       down_read(&uts_sem);
       err=copy_to_user(name, &system_utsname, sizeof (*name));
       up_read(&uts_sem);
       return err?-EFAULT:0;
}
sys_uname()は、system_utsnameを返すだけでが、unameコマンドはglibを介しての処理で、下記サンプルは、直接システムコールを通しての私の環境での結果です。
#include <stdio.h>

struct new_utsname {
       char sysname[65];
       char nodename[65];
       char release[65];
       char version[65];
       char machine[65];
       char domainname[65];
} ;

void    main()
{
       struct new_utsname *tmp, utsname;

       tmp = &utsname;

       __asm__("movl $122, %%eax;\n\t"
               "int $0x80"
               :
               :"b"(tmp)
               );:q

       printf("sysname   :%s\n", utsname.sysname);
       printf("nodename  :%s\n", utsname.nodename);
       printf("release   :%s\n", utsname.release);
       printf("version   :%s\n", utsname.version);
       printf("machine   :%s\n", utsname.machine);
       printf("domainname:%s\n", utsname.domainname);
}

[root@localhost test]# ./a.out
sysname   :Linux
nodename  :localhost.localdomain
release   :3.3.8-1.fc16.i686
version   :#1 SMP Mon Jun 4 21:30:50 UTC 2012
machine   :i686
domainname:(none)
system_utsnameは以下のマクロで初期化されています。UTS_RELEASEはカーネルのMakefileのVERSION+PATCHLEVEL+SUBLEVEL+EXTRAVERSION、またUTS_MACHINEもmakefie下で定義されてます。そしてUTS_VERSIONは/usr/src/linux/include/generated/utsrelease.h(カーネルコンパイル時に生成される。)で設定されます。カーネルモジュールのマジック番号(その1)参照
#ifndef UTS_SYSNAME
#define UTS_SYSNAME "Linux"
#endif

#ifndef UTS_NODENAME
#define UTS_NODENAME "(none)"   /* set by sethostname() */
#endif

#ifndef UTS_DOMAINNAME
#define UTS_DOMAINNAME "(none)" /* set by setdomainname() */
#endif

struct new_utsname system_utsname = {
       .sysname        = UTS_SYSNAME
       .nodename       = UTS_NODENAME
       .release        = UTS_RELEASE
       .version        = UTS_VERSION
       .machine        = UTS_MACHINE
       .domainname     = UTS_DOMAINNAME
};
.nodename/.domainnameはIPアドレスの設定時に設定されるようです。IPアドレス設定時にコールされるip_auto_config_setup()で、設定されるようです。なおnfsaddrs_config_setup()からも、ip_auto_config_setup()をコールしていますが、これはnfsをルートファイルシステムとするケースだと思います。

ip_auto_config_setup()で:をデリミタとする以下の最大6つの項目のaddrsから、ネットワーク設定値を取得し、このホスト名がnodenameに設定されます。
addrs=ローカルアドレス:サーバアドレス:ゲートウエイ:ネットマスク:ホスト名:デバイス名:プロトコル名
(プロトコル名はon/any/dhcp/bootp/rarp/bothのいずれか。ただしコンパイルオプションによる。)
static int __init ip_auto_config_setup(char *addrs)
{
       char *cp, *ip, *dp;
       int num = 0;

       ic_set_manually = 1;

       ic_enable = (*addrs && 
               (strcmp(addrs, "off") != 0) && 
               (strcmp(addrs, "none") != 0));
       if (!ic_enable)
               return 1;

       if (ic_proto_name(addrs))
               return 1;

       /* Parse the whole string */
       ip = addrs;
       while (ip && *ip) {
               if ((cp = strchr(ip, ':')))
                       *cp++ = '\0';
               if (strlen(ip) > 0) {
                       DBG(("IP-Config: Parameter #%d: `%s'\n", num, ip));
                       switch (num) {
                       case 0:
                               if ((ic_myaddr = in_aton(ip)) == INADDR_ANY)
                                       ic_myaddr = INADDR_NONE;
                               break;
                       case 1:
                               if ((ic_servaddr = in_aton(ip)) == INADDR_ANY)
                                       ic_servaddr = INADDR_NONE;
                               break;
                       case 2:
                               if ((ic_gateway = in_aton(ip)) == INADDR_ANY)
                                       ic_gateway = INADDR_NONE;
                               break;
                       case 3:
                               if ((ic_netmask = in_aton(ip)) == INADDR_ANY)
                                       ic_netmask = INADDR_NONE;
                               break;
                       case 4:
                               if ((dp = strchr(ip, '.'))) {
                                       *dp++ = '\0';
                                       strlcpy(system_utsname.domainname, dp,
                                               sizeof(system_utsname.domainname));
                               }
                               strlcpy(system_utsname.nodename, ip,
                                       sizeof(system_utsname.nodename));
                               ic_host_name_set = 1;
                               break;
                       case 5:
                               strlcpy(user_dev_name, ip, sizeof(user_dev_name));
                               break;
                       case 6:
                               ic_proto_name(ip);
                               break;
                       }
               }
               ip = cp;
               num++;
       }

       return 1;
}

static int __init nfsaddrs_config_setup(char *addrs)
{
       return ip_auto_config_setup(addrs);
}

__setup("ip=", ip_auto_config_setup);
__setup("nfsaddrs=", nfsaddrs_config_setup);
__setupマクロは以下の様に定義され、
struct obs_kernel_param {
       const char *str;
       int (*setup_func)(char *);
}

#define __init __attribute__ ((__section__ (".text.init")))

#define __setup(str, fn)                                        \
       static char __setup_str_##fn[] __initdata = str;        \
       static struct obs_kernel_param __setup_##fn             \
                __attribute_used__                             \
                __attribute__((__section__(".init.setup")))    \
               = { __setup_str_##fn, fn }


#define module_init(initfn)                                     \
       static inline initcall_t __inittest(void)               \
       { return initfn; }                                      \
       int init_module(void) __attribute__((alias(#initfn)));

[root@localhost test]# cat hogehoge.c
static int __init hogehoge(void)
{
}

__setup("ip=", hogehoge);


[root@localhost test]# gcc -E hogehoge.c
# 1 "hogehoge.c"
# 1 "<組み込み>"
# 1 "<コマンドライン>"
# 1 "hogehoge.c"
typedef int (*initcall_t)(void);
# 18 "hogehoge.c"
static int __attribute__ ((__section__ (".text.init"))) hogehoge(void)
{
}

static char __setup_str_hogehoge[] __initdata = "ip="; 
static struct obs_kernel_param __setup_hogehoge __attribute_used__ __attribute__((__section__(".init.setup"))) = {  __setup_str_hogehoge, hogehoge };
.init.setupセクションに、struct obs_kernel_param構造体として、__setup_str_hogehoge/hogehogeが配置されます。__setup_str_hogehogeは引数の"ip="で、hogehogeが関数となるわけです。

補足

sysnameはデフォルトのLinux以外に、SunOS/HP-UXがあるようです。
推測ですが、__setup("ip=", ip_auto_config_setup);としてのコールは、カーネル起動時、/etc/sysconfig/networkの内容をip=:::::と編集してコールされるのではと思います。

最終更新 2013/05/14 19:56:15 - north
(2013/05/14 19:47:11 作成)