Created
January 3, 2024 04:51
-
-
Save Guaderxx/ae3bb57bdb0d571ce2009a3a15fef15a to your computer and use it in GitHub Desktop.
clone(2) Example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _GNU_SOURCE | |
#include <sys/wait.h> | |
#include <sys/utsname.h> | |
#include <sched.h> | |
#include <string.h> | |
#include <stdint.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 /* start function for cloned child */ | |
childFunc(void *arg) | |
{ | |
struct utsname uts; | |
/* Change hostname in UTS namespace of child */ | |
if (sethostname(arg, strlen(arg)) == -1) | |
errExit("sethostname"); | |
/* Retrieve and display hostname */ | |
if (uname(&uts) == -1) | |
errExit("uname"); | |
printf("uts.nodename in child: %s\n", uts.nodename); | |
/* Keep the namespace open for a while, by sleeping. | |
This allows some experimentation -- for example, | |
another process might join the namespace. */ | |
sleep(200); | |
return 0; /* Child terminates now */ | |
} | |
#define STACK_SIZE (1024 * 1024) /* Stack size for cloned child */ | |
int | |
main(int argc, char *argv[]) | |
{ | |
char *stack; /* Start of stack buffer */ | |
char *stackTop; /* End of stack buffer */ | |
pid_t pid; | |
struct utsname uts; | |
if (argc < 2) { | |
fprintf(stderr, "Usage: %s <child-hostname>\n", argv[0]); | |
exit(EXIT_SUCCESS); | |
} | |
/* Allocate memory to be used for the stack of the child */ | |
stack = mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE, | |
MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); | |
if (stack == MAP_FAILED) | |
errExit("mmap"); | |
stackTop = stack + STACK_SIZE; /* Assume stack grows downward */ | |
/* Create child that has its own UTS namespace; | |
child commences execution in childFunc() */ | |
pid = clone(childFunc, stackTop, CLONE_NEWUTS | SIGCHLD, argv[1]); | |
if (pid == -1) | |
errExit("clone"); | |
printf("clone() returned %jd\n", (intmax_t) pid); | |
/* Parent falls through to here */ | |
sleep(1); /* Give child time to change its hostname */ | |
/* Display hostname in parent's UTS namespace. | |
This will be different from hostname in child's UTS namespace. */ | |
if (uname(&uts) == -1) | |
errExit("uname"); | |
printf("uts.nodename in parent: %s\n", uts.nodename); | |
if (waitpid(pid, NULL, 0) == -1) /* Wait for child */ | |
errExit("waitpid"); | |
printf("child has terminated\n"); | |
exit(EXIT_SUCCESS); /* Child has already called exit() */ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment