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

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

ホスト名とsetns


本内容は、SETNSについてです。

newuts.cは、CLONE_NEWUTSで、親プロセスと異なるネームスペースの子プロセスを作成し、この子プロセスにsethostname()でホスト名(コマンド引数)を設定する事で、デフォルトの親プロセスのホスト名(localhost.localdomain)と子プロセスのホスト名(babakaka)のホスト名を有する環境となります。

シェルから起動されたプロセスは、ネームスペースの変更がない限り、親シェルのネームスペースのlocalhost.localdomainを継承しますが、このシェル下でbabakakaのプロセスのネームスペースをsetns()で更新後、execしたbashは、localhost.localdomaiでなくbabakakaとなります。

newuts.c
#define _GNU_SOURCE
#include <sys/wait.h>
#include <sys/utsname.h>
#include <sched.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define errExit(msg)    do { perror(msg); exit(EXIT_FAILURE); \
                       } while (0)

static int        childFunc(void *arg)
{
   struct utsname uts;

   if (sethostname(arg, strlen(arg)) == -1)
       errExit("sethostname");

   if (uname(&uts) == -1)
       errExit("uname");
   printf("uts.nodename in child:  %s\n", uts.nodename);

   sleep(200);
   return 0;
}

#define STACK_SIZE (1024 * 1024)    /* clone される子プロセスのスタックサイズ */

int  main(int argc, char *argv[])
{
   char *stack;
   char *stackTop;
   pid_t pid;
   struct utsname uts;

   if (argc < 2) {
       fprintf(stderr, "Usage: %s <child-hostname>\n", argv[0]);
       exit(EXIT_SUCCESS);
   }

   stack = malloc(STACK_SIZE);
   if (stack == NULL)
       errExit("malloc");
   stackTop = stack + STACK_SIZE;

   pid = clone(childFunc, stackTop, CLONE_NEWUTS | SIGCHLD, argv[1]);
   if (pid == -1)
       errExit("clone");
   printf("clone() returned %ld\n", (long) pid);

   sleep(1);

   if (uname(&uts) == -1)
       errExit("uname");
   printf("uts.nodename in parent: %s\n", uts.nodename);

   if (waitpid(pid, NULL, 0) == -1)
       errExit("waitpid");
   printf("child has terminated\n");

   exit(EXIT_SUCCESS);
}

setns.c
#define _GNU_SOURCE
#include <fcntl.h>
#include <sched.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

#define errExit(msg)    do { perror(msg); exit(EXIT_FAILURE); \
                       } while (0)

int
main(int argc, char *argv[])
{
   int fd;

   if (argc < 3) {
       fprintf(stderr, "%s /proc/PID/ns/FILE cmd args...\n", argv[0]);
       exit(EXIT_FAILURE);
   }

   fd = open(argv[1], O_RDONLY);  /* 名前空間のディスクリプターを取得 */
   if (fd == -1)
       errExit("open");

   if (setns(fd, 0) == -1)        /* 名前空間に参加 */
       errExit("setns");

   execvp(argv[2], &argv[2]);     /* 名前空間内でコマンドを実行 */
   errExit("execvp");
}

実効結果

子プロセスIDは2270でホスト名はbabakakaで、シェルとする親プロセスIDは2269でホスト名はlocalhost.localdomainです。
[root@localhost test]# ./newuts babakaka &
[1] 2269
[root@localhost test]# clone() returned 2270
uts.nodename in child:  babakaka
uts.nodename in parent: localhost.localdomain

[root@localhost test]# uname -n
localhost.localdomain
[root@localhost test]# ./setns /proc/2270/ns/uts /bin/bash
[root@babakaka test]# uname -n
babakaka

[root@localhost test]# ./setns /proc/2269/ns/uts /bin/bash
[root@babakaka test]# uname -n
localhost.localdomain

[root@localhost test]# exit
exit
[root@babakaka test]# uname -n
babakaka

[root@babakaka test]# exit
exit
[root@localhost test]# uname -n
localhost.localdomain

追記

ネームスペースはcurrent->nsproxyに設定され、ホスト名は、current->nsproxy->uts_ns->nameに設定されます。ホスト名はネームスペース名という事です。


最終更新 2015/09/30 16:59:34 - north
(2015/09/30 16:39:33 作成)