fork/join copying

This commit is contained in:
Jake Hillion 2021-12-13 13:33:22 +00:00
parent c88fabdf2f
commit 817328f03f
2 changed files with 148 additions and 1 deletions

View File

@ -1,6 +1,6 @@
C=clang C=clang
all: c ml all: c c_cgroup ml
clean: clean:
rm -f c ml rm -f c ml
@ -8,6 +8,9 @@ clean:
c: cp.c c: cp.c
${C} -o c cp.c ${C} -o c cp.c
c_cgroup: cp_cgroup.c
${C} -o c_cgroup cp_cgroup.c
ml: cp.ml ml: cp.ml
opam switch default opam switch default
ocamlopt -o ml cp.ml ocamlopt -o ml cp.ml

144
examples/cp/cp_cgroup.c Normal file
View File

@ -0,0 +1,144 @@
#define _GNU_SOURCE
#include <fcntl.h>
#include <sched.h>
#include <signal.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#define IO_BLOCK_SIZE 4096
/*
* Get size of regular file or error otherwise.
*/
off_t get_file_size(int fd) {
struct stat st;
if (fstat(fd, &st) < 0) {
perror("fstat");
return -1;
}
if (S_ISREG(st.st_mode)) {
return st.st_size;
} else {
return -1;
}
}
/*
* Move self to a leaf node of the cgroup.
*/
int leaf_self() {}
/*
* Perform the copy between the two file descriptors.
*/
int copy(int src_fd, int dst_fd) {
off_t src_len;
int passwd_fd;
if ((passwd_fd = open("/home/jake/plot", O_RDONLY)) == -1) {
perror("open 2");
return 1;
} else {
// TODO: Debug this
fprintf(stderr, "opened second file successfully\n");
}
if ((src_len = get_file_size(src_fd)) == -1) {
return 1;
}
char buf[IO_BLOCK_SIZE];
off_t blocks =
(src_len / IO_BLOCK_SIZE) + ((src_len % IO_BLOCK_SIZE) > 0 ? 1 : 0);
for (off_t i = 0; i < blocks; i++) {
off_t len;
if (i == blocks - 1 && src_len % IO_BLOCK_SIZE != 0) {
len = src_len % IO_BLOCK_SIZE;
} else {
len = IO_BLOCK_SIZE;
}
if (read(src_fd, &buf, len) == -1) {
perror("read");
return -1;
};
if (write(dst_fd, &buf, len) == -1) {
perror("write");
return -1;
}
}
return 0;
}
int main(int argc, char **argv) {
if (argc != 3) {
fprintf(stderr, "usage: %s <src> <dst>\n", argv[0]);
return 1;
}
int src_fd, dst_fd;
if ((src_fd = open(argv[1], O_RDONLY)) == -1) {
perror("open");
return 1;
}
if ((dst_fd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1) {
perror("open");
return 1;
}
// all necessary files opened, drop filesystem
// if (unshare(CLONE_FS) == -1) {
// perror("unshare");
// return -1;
// }
// fork and copy in a second process
pid_t child_pid = fork();
if (child_pid == -1) {
perror("fork");
return -1;
} else if (child_pid == 0) {
// pause(); // await cgroup setup
raise(SIGSTOP); // await cgroup setup
return copy(src_fd, dst_fd);
}
// setup a cgroup for the child
// wait for the child to pause and restart it
int status;
if (waitpid(child_pid, &status, WUNTRACED | WSTOPPED) == -1) {
perror("waitpid");
return -1;
}
if (WIFSTOPPED(status)) {
if (kill(child_pid, SIGCONT) == -1) {
perror("kill");
return -1;
}
} else {
fprintf(stderr, "child behaved unexpectedly\n");
return -1;
}
// wait for the child process to terminate
if (waitpid(child_pid, &status, 0) == -1) {
perror("waitpid");
return -1;
}
if (WIFEXITED(status)) {
return WEXITSTATUS(status);
}
return -1;
}