1. 코드 분석
1. tlpi-dist/namespace/ns_child_exec.c
1. 코드
#define _GNU_SOURCE
#include <sched.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdio.h>
#include <sys/mman.h>
#ifndef CLONE_NEWCGROUP
#define CLONE_NEWCGROUP 0x02000000
#endif
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \
} while (0)
static void
usage(char *pname)
{
fprintf(stderr, "Usage: %s [options] cmd [arg...]\n", pname);
fprintf(stderr, "Options can be:\n");
fprintf(stderr, " -C new cgroup namespace\n");
fprintf(stderr, " -i new IPC namespace\n");
fprintf(stderr, " -m new mount namespace\n");
fprintf(stderr, " -n new network namespace\n");
fprintf(stderr, " -p new PID namespace\n");
fprintf(stderr, " -u new UTS namespace\n");
fprintf(stderr, " -U new user namespace\n");
fprintf(stderr, " -v Display verbose messages\n");
exit(EXIT_FAILURE);
}
static int
childFunc(void *arg)
{
char **argv = arg;
execvp(argv[0], argv);
errExit("execvp");
}
#define STACK_SIZE (1024 * 1024)
int
main(int argc, char *argv[])
{
int flags = 0;
int verbose = 0;
int opt;
while ((opt = getopt(argc, argv, "+CimnpuUv")) != -1) {
switch (opt) {
case 'C': flags |= CLONE_NEWCGROUP; break;
case 'i': flags |= CLONE_NEWIPC; break;
case 'm': flags |= CLONE_NEWNS; break;
case 'n': flags |= CLONE_NEWNET; break;
case 'p': flags |= CLONE_NEWPID; break;
case 'u': flags |= CLONE_NEWUTS; break;
case 'U': flags |= CLONE_NEWUSER; break;
case 'v': verbose = 1; break;
default: usage(argv[0]);
}
}
if (optind >= argc)
usage(argv[0]);
char *stack = mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
if (stack == MAP_FAILED)
errExit("mmap");
pid_t child_pid = clone(childFunc,
stack + STACK_SIZE,
flags | SIGCHLD, &argv[optind]);
if (child_pid == -1)
errExit("clone");
if (verbose)
printf("%s: PID of child created by clone() is %ld\n",
argv[0], (long) child_pid);
munmap(stack, STACK_SIZE);
if (waitpid(child_pid, NULL, 0) == -1)
errExit("waitpid");
if (verbose)
printf("%s: terminating\n", argv[0]);
exit(EXIT_SUCCESS);
}
2. 동작 모습

3. 디버깅 및 분석
2. tlpi-dist/namespace/demo_uts_namespaces.c
1. 코드
#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>
#include <sys/mman.h>
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \
} while (0)
static int
childFunc(void *arg)
{
if (sethostname(arg, strlen(arg)) == -1)
errExit("sethostname");
struct utsname uts;
if (uname(&uts) == -1)
errExit("uname");
printf("uts.nodename in child: %s\n", uts.nodename);
sleep(1000);
return 0;
}
#define STACK_SIZE (1024 * 1024)
int
main(int argc, char *argv[])
{
if (argc < 2) {
fprintf(stderr, "Usage: %s <child-hostname>\n", argv[0]);
exit(EXIT_SUCCESS);
}
char *stack = mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
if (stack == MAP_FAILED)
errExit("mmap");
pid_t child_pid = clone(childFunc,
stack + STACK_SIZE,
CLONE_NEWUTS | SIGCHLD, argv[1]);
if (child_pid == -1)
errExit("clone");
printf("PID of child created by clone() is %ld\n", (long) child_pid);
munmap(stack, STACK_SIZE);
sleep(1);
struct utsname uts;
if (uname(&uts) == -1)
errExit("uname");
printf("uts.nodename in parent: %s\n", uts.nodename);
if (waitpid(child_pid, NULL, 0) == -1)
errExit("waitpid");
printf("child has terminated\n");
exit(EXIT_SUCCESS);
}
2. 동작 모습

3. 디버깅 및 분석